diff --git a/harbour/ChangeLog b/harbour/ChangeLog index ad4c701782..fa134bd022 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -17,6 +17,136 @@ past entries belonging to author(s): Viktor Szakats. */ +2009-10-23 09:24 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) + * harbour/src/rdd/dbfnsx/dbfnsx1.c + ! fixed bug reported by Jaroslav Janik (many thanks) - if index FOR + expression excluded all records from non empty table then root page + was not initialized and DBFNSX generated corruption RTE. + + * harbour/utils/hbi18n/hbi18n.prg + * set default GT to CGI + + * harbour/src/common/hbgete.c + ! fixed memory leak in non UNICODE Windows hb_getenv_buffer() + ! add C stack buffers to eliminate memory allocation in UNICODE + Windows hb_getenv_buffer() - they are used if envvar name and + passed buffer are not too large. It fixes HB_FM_STATISTICS + Windows builds. + + * harbour/contrib/hbwin/wapi_winuser.c + + added WAPI_DESTROYWINDOW function + + * harbour/contrib/xhb/traceprg.prg + * harbour/contrib/xhb/hbcompat.ch + ! fixed typo in TraceLog() condition - was always disabled + + added emulation for xHarbour Set( _SET_TRACE* [, ] ) + settings + + * harbour/src/vm/hvmall.c + ! define _GNU_SOURCE to fix compilation with HB_FM_DL_ALLOC in Linux + builds + + * harbour/include/hbdefs.h + * declare HB_FOFFSET as LONG instead of LONGLONG on platforms where + LONG is 64bit integer to be compatible with C RTL file API + + * harbour/src/vm/maindllh.c + * harbour/src/vm/maindllp.c + * harbour/contrib/hbct/ctstr.c + ! casting in HB_TRACE() massages + + * harbour/include/hbapi.h + * harbour/include/hbapiitm.h + * harbour/src/vm/arrays.c + * harbour/src/vm/hashes.c + * harbour/src/vm/itemapi.c + + added hb_arrayCloneTo(), hb_hashCloneTo(), hb_itemCloneTo() + + * harbour/src/vm/arrayshb.c + * harbour/src/vm/classes.c + * harbour/src/vm/hashes.c + * harbour/src/vm/hashfunc.c + * harbour/src/vm/hvm.c + % use hb_*CloneTo() instead of hb_*Clone() + + * harbour/include/hbapi.h + * harbour/src/vm/garbage.c + - removed hb_gcRegisterSweep() function and support for user defined + sweep mark functions in GC blocks + - removed hb_gcAlloc() function + + added new function hb_gcAllocate() which work in similar way to removed + hb_gcAlloc() function but it accepts as second parameter HB_GC_FUNCS + structure instead of HB_GARBAGE_FUNC_PTR and returned GC blocks are + locked so programmer does not have to worry that they can be removed + by GC. + + added new internal function hb_gcAllocRaw() which works like + hb_gcAllocate() but returned GC blocks are not locked. They can + be used only in HVM in places well known that cannot activate + automatic GC scan. It should not be used by 3-rd party code. + + * harbour/include/hbapi.h + * harbour/include/hbapiitm.h + * harbour/src/vm/extend.c + * harbour/src/vm/itemapi.c + * modified hb_parptrGC(), hb_parvptrGC(), hb_arrayGetPtrGC(), + hb_itemGetPtrGC() functions to use HB_GC_FUNCS structure instead + of HB_GARBAGE_FUNC_PTR + * modified hb_itemPutPtrGC() and indirectly related functions like + hb_arraySetPtrGC() or hb_stor[v]ptrGC() to automatically unlock + passed GC block just after attaching to known HVM item. + + * harbour/include/hbregex.h + * harbour/src/rtl/hbregexc.c + * declare GC block detractor as static function + + added hb_regexIs() function + * updated to work with new GC API + * removed unnecessary in new GC API hb_gcLock() call - GC blocks + allocated by hb_gcAllocate() are already locked and they mustn't + be locked explicitly by programmer (until he does not exactly knows + what he does ;)) + + * harbour/src/rtl/hbregex.c + * use hb_regexIs() instead of using regex GC destructor + * removed unnecessary in new GC API hb_gcUnlock() call - GC blocks + stored in HB_IT_POINTER item are automatically unlocked + + * harbour/src/rtl/hbinet.c + * harbour/contrib/hbcurl/hbcurl.c + * updated to work with new GC API + % unlock items storing callback codeblocks and use GC mark functions + to mark them as used in GC passes + + * harbour/src/pp/pplib.c + * harbour/src/vm/runner.c + * harbour/src/vm/codebloc.c + * harbour/src/vm/hashes.c + * harbour/src/vm/hvm.c + * harbour/src/vm/arrays.c + * harbour/src/vm/thread.c + * harbour/src/vm/dynlibhb.c + * harbour/src/rtl/hbzlibgz.c + * harbour/src/rtl/hbregex.c + * harbour/src/rtl/hbregexc.c + * harbour/src/rtl/hbgtcore.c + * harbour/src/rtl/hbi18n1.c + * harbour/src/rdd/wacore.c + * harbour/contrib/hbsqlit3/hbsqlit3.c + * harbour/contrib/hbnetio/netiosrv.c + * harbour/contrib/hbmzip/hbmzip.c + * harbour/contrib/hbhpdf/harupdf.c + * harbour/contrib/hbwin/olecore.c + * harbour/contrib/hbwin/win_prn1.c + * harbour/contrib/hbwin/win_dll.c + * updated code which was using hb_gcAlloc() to work with new GC API. + + * harbour/contrib/hbwin/axcore.c + * updated syntax description + + TODO: update contrib code: hbqt, hbssl, ... to work with new GC API. + I would like to ask authors of above libraries to do it. + TODO: defined when and how we should free AX control and user callback + handler and update AX code to respect new definition + 2009-10-23 09:08 UTC+0200 Viktor Szakats (harbour.01 syenar.hu) + hbqt/qtgui/qtguis + hbqt/qtgui/qtguis/Makefile diff --git a/harbour/contrib/hbct/ctstr.c b/harbour/contrib/hbct/ctstr.c index 967aea3a55..145fe987c2 100644 --- a/harbour/contrib/hbct/ctstr.c +++ b/harbour/contrib/hbct/ctstr.c @@ -81,8 +81,8 @@ const char *ct_at_exact_forward( const char *pcString, size_t sStrLen, size_t sPos; - HB_TRACE( HB_TR_DEBUG, ( "ct_at_exact_forward (\"%s\", %u, \"%s\", %u, %p)", - pcString, sStrLen, pcMatch, sMatchLen, psMatchStrLen ) ); + HB_TRACE( HB_TR_DEBUG, ( "ct_at_exact_forward (\"%s\", %lu, \"%s\", %lu, %p)", + pcString, ( ULONG ) sStrLen, pcMatch, ( ULONG ) sMatchLen, psMatchStrLen ) ); if( ( sMatchLen == 0 ) || ( sStrLen < sMatchLen ) ) return NULL; @@ -112,8 +112,8 @@ const char *ct_at_exact_backward( const char *pcString, size_t sStrLen, size_t sIndex; const char *pcRet; - HB_TRACE( HB_TR_DEBUG, ( "ct_at_exact_backward (\"%s\", %u, \"%s\", %u, %p)", - pcString, sStrLen, pcMatch, sMatchLen, psMatchStrLen ) ); + HB_TRACE( HB_TR_DEBUG, ( "ct_at_exact_backward (\"%s\", %lu, \"%s\", %lu, %p)", + pcString, ( ULONG ) sStrLen, pcMatch, ( ULONG ) sMatchLen, psMatchStrLen ) ); if( ( sMatchLen == 0 ) || ( sStrLen < sMatchLen ) ) return NULL; @@ -147,8 +147,8 @@ const char *ct_at_wildcard_forward( const char *pcString, size_t sStrLen, size_t sIndex; const char *pcRet, *pcStop; - HB_TRACE( HB_TR_DEBUG, ( "ct_at_wildcard_forward (\"%s\", %u, \"%s\", %u, \'%c\', %p)", - pcString, sStrLen, pcMatch, sMatchLen, cWildCard, psMatchStrLen ) ); + HB_TRACE( HB_TR_DEBUG, ( "ct_at_wildcard_forward (\"%s\", %lu, \"%s\", %lu, \'%c\', %p)", + pcString, ( ULONG ) sStrLen, pcMatch, ( ULONG ) sMatchLen, cWildCard, psMatchStrLen ) ); if( ( sMatchLen == 0 ) || ( sStrLen < sMatchLen ) ) return NULL; @@ -186,8 +186,8 @@ const char *ct_at_wildcard_backward( const char *pcString, size_t sStrLen, size_t sIndex; const char *pcRet; - HB_TRACE( HB_TR_DEBUG, ( "ct_at_wildcard_backward (\"%s\", %u, \"%s\", %u, \'%c\', %p)", - pcString, sStrLen, pcMatch, sMatchLen, cWildCard, psMatchStrLen ) ); + HB_TRACE( HB_TR_DEBUG, ( "ct_at_wildcard_backward (\"%s\", %lu, \"%s\", %lu, \'%c\', %p)", + pcString, ( ULONG ) sStrLen, pcMatch, ( ULONG ) sMatchLen, cWildCard, psMatchStrLen ) ); if( ( sMatchLen == 0 ) || ( sStrLen < sMatchLen ) ) return NULL; @@ -223,8 +223,8 @@ const char *ct_at_charset_forward( const char *pcString, size_t sStrLen, const char *pcRet, *pcSet, *pcStop1, *pcStop2; - HB_TRACE( HB_TR_DEBUG, ( "ct_at_charset_forward (\"%s\", %u, \"%s\", %u, %p)", - pcString, sStrLen, pcCharSet, sCharSetLen, psMatchedCharPos ) ); + HB_TRACE( HB_TR_DEBUG, ( "ct_at_charset_forward (\"%s\", %lu, \"%s\", %lu, %p)", + pcString, ( ULONG ) sStrLen, pcCharSet, ( ULONG ) sCharSetLen, psMatchedCharPos ) ); *( psMatchedCharPos ) = sCharSetLen; @@ -257,8 +257,8 @@ const char *ct_at_charset_backward( const char *pcString, size_t sStrLen, const char *pcRet, *pcSet, *pcStop; - HB_TRACE( HB_TR_DEBUG, ( "ct_at_charset_backward (\"%s\", %u, \"%s\", %u, %p)", - pcString, sStrLen, pcCharSet, sCharSetLen, psMatchedCharPos ) ); + HB_TRACE( HB_TR_DEBUG, ( "ct_at_charset_backward (\"%s\", %lu, \"%s\", %lu, %p)", + pcString, ( ULONG ) sStrLen, pcCharSet, ( ULONG ) sCharSetLen, psMatchedCharPos ) ); *( psMatchedCharPos ) = sCharSetLen; diff --git a/harbour/contrib/hbcurl/hbcurl.c b/harbour/contrib/hbcurl/hbcurl.c index f35ab86a3e..039a0b4629 100644 --- a/harbour/contrib/hbcurl/hbcurl.c +++ b/harbour/contrib/hbcurl/hbcurl.c @@ -507,22 +507,43 @@ static PHB_CURL PHB_CURL_create( CURL * from ) static HB_GARBAGE_FUNC( PHB_CURL_release ) { - void ** ph = ( void ** ) Cargo; - + PHB_CURL * hb_curl_ptr = ( PHB_CURL * ) Cargo; /* Check if pointer is not NULL to avoid multiple freeing */ - if( ph && * ph ) + if( hb_curl_ptr && * hb_curl_ptr ) { - /* Destroy the object */ - PHB_CURL_free( ( PHB_CURL ) * ph, hbTRUE ); + PHB_CURL hb_curl = * hb_curl_ptr; /* set pointer to NULL to avoid multiple freeing */ - * ph = NULL; + * hb_curl_ptr = NULL; + + /* Destroy the object */ + PHB_CURL_free( hb_curl, hbTRUE ); } } +static HB_GARBAGE_FUNC( PHB_CURL_mark ) +{ + PHB_CURL * hb_curl_ptr = ( PHB_CURL * ) Cargo; + + if( hb_curl_ptr && * hb_curl_ptr ) + { + PHB_CURL hb_curl = * hb_curl_ptr; + + if( hb_curl->pProgressBlock ) + hb_gcMark( hb_curl->pProgressBlock ); + } +} + +static const HB_GC_FUNCS s_gcCURLFuncs = +{ + PHB_CURL_release, + PHB_CURL_mark +}; + + static void PHB_CURL_ret( PHB_CURL from ) { - void ** ph = ( void ** ) hb_gcAlloc( sizeof( PHB_CURL ), PHB_CURL_release ); + void ** ph = ( void ** ) hb_gcAllocate( sizeof( PHB_CURL ), &s_gcCURLFuncs ); * ph = PHB_CURL_create( from ); @@ -531,12 +552,12 @@ static void PHB_CURL_ret( PHB_CURL from ) static void * PHB_CURL_is( int iParam ) { - return hb_parptrGC( PHB_CURL_release, iParam ); + return hb_parptrGC( &s_gcCURLFuncs, iParam ); } static PHB_CURL PHB_CURL_par( int iParam ) { - void ** ph = ( void ** ) hb_parptrGC( PHB_CURL_release, iParam ); + void ** ph = ( void ** ) hb_parptrGC( &s_gcCURLFuncs, iParam ); return ph ? ( PHB_CURL ) * ph : NULL; } @@ -561,15 +582,17 @@ HB_FUNC( CURL_EASY_CLEANUP ) { if( PHB_CURL_is( 1 ) ) { - void ** ph = ( void ** ) hb_parptrGC( PHB_CURL_release, 1 ); + void ** ph = ( void ** ) hb_parptrGC( &s_gcCURLFuncs, 1 ); if( ph && * ph ) { - /* Destroy the object */ - PHB_CURL_free( ( PHB_CURL ) * ph, hbTRUE ); + PHB_CURL hb_curl = ( PHB_CURL ) * ph; /* set pointer to NULL to avoid multiple freeing */ * ph = NULL; + + /* Destroy the object */ + PHB_CURL_free( hb_curl, hbTRUE ); } } else @@ -1365,6 +1388,8 @@ HB_FUNC( CURL_EASY_SETOPT ) if( pProgressBlock ) { hb_curl->pProgressBlock = hb_itemNew( pProgressBlock ); + /* unlock the item so GC will not mark them as used */ + hb_gcUnlock( hb_curl->pProgressBlock ); curl_easy_setopt( hb_curl->curl, CURLOPT_PROGRESSFUNCTION, hb_curl_progress_callback ); res = curl_easy_setopt( hb_curl->curl, CURLOPT_PROGRESSDATA, hb_curl->pProgressBlock ); diff --git a/harbour/contrib/hbhpdf/harupdf.c b/harbour/contrib/hbhpdf/harupdf.c index b13b2597d7..dc82437e9f 100644 --- a/harbour/contrib/hbhpdf/harupdf.c +++ b/harbour/contrib/hbhpdf/harupdf.c @@ -79,9 +79,15 @@ static HB_GARBAGE_FUNC( HPDF_Doc_release ) } } +static const HB_GC_FUNCS s_gcHPDF_DocFuncs = +{ + HPDF_Doc_release, + hb_gcDummyMark +}; + static HPDF_Doc HPDF_Doc_par( int iParam ) { - void ** ph = ( void ** ) hb_parptrGC( HPDF_Doc_release, iParam ); + void ** ph = ( void ** ) hb_parptrGC( &s_gcHPDF_DocFuncs, iParam ); return ph ? ( HPDF_Doc ) * ph : NULL; } @@ -95,7 +101,7 @@ static HPDF_Doc HPDF_Doc_par( int iParam ) */ HB_FUNC( HPDF_NEW ) { - void ** ph = ( void ** ) hb_gcAlloc( sizeof( HPDF_Doc ), HPDF_Doc_release ); + void ** ph = ( void ** ) hb_gcAllocate( sizeof( HPDF_Doc ), &s_gcHPDF_DocFuncs ); * ph = ( void * ) HPDF_New( NULL, NULL ); @@ -106,7 +112,7 @@ HB_FUNC( HPDF_NEW ) */ HB_FUNC( HPDF_FREE ) { - void ** ph = ( void ** ) hb_parptrGC( HPDF_Doc_release, 1 ); + void ** ph = ( void ** ) hb_parptrGC( &s_gcHPDF_DocFuncs, 1 ); if( ph && * ph ) { diff --git a/harbour/contrib/hbmzip/hbmzip.c b/harbour/contrib/hbmzip/hbmzip.c index 73399441e7..ab8bf80704 100644 --- a/harbour/contrib/hbmzip/hbmzip.c +++ b/harbour/contrib/hbmzip/hbmzip.c @@ -93,10 +93,16 @@ static HB_GARBAGE_FUNC( hb_zipfile_destructor ) } } +static const HB_GC_FUNCS s_gcZipFileFuncs = +{ + hb_zipfile_destructor, + hb_gcDummyMark +}; + static gzFile hb_zipfileParam( int iParam ) { - zipFile* phZip = ( zipFile* ) hb_parptrGC( hb_zipfile_destructor, iParam ); + zipFile* phZip = ( zipFile* ) hb_parptrGC( &s_gcZipFileFuncs, iParam ); if( phZip && * phZip ) return * phZip; @@ -117,10 +123,16 @@ static HB_GARBAGE_FUNC( hb_unzipfile_destructor ) } } +static const HB_GC_FUNCS s_gcUnZipFileFuncs = +{ + hb_unzipfile_destructor, + hb_gcDummyMark +}; + static gzFile hb_unzipfileParam( int iParam ) { - unzFile* phUnzip = ( unzFile* ) hb_parptrGC( hb_unzipfile_destructor, iParam ); + unzFile* phUnzip = ( unzFile* ) hb_parptrGC( &s_gcUnZipFileFuncs, iParam ); if( phUnzip && * phUnzip ) return * phUnzip; @@ -143,7 +155,7 @@ HB_FUNC( HB_ZIPOPEN ) &pszGlobalComment, NULL ); if( hZip ) { - zipFile* phZip = (zipFile*) hb_gcAlloc( sizeof( zipFile ), hb_zipfile_destructor ); + zipFile* phZip = (zipFile*) hb_gcAllocate( sizeof( zipFile ), &s_gcZipFileFuncs ); * phZip = hZip; hb_retptrGC( phZip ); @@ -160,7 +172,7 @@ HB_FUNC( HB_ZIPOPEN ) /* HB_ZipClose( hZip, [ cGlobalComment ] ) --> nError */ HB_FUNC( HB_ZIPCLOSE ) { - zipFile* phZip = ( zipFile* ) hb_parptrGC( hb_zipfile_destructor, 1 ); + zipFile* phZip = ( zipFile* ) hb_parptrGC( &s_gcZipFileFuncs, 1 ); if( phZip && * phZip ) { @@ -273,7 +285,7 @@ HB_FUNC( HB_UNZIPOPEN ) unzFile hUnzip = unzOpen( szFileName ); if( hUnzip ) { - unzFile* phUnzip = (unzFile*) hb_gcAlloc( sizeof( unzFile ), hb_unzipfile_destructor ); + unzFile* phUnzip = (unzFile*) hb_gcAllocate( sizeof( unzFile ), &s_gcUnZipFileFuncs ); * phUnzip = hUnzip; hb_retptrGC( phUnzip ); @@ -287,7 +299,7 @@ HB_FUNC( HB_UNZIPOPEN ) /* HB_UnzipClose( hUnzip ) --> nError */ HB_FUNC( HB_UNZIPCLOSE ) { - unzFile* phUnzip = ( unzFile* ) hb_parptrGC( hb_unzipfile_destructor, 1 ); + unzFile* phUnzip = ( unzFile* ) hb_parptrGC( &s_gcUnZipFileFuncs, 1 ); if( phUnzip && * phUnzip ) { diff --git a/harbour/contrib/hbnetio/netiosrv.c b/harbour/contrib/hbnetio/netiosrv.c index e93d1f2769..300d1d7dc6 100644 --- a/harbour/contrib/hbnetio/netiosrv.c +++ b/harbour/contrib/hbnetio/netiosrv.c @@ -232,9 +232,15 @@ static HB_GARBAGE_FUNC( s_consrv_destructor ) } } +static const HB_GC_FUNCS s_gcConSrvFuncs = +{ + s_consrv_destructor, + hb_gcDummyMark +}; + static PHB_CONSRV s_consrvParam( int iParam ) { - PHB_CONSRV * conn_ptr = ( PHB_CONSRV * ) hb_parptrGC( s_consrv_destructor, + PHB_CONSRV * conn_ptr = ( PHB_CONSRV * ) hb_parptrGC( &s_gcConSrvFuncs, iParam ); if( conn_ptr && *conn_ptr ) @@ -248,8 +254,8 @@ static void s_consrvRet( PHB_CONSRV conn ) { if( conn ) { - PHB_CONSRV * conn_ptr = ( PHB_CONSRV * ) hb_gcAlloc( sizeof( PHB_CONSRV ), - s_consrv_destructor ); + PHB_CONSRV * conn_ptr = ( PHB_CONSRV * ) hb_gcAllocate( sizeof( PHB_CONSRV ), + &s_gcConSrvFuncs ); *conn_ptr = conn; hb_retptrGC( conn_ptr ); } @@ -330,10 +336,16 @@ static HB_GARBAGE_FUNC( s_listensd_destructor ) } } +static const HB_GC_FUNCS s_gcListensdFuncs = +{ + s_listensd_destructor, + hb_gcDummyMark +}; + static PHB_LISTENSD s_listenParam( int iParam, BOOL fError ) { PHB_LISTENSD * lsd_ptr = ( PHB_LISTENSD * ) - hb_parptrGC( s_listensd_destructor, iParam ); + hb_parptrGC( &s_gcListensdFuncs, iParam ); if( lsd_ptr && *lsd_ptr ) return *lsd_ptr; @@ -367,8 +379,8 @@ static void s_listenRet( HB_SOCKET sd, const char * szRootPath ) lsd->rootPath[ iLen ] = HB_OS_PATH_DELIM_CHR; } } - lsd_ptr = ( PHB_LISTENSD * ) hb_gcAlloc( sizeof( PHB_LISTENSD ), - s_listensd_destructor ); + lsd_ptr = ( PHB_LISTENSD * ) hb_gcAllocate( sizeof( PHB_LISTENSD ), + &s_gcListensdFuncs ); *lsd_ptr = lsd; hb_retptrGC( lsd_ptr ); } diff --git a/harbour/contrib/hbsqlit3/hbsqlit3.c b/harbour/contrib/hbsqlit3/hbsqlit3.c index 851ba205a5..ddcbaf455a 100644 --- a/harbour/contrib/hbsqlit3/hbsqlit3.c +++ b/harbour/contrib/hbsqlit3/hbsqlit3.c @@ -157,6 +157,13 @@ static HB_GARBAGE_FUNC( hb_sqlite3_destructor ) } } +static const HB_GC_FUNCS s_gcSqlite3Funcs = +{ + hb_sqlite3_destructor, + hb_gcDummyMark +}; + + PHB_ITEM hb_sqlite3_itemPut( PHB_ITEM pItem, void *pMemAddr, int iType ) { PHB_SQLITE3_HOLDER pStructHolder; @@ -173,7 +180,7 @@ PHB_ITEM hb_sqlite3_itemPut( PHB_ITEM pItem, void *pMemAddr, int iType ) pItem = hb_itemNew( pItem ); } - pStructHolder = ( PHB_SQLITE3_HOLDER ) hb_gcAlloc( sizeof(HB_SQLITE3_HOLDER), hb_sqlite3_destructor ); + pStructHolder = ( PHB_SQLITE3_HOLDER ) hb_gcAllocate( sizeof(HB_SQLITE3_HOLDER), &s_gcSqlite3Funcs ); pStructHolder->hbsqlite3 = ( HB_SQLITE3 * ) pMemAddr; pStructHolder->type = iType; @@ -182,7 +189,7 @@ PHB_ITEM hb_sqlite3_itemPut( PHB_ITEM pItem, void *pMemAddr, int iType ) void *hb_sqlite3_itemGet( PHB_ITEM pItem, int iType, BOOL fError ) { - PHB_SQLITE3_HOLDER pStructHolder = ( PHB_SQLITE3_HOLDER ) hb_itemGetPtrGC( pItem, hb_sqlite3_destructor ); + PHB_SQLITE3_HOLDER pStructHolder = ( PHB_SQLITE3_HOLDER ) hb_itemGetPtrGC( pItem, &s_gcSqlite3Funcs ); int iError = 0; HB_SYMBOL_UNUSED( iError ); diff --git a/harbour/contrib/hbwin/axcore.c b/harbour/contrib/hbwin/axcore.c index b984b7f615..0a79b3d262 100644 --- a/harbour/contrib/hbwin/axcore.c +++ b/harbour/contrib/hbwin/axcore.c @@ -311,7 +311,8 @@ HB_OLE_PARAM_REF; static HRESULT STDMETHODCALLTYPE Invoke( IDispatch* lpThis, DISPID dispid, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pParams, - VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr ) + VARIANT* pVarResult, EXCEPINFO* pExcepInfo, + UINT* puArgErr ) { int i, iCount, ii, iRefs; PHB_ITEM pAction, pKey = NULL; @@ -395,7 +396,7 @@ static const IDispatchVtbl ISink_Vtbl = { }; -HB_FUNC( __AXREGISTERHANDLER ) /* ( pDisp, bHandler ) --> pSink */ +HB_FUNC( __AXREGISTERHANDLER ) /* ( pDisp, bHandler [, cID] ) --> pSink */ { IDispatch * pDisp = hb_oleParam( 1 ); diff --git a/harbour/contrib/hbwin/olecore.c b/harbour/contrib/hbwin/olecore.c index 089a0e88d7..fc572d93b0 100644 --- a/harbour/contrib/hbwin/olecore.c +++ b/harbour/contrib/hbwin/olecore.c @@ -127,6 +127,12 @@ static HB_GARBAGE_FUNC( hb_ole_destructor ) } } +static const HB_GC_FUNCS s_gcOleFuncs = +{ + hb_ole_destructor, + hb_gcDummyMark +}; + static HB_GARBAGE_FUNC( hb_oleenum_destructor ) { @@ -139,10 +145,16 @@ static HB_GARBAGE_FUNC( hb_oleenum_destructor ) } } +static const HB_GC_FUNCS s_gcOleenumFuncs = +{ + hb_oleenum_destructor, + hb_gcDummyMark +}; + IDispatch* hb_oleParam( int iParam ) { - IDispatch** ppDisp = ( IDispatch** ) hb_parptrGC( hb_ole_destructor, iParam ); + IDispatch** ppDisp = ( IDispatch** ) hb_parptrGC( &s_gcOleFuncs, iParam ); if( ppDisp && *ppDisp ) return *ppDisp; @@ -154,7 +166,7 @@ IDispatch* hb_oleParam( int iParam ) IDispatch* hb_oleItemGet( PHB_ITEM pItem ) { - return ( IDispatch* ) hb_itemGetPtrGC( pItem, hb_ole_destructor ); + return ( IDispatch* ) hb_itemGetPtrGC( pItem, &s_gcOleFuncs ); } @@ -162,7 +174,7 @@ PHB_ITEM hb_oleItemPut( PHB_ITEM pItem, IDispatch* pDisp ) { IDispatch** ppDisp; - ppDisp = ( IDispatch** ) hb_gcAlloc( sizeof( IDispatch* ), hb_ole_destructor ); + ppDisp = ( IDispatch** ) hb_gcAllocate( sizeof( IDispatch* ), &s_gcOleFuncs ); *ppDisp = pDisp; return hb_itemPutPtrGC( pItem, ppDisp ); @@ -171,7 +183,7 @@ PHB_ITEM hb_oleItemPut( PHB_ITEM pItem, IDispatch* pDisp ) static IEnumVARIANT* hb_oleenumParam( int iParam ) { - IEnumVARIANT** ppEnum = ( IEnumVARIANT** ) hb_parptrGC( hb_oleenum_destructor, iParam ); + IEnumVARIANT** ppEnum = ( IEnumVARIANT** ) hb_parptrGC( &s_gcOleenumFuncs, iParam ); if( ppEnum && *ppEnum ) return *ppEnum; @@ -439,7 +451,6 @@ void hb_oleVariantToItem( PHB_ITEM pItem, VARIANT* pVariant ) if( pdispVal ) { PHB_ITEM pObject, pPtrGC; - IDispatch** ppDisp; if( hb_vmRequestReenter() ) { @@ -449,12 +460,9 @@ void hb_oleVariantToItem( PHB_ITEM pItem, VARIANT* pVariant ) pObject = hb_itemNew( hb_stackReturnItem() ); - ppDisp = ( IDispatch** ) hb_gcAlloc( sizeof( IDispatch* ), hb_ole_destructor ); - *ppDisp = pdispVal; - pPtrGC = hb_itemPutPtrGC( NULL, ppDisp ); - + pPtrGC = hb_oleItemPut( NULL, pdispVal ); /* Item is one more copy of the object */ - HB_VTBL( *ppDisp )->AddRef( HB_THIS( *ppDisp ) ); + HB_VTBL( pdispVal )->AddRef( HB_THIS( pdispVal ) ); hb_vmPushDynSym( s_pDyns_hObjAssign ); hb_vmPush( pObject ); @@ -897,7 +905,6 @@ HB_FUNC( __OLECREATEOBJECT ) /* ( cOleName | cCLSID [, cIID ] ) */ wchar_t* cCLSID; GUID ClassID, iid = IID_IDispatch; IDispatch* pDisp = NULL; - IDispatch** ppDisp; const char* cOleName = hb_parc( 1 ); const char* cID = hb_parc( 2 ); HRESULT lOleError; @@ -933,11 +940,7 @@ HB_FUNC( __OLECREATEOBJECT ) /* ( cOleName | cCLSID [, cIID ] ) */ hb_oleSetError( lOleError ); if( lOleError == S_OK ) - { - ppDisp = ( IDispatch** ) hb_gcAlloc( sizeof( IDispatch* ), hb_ole_destructor ); - *ppDisp = pDisp; - hb_retptrGC( ppDisp ); - } + hb_oleItemPut( hb_stackReturnItem(), pDisp ); else hb_ret(); } @@ -948,7 +951,6 @@ HB_FUNC( __OLEGETACTIVEOBJECT ) /* ( cOleName | cCLSID [, cIID ] ) */ BSTR wCLSID; IID ClassID, iid = IID_IDispatch; IDispatch* pDisp = NULL; - IDispatch** ppDisp; IUnknown* pUnk = NULL; const char* cOleName = hb_parc( 1 ); const char* cID = hb_parc( 2 ); @@ -990,11 +992,7 @@ HB_FUNC( __OLEGETACTIVEOBJECT ) /* ( cOleName | cCLSID [, cIID ] ) */ hb_oleSetError( lOleError ); if( lOleError == S_OK ) - { - ppDisp = ( IDispatch** ) hb_gcAlloc( sizeof( IDispatch* ), hb_ole_destructor ); - *ppDisp = pDisp; - hb_retptrGC( ppDisp ); - } + hb_oleItemPut( hb_stackReturnItem(), pDisp ); else hb_ret(); } @@ -1051,7 +1049,7 @@ HB_FUNC( __OLEENUMCREATE ) /* ( __hObj ) */ hb_oleSetError( S_OK ); - ppEnum = ( IEnumVARIANT** ) hb_gcAlloc( sizeof( IEnumVARIANT* ), hb_oleenum_destructor ); + ppEnum = ( IEnumVARIANT** ) hb_gcAllocate( sizeof( IEnumVARIANT* ), &s_gcOleenumFuncs ); *ppEnum = pEnum; hb_retptrGC( ppEnum ); return; diff --git a/harbour/contrib/hbwin/wapi_winuser.c b/harbour/contrib/hbwin/wapi_winuser.c index 0fe853934d..b80ee671b2 100644 --- a/harbour/contrib/hbwin/wapi_winuser.c +++ b/harbour/contrib/hbwin/wapi_winuser.c @@ -101,6 +101,11 @@ HB_FUNC( WAPI_CREATEWINDOWEX ) HB_TCHAR_FREE( lpStr2 ); } +HB_FUNC( WAPI_DESTROYWINDOW ) +{ + hb_retl( DestroyWindow( ( HWND ) hb_parptr( 1 ) ) ); +} + /*-----------------------------------------------------------------------/ BEGIN SCROLLBAR MANIPULATION WINAPI FUNCTIONS /-----------------------------------------------------------------------*/ diff --git a/harbour/contrib/hbwin/win_dll.c b/harbour/contrib/hbwin/win_dll.c index 71c7fdced1..e8cc398e36 100644 --- a/harbour/contrib/hbwin/win_dll.c +++ b/harbour/contrib/hbwin/win_dll.c @@ -726,6 +726,14 @@ static HB_GARBAGE_FUNC( _DLLUnload ) xec->dwType = 0; } } + +static const HB_GC_FUNCS s_gcDllFuncs = +{ + _DLLUnload, + hb_gcDummyMark +}; + + #endif static LPVOID hb_getprocaddress( HMODULE hDLL, int iProc ) @@ -821,7 +829,7 @@ HB_FUNC( DLLCALL ) HB_FUNC( DLLPREPARECALL ) { #if ! defined( HB_OS_WIN_CE ) - PXPP_DLLEXEC xec = ( PXPP_DLLEXEC ) hb_gcAlloc( sizeof( XPP_DLLEXEC ), _DLLUnload ); + PXPP_DLLEXEC xec = ( PXPP_DLLEXEC ) hb_gcAllocate( sizeof( XPP_DLLEXEC ), &s_gcDllFuncs ); char * pszErrorText; memset( xec, 0, sizeof( XPP_DLLEXEC ) ); diff --git a/harbour/contrib/hbwin/win_prn1.c b/harbour/contrib/hbwin/win_prn1.c index b01441b551..a11882f5b0 100644 --- a/harbour/contrib/hbwin/win_prn1.c +++ b/harbour/contrib/hbwin/win_prn1.c @@ -98,9 +98,16 @@ static HB_GARBAGE_FUNC( win_HDC_release ) } } +static const HB_GC_FUNCS s_gc_HDC_funcs = +{ + win_HDC_release, + hb_gcDummyMark +}; + + static HDC win_HDC_par( int iParam ) { - void ** ph = ( void ** ) hb_parptrGC( win_HDC_release, iParam ); + void ** ph = ( void ** ) hb_parptrGC( &s_gc_HDC_funcs, iParam ); return ph ? ( HDC ) * ph : ( HDC ) hb_parptr( iParam ); } @@ -120,12 +127,18 @@ static HB_GARBAGE_FUNC( win_HPEN_release ) } } +static const HB_GC_FUNCS s_gc_HPEN_funcs = +{ + win_HPEN_release, + hb_gcDummyMark +}; + HB_FUNC( WIN_CREATEDC ) { if( HB_ISCHAR( 1 ) ) { LPTSTR lpText = HB_TCHAR_CONVTO( hb_parc( 1 ) ); - void ** ph = ( void ** ) hb_gcAlloc( sizeof( HDC * ), win_HDC_release ); + void ** ph = ( void ** ) hb_gcAllocate( sizeof( HDC * ), &s_gc_HDC_funcs ); *ph = ( void * ) CreateDC( TEXT( "" ), lpText, NULL, NULL ); hb_retptrGC( ph ); HB_TCHAR_FREE( lpText ); @@ -183,7 +196,7 @@ HB_FUNC( WIN_ABORTDOC ) HB_FUNC( WIN_DELETEDC ) { - void ** phDC = ( void ** ) hb_parptrGC( win_HDC_release, 1 ); + void ** phDC = ( void ** ) hb_parptrGC( &s_gc_HDC_funcs, 1 ); /* Check if pointer is not NULL to avoid multiple freeing */ if( phDC && * phDC ) @@ -596,7 +609,7 @@ HB_FUNC( WIN_SETPEN ) HDC hDC = win_HDC_par( 1 ); HPEN hOldPen; - void ** ph = ( void ** ) hb_gcAlloc( sizeof( HPEN * ), win_HPEN_release ); + void ** ph = ( void ** ) hb_gcAllocate( sizeof( HPEN * ), &s_gc_HPEN_funcs ); * ph = ( void * ) CreatePen( hb_parni( 2 ), /* pen style */ hb_parni( 3 ), /* pen width */ diff --git a/harbour/contrib/xhb/hbcompat.ch b/harbour/contrib/xhb/hbcompat.ch index 1e7540ed44..031ed48ad0 100644 --- a/harbour/contrib/xhb/hbcompat.ch +++ b/harbour/contrib/xhb/hbcompat.ch @@ -328,6 +328,11 @@ #xtranslate i18n() => hb_i18n_gettext() + /* _SET_TRACE* / TraceLog() */ + #xtranslate Set(_SET_TRACE [,]) => xhb_setTrace( ) + #xtranslate Set(_SET_TRACEFILE [,]) => xhb_setTraceFile( ) + #xtranslate Set(_SET_TRACESTACK [,]) => xhb_setTraceStack( ) + /* MT functions */ #xtranslate hb_MultiThread() => hb_mtvm() #xtranslate GetCurrentThread() => hb_threadSelf() diff --git a/harbour/contrib/xhb/traceprg.prg b/harbour/contrib/xhb/traceprg.prg index caaec6481e..8593035ca3 100644 --- a/harbour/contrib/xhb/traceprg.prg +++ b/harbour/contrib/xhb/traceprg.prg @@ -50,50 +50,100 @@ */ #include "set.ch" +#include "fileio.ch" + +#define HB_SET_TRACESTACK_NONE 0 +#define HB_SET_TRACESTACK_CURRENT 1 +#define HB_SET_TRACESTACK_ALL 2 + +#define CRLF HB_OsNewLine() -#DEFINE CRLF HB_OsNewLine() #xtranslate Write( ) => FWrite( FileHandle, ) //;HB_OutDebug( ) -STATIC s_cSET_TRACEFILE := "trace.log" -STATIC s_nSET_TRACESTACK := 2 /* HB_SET_TRACESTACK_ALL */ -STATIC s_lSET_TRACE := .T. +STATIC s_lSET_TRACE := .T. +STATIC s_cSET_TRACEFILE := "trace.log" +STATIC s_nSET_TRACESTACK := HB_SET_TRACESTACK_ALL + +FUNCTION xhb_setTrace( xTrace ) + LOCAL lTrace := s_lSET_TRACE + + IF HB_ISLOGICAL( xTrace ) + s_lSET_TRACE := xTrace + ELSEIF HB_ISSTRING( xTrace ) + IF Upper( xTrace ) = "ON" + s_lSET_TRACE := .T. + ELSEIF Upper( xTrace ) = "OFF" + s_lSET_TRACE := .F. + ENDIF + ENDIF + +RETURN lTrace + +FUNCTION xhb_setTraceFile( xFile, lAppend ) + LOCAL cTraceFile := s_cSET_TRACEFILE + + IF HB_ISSTRING( xFile ) + s_cSET_TRACEFILE := xFile + IF !HB_ISLOGICAL( lAppend ) .OR. !lAppend + FClose( FCreate( s_cSET_TRACEFILE ) ) + ENDIF + ENDIF + +RETURN cTraceFile + +FUNCTION xhb_setTraceStack( xLevel ) + LOCAL nTraceLevel := s_nSET_TRACESTACK + + IF HB_ISSTRING( xLevel ) + IF Upper( xLevel ) == "NONE" + s_nSET_TRACESTACK := HB_SET_TRACESTACK_NONE + ELSEIF Upper( xLevel ) == "CURRENT" + s_nSET_TRACESTACK := HB_SET_TRACESTACK_CURRENT + ELSEIF Upper( xLevel ) == "ALL" + s_nSET_TRACESTACK := HB_SET_TRACESTACK_ALL + ENDIF + ELSEIF HB_ISNUMERIC( xLevel ) + IF xLevel >= 0 + s_nSET_TRACESTACK := xLevel + ENDIF + ENDIF + +RETURN nTraceLevel //--------------------------------------------------------------// + FUNCTION TraceLog( ... ) // Using PRIVATE instead of LOCALs so TraceLog() is DIVERT friendly. - MEMVAR cFile, FileHandle, nLevel, ProcName, xParam + LOCAL cFile, FileHandle, nLevel, ProcName, xParam #ifdef __XHARBOUR__ IF ! SET( _SET_TRACE ) RETURN .T. ENDIF - PRIVATE cFile := SET( _SET_TRACEFILE ) - PRIVATE nLevel := SET( _SET_TRACESTACK ) + cFile := SET( _SET_TRACEFILE ) + nLevel := SET( _SET_TRACESTACK ) #else - IF s_lSET_TRACE + IF !s_lSET_TRACE RETURN .T. ENDIF - PRIVATE cFile := s_cSET_TRACEFILE - PRIVATE nLevel := s_nSET_TRACESTACK + cFile := s_cSET_TRACEFILE + nLevel := s_nSET_TRACESTACK #endif - PRIVATE FileHandle - PRIVATE ProcName, xParam - /* hb_FileExists() and FOpen()/FCreate() make different assumptions rgdg path, so we have to make sure cFile contains path to avoid ambiguity */ cFile := cWithPath( cFile ) IF hb_FileExists( cFile ) - FileHandle := FOpen( cFile, 1 ) + FileHandle := FOpen( cFile, FO_WRITE ) ELSE FileHandle := FCreate( cFile ) ENDIF - FSeek( FileHandle, 0, 2 ) + FSeek( FileHandle, 0, FS_END ) IF nLevel > 0 Write( '[' + ProcFile(1) + "->" + ProcName( 1 ) + '] (' + LTrim( Str( Procline(1) ) ) + ')' ) @@ -115,7 +165,7 @@ FUNCTION TraceLog( ... ) Write( CRLF ) - FClose(FileHandle) + FClose( FileHandle ) RETURN .T. //--------------------------------------------------------------// diff --git a/harbour/include/hbapi.h b/harbour/include/hbapi.h index e1c15b74a6..34d95e7e4e 100644 --- a/harbour/include/hbapi.h +++ b/harbour/include/hbapi.h @@ -569,22 +569,30 @@ extern HB_EXPORT void hb_xvheapunlock( HB_VMHANDLE h, ULONG nOffset ); typedef HB_GARBAGE_FUNC( HB_GARBAGE_FUNC_ ); typedef HB_GARBAGE_FUNC_ * HB_GARBAGE_FUNC_PTR; -#define HB_GARBAGE_SWEEPER( hbfunc ) BOOL hbfunc( void * Cargo ) /* callback function for cleaning garbage memory pointer */ -typedef HB_GARBAGE_SWEEPER( HB_GARBAGE_SWEEPER_ ); -typedef HB_GARBAGE_SWEEPER_ * HB_GARBAGE_SWEEPER_PTR; +typedef struct +{ + HB_GARBAGE_FUNC_PTR clear; + HB_GARBAGE_FUNC_PTR mark; +} +HB_GC_FUNCS; -extern void hb_gcRegisterSweep( HB_GARBAGE_SWEEPER_PTR pSweep, void * Cargo ); +extern HB_EXPORT void * hb_gcAllocate( ULONG ulSize, const HB_GC_FUNCS * pFuncs ); /* allocates a memory controlled by the garbage collector */ +extern HB_EXPORT void hb_gcFree( void * pAlloc ); /* deallocates a memory allocated by the garbage collector */ +extern HB_EXPORT void * hb_gcLock( void * pAlloc ); /* do not release passed memory block */ +extern HB_EXPORT void * hb_gcUnlock( void * pAlloc ); /* passed block is allowed to be released */ +extern HB_EXPORT void hb_gcMark( void * pAlloc ); /* mark given block as used */ + +extern HB_EXPORT void hb_gcDummyMark( void * Cargo ); /* dummy GC mark function */ extern PHB_ITEM hb_gcGripGet( HB_ITEM_PTR pItem ); extern void hb_gcGripDrop( HB_ITEM_PTR pItem ); -extern HB_EXPORT void *hb_gcAlloc( ULONG ulSize, HB_GARBAGE_FUNC_PTR pFunc ); /* allocates a memory controlled by the garbage collector */ -extern void hb_gcFree( void *pAlloc ); /* deallocates a memory allocated by the garbage collector */ -extern void * hb_gcLock( void *pAlloc ); /* do not release passed memory block */ -extern void * hb_gcUnlock( void *pAlloc ); /* passed block is allowed to be released */ #ifdef _HB_API_INTERNAL_ -HB_GARBAGE_FUNC_PTR hb_gcFunc( void *pBlock ); /* return cleanup function pointer */ -extern void hb_gcItemRef( HB_ITEM_PTR pItem ); /* checks if passed item refers passed memory block pointer */ +extern const HB_GC_FUNCS * hb_gcFuncs( void *pBlock ); /* return cleanup function pointer */ +extern void hb_gcAttach( void * pBlock ); +extern void * hb_gcAllocRaw( ULONG ulSize, const HB_GC_FUNCS * pFuncs ); /* allocates a memory controlled by the garbage collector */ +extern void hb_gcGripMark( void * Cargo ); /* mark complex variables inside given item as used */ +extern void hb_gcItemRef( HB_ITEM_PTR pItem ); /* mark complex variables inside given item as used */ extern void hb_vmIsStackRef( void ); /* hvm.c - mark all local variables as used */ extern void hb_vmIsStaticRef( void ); /* hvm.c - mark all static variables as used */ extern void hb_gcReleaseAll( void ); /* release all memory blocks unconditionally */ @@ -631,7 +639,7 @@ extern HB_EXPORT long hb_parnl( int iParam ); /* retrieve a numeric para extern HB_EXPORT long hb_parnldef( int iParam, long lDefValue ); /* retrieve a numeric parameter as a long, return default value if parameter isn't numeric */ extern HB_EXPORT HB_LONG hb_parnint( int iParam ); /* retrieve a numeric parameter as a HB_LONG */ extern HB_EXPORT void * hb_parptr( int iParam ); /* retrieve a parameter as a pointer */ -extern HB_EXPORT void * hb_parptrGC( HB_GARBAGE_FUNC_PTR pFunc, int iParam ); /* retrieve a parameter as a pointer if it's a pointer to GC allocated block */ +extern HB_EXPORT void * hb_parptrGC( const HB_GC_FUNCS * pFuncs, int iParam ); /* retrieve a parameter as a pointer if it's a pointer to GC allocated block */ #ifndef HB_LONG_LONG_OFF extern HB_EXPORT LONGLONG hb_parnll( int iParam ); /* retrieve a numeric parameter as a long long */ #endif @@ -651,7 +659,7 @@ extern HB_EXPORT int hb_parvni( int iParam, ... ); /* retrieve a numeri extern HB_EXPORT long hb_parvnl( int iParam, ... ); /* retrieve a numeric parameter as a long */ extern HB_EXPORT HB_LONG hb_parvnint( int iParam, ... ); /* retrieve a numeric parameter as a HB_LONG */ extern HB_EXPORT void * hb_parvptr( int iParam, ... ); /* retrieve a parameter as a pointer */ -extern HB_EXPORT void * hb_parvptrGC( HB_GARBAGE_FUNC_PTR pFunc, int iParam, ... ); /* retrieve a parameter as a pointer if it's a pointer to GC allocated block */ +extern HB_EXPORT void * hb_parvptrGC( const HB_GC_FUNCS * pFuncs, int iParam, ... ); /* retrieve a parameter as a pointer if it's a pointer to GC allocated block */ #ifndef HB_LONG_LONG_OFF extern HB_EXPORT LONGLONG hb_parvnll( int iParam, ... ); /* retrieve a numeric parameter as a long long */ #endif @@ -790,7 +798,7 @@ extern HB_EXPORT char * hb_arrayGetC( PHB_ITEM pArray, ULONG ulIndex ); /* extern HB_EXPORT const char * hb_arrayGetCPtr( PHB_ITEM pArray, ULONG ulIndex ); /* retrieves the string pointer on an array element */ extern HB_EXPORT ULONG hb_arrayGetCLen( PHB_ITEM pArray, ULONG ulIndex ); /* retrieves the string length contained on an array element */ extern HB_EXPORT void * hb_arrayGetPtr( PHB_ITEM pArray, ULONG ulIndex ); /* retrieves the pointer contained on an array element */ -extern HB_EXPORT void * hb_arrayGetPtrGC( PHB_ITEM pArray, ULONG ulIndex, HB_GARBAGE_FUNC_PTR pFunc ); /* retrieves the GC pointer contained on an array element */ +extern HB_EXPORT void * hb_arrayGetPtrGC( PHB_ITEM pArray, ULONG ulIndex, const HB_GC_FUNCS * pFuncs ); /* retrieves the GC pointer contained on an array element */ extern HB_EXPORT PHB_SYMB hb_arrayGetSymbol( PHB_ITEM pArray, ULONG ulIndex ); /* retrieves symbol contained on an array element */ extern HB_EXPORT BOOL hb_arrayGetL( PHB_ITEM pArray, ULONG ulIndex ); /* retrieves the logical value contained on an array element */ extern HB_EXPORT int hb_arrayGetNI( PHB_ITEM pArray, ULONG ulIndex ); /* retrieves the int value contained on an array element */ @@ -828,6 +836,7 @@ extern HB_EXPORT ULONG hb_arrayRevScan( PHB_ITEM pArray, PHB_ITEM pValue, extern HB_EXPORT BOOL hb_arrayEval( PHB_ITEM pArray, PHB_ITEM bBlock, ULONG * pulStart, ULONG * pulCount ); /* execute a code-block for every element of an array item */ extern HB_EXPORT BOOL hb_arrayCopy( PHB_ITEM pSrcArray, PHB_ITEM pDstArray, ULONG * pulStart, ULONG * pulCount, ULONG * pulTarget ); /* copy items from one array to another */ extern HB_EXPORT PHB_ITEM hb_arrayClone( PHB_ITEM pArray ); /* returns a duplicate of an existing array, including all nested items */ +extern HB_EXPORT PHB_ITEM hb_arrayCloneTo( PHB_ITEM pDest, PHB_ITEM pArray ); /* returns a duplicate of an existing array, including all nested items */ extern HB_EXPORT BOOL hb_arraySort( PHB_ITEM pArray, ULONG * pulStart, ULONG * pulCount, PHB_ITEM pBlock ); /* sorts an array item */ extern HB_EXPORT PHB_ITEM hb_arrayFromStack( USHORT uiLen ); /* Creates and returns an Array of n Elements from the Eval Stack - Does NOT pop the items. */ extern HB_EXPORT PHB_ITEM hb_arrayFromParams( int iLevel ); /* Creates and returns an Array of Generic Parameters for a given call level */ @@ -853,7 +862,8 @@ extern HB_EXPORT BOOL hb_hashAddNew( PHB_ITEM pHash, PHB_ITEM pKey, PHB_ITE extern HB_EXPORT BOOL hb_hashRemove( PHB_ITEM pHash, PHB_ITEM pItem ); extern HB_EXPORT BOOL hb_hashAllocNewPair( PHB_ITEM pHash, PHB_ITEM * pKeyPtr, PHB_ITEM * pValPtr ); extern HB_EXPORT void hb_hashSort( PHB_ITEM pHash ); -extern HB_EXPORT PHB_ITEM hb_hashClone( PHB_ITEM pSource ); +extern HB_EXPORT PHB_ITEM hb_hashClone( PHB_ITEM pHash ); +extern HB_EXPORT PHB_ITEM hb_hashCloneTo( PHB_ITEM pDest, PHB_ITEM pHash ); extern HB_EXPORT void hb_hashJoin( PHB_ITEM pDest, PHB_ITEM pSource, int iType ); extern HB_EXPORT BOOL hb_hashScan( PHB_ITEM pHash, PHB_ITEM pKey, ULONG * pulPos ); extern HB_EXPORT void hb_hashPreallocate( PHB_ITEM pHash, ULONG ulNewSize ); @@ -890,11 +900,6 @@ extern HB_EXPORT BOOL hb_hashDelAt( PHB_ITEM pHash, ULONG ulPos ); #define HB_HASH_FLAG_MASK 0xFFFF #define HB_HASH_FLAG_DEFAULT ( HB_HASH_AUTOADD_ASSIGN | HB_HASH_BINARY ) -#ifdef _HB_API_INTERNAL_ -/* internal hash API not exported */ -extern void hb_hashRefGrabage( PHB_ITEM pHash ); -#endif - #define HB_HASH_UNION 0 /* logical OR on items in two hash tables */ #define HB_HASH_INTERSECT 1 /* logical AND on items in two hash tables */ #define HB_HASH_DIFFERENCE 2 /* logical XOR on items in two hash tables */ diff --git a/harbour/include/hbapiitm.h b/harbour/include/hbapiitm.h index c3da6311b8..fc84b288c8 100644 --- a/harbour/include/hbapiitm.h +++ b/harbour/include/hbapiitm.h @@ -100,7 +100,7 @@ extern HB_EXPORT long hb_itemGetNL ( PHB_ITEM pItem ); extern HB_EXPORT HB_LONG hb_itemGetNInt ( PHB_ITEM pItem ); extern HB_EXPORT void hb_itemGetNLen ( PHB_ITEM pItem, int * piWidth, int * piDec ); extern HB_EXPORT void * hb_itemGetPtr ( PHB_ITEM pItem ); -extern HB_EXPORT void * hb_itemGetPtrGC ( PHB_ITEM pItem, HB_GARBAGE_FUNC_PTR pFunc ); +extern HB_EXPORT void * hb_itemGetPtrGC ( PHB_ITEM pItem, const HB_GC_FUNCS * pFuncs ); extern HB_EXPORT PHB_SYMB hb_itemGetSymbol ( PHB_ITEM pItem ); extern HB_EXPORT PHB_ITEM hb_itemNew ( PHB_ITEM pNull ); extern HB_EXPORT void hb_itemInit ( PHB_ITEM pItem ); @@ -171,6 +171,7 @@ extern HB_EXPORT PHB_ITEM hb_itemUnShareString( PHB_ITEM pItem ); /* un-shar extern HB_EXPORT PHB_ITEM hb_itemReSizeString( PHB_ITEM pItem, ULONG ulSize ); /* Resize string buffer of given string item - the pItem have to be valid unrefed string item */ extern HB_EXPORT BOOL hb_itemGetWriteCL( PHB_ITEM pItem, char ** pszValue, ULONG * pulLen ); extern HB_EXPORT PHB_ITEM hb_itemClone ( PHB_ITEM pItem ); /* clone the given item */ +extern HB_EXPORT PHB_ITEM hb_itemCloneTo ( PHB_ITEM pDest, PHB_ITEM pSource ); /* clone the given item */ extern HB_EXPORT char * hb_itemStr ( PHB_ITEM pNumber, PHB_ITEM pWidth, PHB_ITEM pDec ); /* convert a number to a string */ extern HB_EXPORT char * hb_itemString ( PHB_ITEM pItem, ULONG * ulLen, BOOL * bFreeReq ); /* Convert any scalar to a string */ extern HB_EXPORT BOOL hb_itemStrBuf ( char *szResult, PHB_ITEM pNumber, int iSize, int iDec ); /* convert a number to a string */ diff --git a/harbour/include/hbdefs.h b/harbour/include/hbdefs.h index ca199b9c5b..4a8dffa65b 100644 --- a/harbour/include/hbdefs.h +++ b/harbour/include/hbdefs.h @@ -589,7 +589,7 @@ typedef unsigned long HB_COUNTER; typedef unsigned long HB_PTRUINT; #endif -#ifdef HB_LONG_LONG_OFF +#if defined( HB_LONG_LONG_OFF ) || ULONG_MAX == ULONGLONG_MAX typedef LONG HB_FOFFSET; /* we can add hack with double as work around what should effectively give 52bit file size limit */ diff --git a/harbour/include/hbregex.h b/harbour/include/hbregex.h index 918386afb8..01fe0a8347 100644 --- a/harbour/include/hbregex.h +++ b/harbour/include/hbregex.h @@ -106,7 +106,7 @@ typedef int ( * HB_REG_COMP )( PHB_REGEX, const char * ); typedef int ( * HB_REG_EXEC )( PHB_REGEX, const char *, ULONG, int, HB_REGMATCH * ); extern void hb_regexInit( HB_REG_FREE pFree, HB_REG_COMP pComp, HB_REG_EXEC pExec ); -extern HB_GARBAGE_FUNC( hb_regexRelease ); +extern BOOL hb_regexIs( PHB_ITEM pItem ); #ifndef REG_EXTENDED # define REG_EXTENDED 0x00 diff --git a/harbour/src/common/hbgete.c b/harbour/src/common/hbgete.c index 32413f3a52..6e5287604c 100644 --- a/harbour/src/common/hbgete.c +++ b/harbour/src/common/hbgete.c @@ -114,19 +114,40 @@ char * hb_getenv( const char * szName ) BOOL hb_getenv_buffer( const char * szName, char * szBuffer, int nSize ) { - BOOL bRetVal; + BOOL fRetVal; #if defined( HB_OS_WIN ) { - LPTSTR lpName = HB_TCHAR_CONVTO( szName ); - LPTSTR lpBuffer = ( LPTSTR ) hb_xgrab( nSize * sizeof( TCHAR ) ); +#if defined( UNICODE ) + TCHAR name[ 128 ]; + TCHAR buffer[ 128 ]; + LPTSTR lpName, lpBuffer; + ULONG nLen = ( ULONG ) strlen( szName ) + 1; - bRetVal = GetEnvironmentVariable( lpName, lpBuffer, nSize ) != 0; + if( nLen * sizeof( TCHAR ) <= sizeof( name ) ) + lpName = name; + else + lpName = ( LPTSTR ) hb_xgrab( nLen * sizeof( TCHAR ) ); + hb_mbtowcset( lpName, szName, nLen ); - HB_TCHAR_GETFROM( szBuffer, lpBuffer, nSize ); + if( szBuffer == NULL ) + lpBuffer = NULL; + else if( nSize * sizeof( TCHAR ) <= sizeof( buffer ) ) + lpBuffer = buffer; + else + lpBuffer = ( LPTSTR ) hb_xgrab( nSize * sizeof( TCHAR ) ); - HB_TCHAR_FREE( lpBuffer ); - HB_TCHAR_FREE( lpName ); + fRetVal = GetEnvironmentVariable( lpName, lpBuffer, nSize ) != 0; + + hb_wctombget( szBuffer, lpBuffer, nSize ); + + if( lpName != name ) + hb_xfree( lpName ); + if( lpBuffer && lpBuffer != buffer ) + hb_xfree( lpBuffer ); +#else + fRetVal = GetEnvironmentVariableA( szName, szBuffer, nSize ) != 0; +#endif } #elif defined( HB_OS_OS2 ) { @@ -134,12 +155,12 @@ BOOL hb_getenv_buffer( const char * szName, char * szBuffer, int nSize ) if( DosScanEnv( ( PCSZ ) szName, &EnvValue ) == NO_ERROR ) { - bRetVal = TRUE; + fRetVal = TRUE; if( szBuffer != NULL && nSize != 0 ) hb_strncpy( szBuffer, ( char * ) EnvValue, nSize - 1 ); } else - bRetVal = FALSE; + fRetVal = FALSE; } #else { @@ -147,19 +168,19 @@ BOOL hb_getenv_buffer( const char * szName, char * szBuffer, int nSize ) if( pszTemp != NULL ) { - bRetVal = TRUE; + fRetVal = TRUE; if( szBuffer != NULL && nSize != 0 ) hb_strncpy( szBuffer, pszTemp, nSize - 1 ); } else - bRetVal = FALSE; + fRetVal = FALSE; } #endif - if( !bRetVal && szBuffer != NULL && nSize != 0 ) + if( !fRetVal && szBuffer != NULL && nSize != 0 ) szBuffer[ 0 ] = '\0'; - return bRetVal; + return fRetVal; } /* set current process environment variable, if szValue is NULL delete diff --git a/harbour/src/pp/pplib.c b/harbour/src/pp/pplib.c index 0282f001b1..e21e8f8ca3 100644 --- a/harbour/src/pp/pplib.c +++ b/harbour/src/pp/pplib.c @@ -122,6 +122,12 @@ static HB_GARBAGE_FUNC( hb_pp_Destructor ) } } +static const HB_GC_FUNCS s_gcPPFuncs = +{ + hb_pp_Destructor, + hb_gcDummyMark +}; + static void hb_pp_StdRules( PHB_ITEM ppItem ) { static BOOL s_fInit = TRUE; @@ -145,7 +151,7 @@ static void hb_pp_StdRules( PHB_ITEM ppItem ) PHB_PP_STATE hb_pp_Param( int iParam ) { PHB_PP_STATE * pStatePtr = - ( PHB_PP_STATE * ) hb_parptrGC( hb_pp_Destructor, iParam ); + ( PHB_PP_STATE * ) hb_parptrGC( &s_gcPPFuncs, iParam ); if( pStatePtr ) return * pStatePtr; @@ -169,8 +175,8 @@ HB_FUNC( __PP_INIT ) BOOL fArchDefs = !ISLOG( 3 ) || hb_parl( 3 ); PHB_ITEM ppItem; - pStatePtr = ( PHB_PP_STATE * ) hb_gcAlloc( sizeof( PHB_PP_STATE ), - hb_pp_Destructor ); + pStatePtr = ( PHB_PP_STATE * ) hb_gcAllocate( sizeof( PHB_PP_STATE ), + &s_gcPPFuncs ); * pStatePtr = pState; ppItem = hb_itemPutPtrGC( NULL, ( void * ) pStatePtr ); diff --git a/harbour/src/rdd/dbfnsx/dbfnsx1.c b/harbour/src/rdd/dbfnsx/dbfnsx1.c index 8a002bb50c..f2d55e2771 100644 --- a/harbour/src/rdd/dbfnsx/dbfnsx1.c +++ b/harbour/src/rdd/dbfnsx/dbfnsx1.c @@ -5189,7 +5189,7 @@ static void hb_nsxSortAddNodeKey( LPNSXSORTINFO pSort, UCHAR *pKeyVal, ULONG ulR { pSort->ulLastLeaf = ulPage; hb_nsxSetPageType( pSort->NodeList[ 0 ], NSX_LEAFPAGE ); - hb_nsxSetKeyRecSize( pSort->NodeList[ iLevel ], pSort->recSize ); + hb_nsxSetKeyRecSize( pSort->NodeList[ 0 ], pSort->recSize ); pSort->NodeList[ 0 ]->uiOffset = NSX_LEAFKEYOFFSET; } else @@ -5614,7 +5614,12 @@ static void hb_nsxSortOut( LPNSXSORTINFO pSort ) #endif if( pSort->NodeList[ 0 ] == NULL ) + { pSort->NodeList[ 0 ] = hb_nsxPageNew( pTag, TRUE ); + hb_nsxSetPageType( pSort->NodeList[ 0 ], NSX_LEAFPAGE ); + hb_nsxSetKeyRecSize( pSort->NodeList[ 0 ], pSort->recSize ); + pSort->NodeList[ 0 ]->uiOffset = NSX_LEAFKEYOFFSET; + } iLevel = 0; ulPage = 0; diff --git a/harbour/src/rdd/wacore.c b/harbour/src/rdd/wacore.c index 1e377a6197..5ca1b1d4f5 100644 --- a/harbour/src/rdd/wacore.c +++ b/harbour/src/rdd/wacore.c @@ -489,6 +489,12 @@ static HB_GARBAGE_FUNC( hb_waHolderDestructor ) } } +static const HB_GC_FUNCS s_gcWAFuncs = +{ + hb_waHolderDestructor, + hb_gcDummyMark +}; + void hb_rddCloseDetachedAreas( void ) { PHB_ITEM pDetachedArea; @@ -556,7 +562,7 @@ HB_ERRCODE hb_rddDetachArea( AREAP pArea, PHB_ITEM pCargo ) hb_arrayNew( pDetachedArea, 2 ); if( pCargo ) hb_arraySet( pDetachedArea, 2, pCargo ); - pHolder = ( AREAP * ) hb_gcAlloc( sizeof( AREAP ), hb_waHolderDestructor ); + pHolder = ( AREAP * ) hb_gcAllocate( sizeof( AREAP ), &s_gcWAFuncs ); *pHolder = pArea; hb_arraySetPtrGC( pDetachedArea, 1, pHolder ); /* siagnal waiting processes that new area is available */ diff --git a/harbour/src/rtl/hbgtcore.c b/harbour/src/rtl/hbgtcore.c index 0674391728..253fbb7b05 100644 --- a/harbour/src/rtl/hbgtcore.c +++ b/harbour/src/rtl/hbgtcore.c @@ -3379,9 +3379,15 @@ static HB_GARBAGE_FUNC( hb_gt_Destructor ) } } +static const HB_GC_FUNCS s_gcGTFuncs = +{ + hb_gt_Destructor, + hb_gcDummyMark +}; + static void * hb_gtParam( int iParam ) { - void ** gtHolder = ( void ** ) hb_parptrGC( hb_gt_Destructor, iParam ); + void ** gtHolder = ( void ** ) hb_parptrGC( &s_gcGTFuncs, iParam ); if( gtHolder && *gtHolder ) return *gtHolder; @@ -3392,7 +3398,7 @@ static void * hb_gtParam( int iParam ) PHB_GT hb_gt_ItemBase( PHB_ITEM pItemGT ) { - void ** gtHolder = ( void ** ) hb_itemGetPtrGC( pItemGT, hb_gt_Destructor ); + void ** gtHolder = ( void ** ) hb_itemGetPtrGC( pItemGT, &s_gcGTFuncs ); if( gtHolder && *gtHolder ) { PHB_GT pGT = ( PHB_GT ) *gtHolder; @@ -3421,7 +3427,7 @@ HB_FUNC( HB_GTCREATE ) if( hGT ) { - void ** gtHolder = ( void ** ) hb_gcAlloc( sizeof( void * ), hb_gt_Destructor ); + void ** gtHolder = ( void ** ) hb_gcAllocate( sizeof( void * ), &s_gcGTFuncs ); *gtHolder = hGT; hb_retptrGC( gtHolder ); } @@ -3446,7 +3452,7 @@ HB_FUNC( HB_GTSELECT ) if( hGT ) { - void ** gtHolder = ( void ** ) hb_gcAlloc( sizeof( void * ), hb_gt_Destructor ); + void ** gtHolder = ( void ** ) hb_gcAllocate( sizeof( void * ), &s_gcGTFuncs ); *gtHolder = hGT; hb_retptrGC( gtHolder ); } diff --git a/harbour/src/rtl/hbi18n1.c b/harbour/src/rtl/hbi18n1.c index 52e203da6d..49a5bac85e 100644 --- a/harbour/src/rtl/hbi18n1.c +++ b/harbour/src/rtl/hbi18n1.c @@ -446,9 +446,15 @@ static HB_GARBAGE_FUNC( hb_i18n_destructor ) } } +static const HB_GC_FUNCS s_gcI18NFuncs = +{ + hb_i18n_destructor, + hb_gcDummyMark +}; + static PHB_I18N_TRANS hb_i18n_param( int * piParam, BOOL fActive ) { - PHB_I18N_TRANS * pI18NHolder = ( PHB_I18N_TRANS * ) hb_parptrGC( hb_i18n_destructor, *piParam ); + PHB_I18N_TRANS * pI18NHolder = ( PHB_I18N_TRANS * ) hb_parptrGC( &s_gcI18NFuncs, *piParam ); if( pI18NHolder ) { @@ -467,7 +473,7 @@ static PHB_ITEM hb_i18n_newitem( PHB_I18N_TRANS pI18N ) if( !pI18N ) pI18N = hb_i18n_new(); pI18NHolder = ( PHB_I18N_TRANS * ) - hb_gcAlloc( sizeof( PHB_I18N_TRANS ), hb_i18n_destructor ); + hb_gcAllocate( sizeof( PHB_I18N_TRANS ), &s_gcI18NFuncs ); *pI18NHolder = pI18N; return hb_itemPutPtrGC( pItem, pI18NHolder ); @@ -1055,7 +1061,8 @@ HB_FUNC( __I18N_HASHTABLE ) if( pTable ) { - pI18N = hb_i18n_initialize( hb_itemNew( pTable ) ); + pTable = hb_itemNew( pTable ); + pI18N = hb_i18n_initialize( pTable ); if( pI18N ) hb_itemReturnRelease( hb_i18n_newitem( pI18N ) ); else diff --git a/harbour/src/rtl/hbinet.c b/harbour/src/rtl/hbinet.c index 8bc5b6c8de..ceeb30d720 100644 --- a/harbour/src/rtl/hbinet.c +++ b/harbour/src/rtl/hbinet.c @@ -93,12 +93,12 @@ typedef struct #define HB_INET_INITIALIZE() if( s_initialize ) hb_inetAutoInit() -#define HB_PARSOCKET( n ) ( ( PHB_SOCKET_STRUCT ) hb_parptrGC( hb_inetSocketFinalize, n ) ) +#define HB_PARSOCKET( n ) ( ( PHB_SOCKET_STRUCT ) hb_parptrGC( &s_gcInetFuncs, n ) ) #define HB_SOCKET_INIT( s, p ) \ do { \ HB_INET_INITIALIZE(); \ - s = ( PHB_SOCKET_STRUCT ) hb_gcAlloc( sizeof( HB_SOCKET_STRUCT ), hb_inetSocketFinalize ); \ + s = ( PHB_SOCKET_STRUCT ) hb_gcAllocate( sizeof( HB_SOCKET_STRUCT ), &s_gcInetFuncs ); \ memset( s, 0, sizeof( HB_SOCKET_STRUCT ) ); \ s->sd = HB_NO_SOCKET; \ s->readahead = HB_INET_BUFFER_LEN; \ @@ -175,6 +175,20 @@ static HB_GARBAGE_FUNC( hb_inetSocketFinalize ) } } +static HB_GARBAGE_FUNC( hb_inetSocketMark ) +{ + PHB_SOCKET_STRUCT socket = ( PHB_SOCKET_STRUCT ) Cargo; + + if( socket->pPeriodicBlock ) + hb_gcMark( socket->pPeriodicBlock ); +} + +static const HB_GC_FUNCS s_gcInetFuncs = +{ + hb_inetSocketFinalize, + hb_inetSocketMark +}; + /***************************************************** * Socket Initialization ***/ @@ -444,6 +458,7 @@ HB_FUNC( HB_INETPERIODCALLBACK ) if( socket->pPeriodicBlock ) hb_itemRelease( socket->pPeriodicBlock ); socket->pPeriodicBlock = hb_itemClone( pExec ); + hb_gcUnlock( socket->pPeriodicBlock ); } } else diff --git a/harbour/src/rtl/hbregex.c b/harbour/src/rtl/hbregex.c index 0369b59b0c..c96f980d2c 100644 --- a/harbour/src/rtl/hbregex.c +++ b/harbour/src/rtl/hbregex.c @@ -174,14 +174,13 @@ HB_FUNC( HB_REGEXCOMP ) { pRegEx->fFree = FALSE; hb_retptrGC( pRegEx ); - hb_gcUnlock( pRegEx ); } } } HB_FUNC( HB_ISREGEX ) { - hb_retl( hb_parptrGC( hb_regexRelease, 1 ) != NULL ); + hb_retl( hb_regexIs( hb_param( 1, HB_IT_ANY ) ) ); } HB_FUNC( HB_ATX ) diff --git a/harbour/src/rtl/hbregexc.c b/harbour/src/rtl/hbregexc.c index 001a6318de..662c6fdee8 100644 --- a/harbour/src/rtl/hbregexc.c +++ b/harbour/src/rtl/hbregexc.c @@ -90,19 +90,29 @@ void hb_regexInit( HB_REG_FREE pFree, HB_REG_COMP pComp, HB_REG_EXEC pExec ) } /* This releases regex when called from the garbage collector */ -HB_GARBAGE_FUNC( hb_regexRelease ) +static HB_GARBAGE_FUNC( hb_regexRelease ) { ( s_reg_free )( ( PHB_REGEX ) Cargo ); } +static const HB_GC_FUNCS s_gcRegexFuncs = +{ + hb_regexRelease, + hb_gcDummyMark +}; + +BOOL hb_regexIs( PHB_ITEM pItem ) +{ + return hb_itemGetPtrGC( pItem, &s_gcRegexFuncs ) != NULL; +} + PHB_REGEX hb_regexCompile( const char *szRegEx, ULONG ulLen, int iFlags ) { PHB_REGEX pRegEx; HB_SYMBOL_UNUSED( ulLen ); - pRegEx = ( PHB_REGEX ) hb_gcAlloc( sizeof( HB_REGEX ), hb_regexRelease ); - hb_gcLock( pRegEx ); + pRegEx = ( PHB_REGEX ) hb_gcAllocate( sizeof( HB_REGEX ), &s_gcRegexFuncs ); memset( pRegEx, 0, sizeof( HB_REGEX ) ); pRegEx->fFree = TRUE; pRegEx->iFlags = iFlags; @@ -124,7 +134,7 @@ PHB_REGEX hb_regexGet( PHB_ITEM pRegExItm, int iFlags ) { if( HB_IS_POINTER( pRegExItm ) ) { - pRegEx = ( PHB_REGEX ) hb_itemGetPtrGC( pRegExItm, hb_regexRelease ); + pRegEx = ( PHB_REGEX ) hb_itemGetPtrGC( pRegExItm, &s_gcRegexFuncs ); } else if( HB_IS_STRING( pRegExItm ) ) { diff --git a/harbour/src/rtl/hbzlibgz.c b/harbour/src/rtl/hbzlibgz.c index 97bccd74bb..1151c15c19 100644 --- a/harbour/src/rtl/hbzlibgz.c +++ b/harbour/src/rtl/hbzlibgz.c @@ -67,9 +67,15 @@ static HB_GARBAGE_FUNC( hb_gz_Destructor ) } } +static const HB_GC_FUNCS s_gcGZFuncs = +{ + hb_gz_Destructor, + hb_gcDummyMark +}; + static gzFile hb_gzParam( int iParam ) { - gzFile * gzHolder = ( gzFile * ) hb_parptrGC( hb_gz_Destructor, iParam ); + gzFile * gzHolder = ( gzFile * ) hb_parptrGC( &s_gcGZFuncs, iParam ); if( gzHolder && * gzHolder ) return * gzHolder; @@ -89,8 +95,8 @@ HB_FUNC( HB_GZOPEN ) gzFile gz = gzopen( cFile, cMode ); if( gz ) { - gzFile * gzHolder = ( gzFile * ) hb_gcAlloc( sizeof( gzFile ), - hb_gz_Destructor ); + gzFile * gzHolder = ( gzFile * ) hb_gcAllocate( sizeof( gzFile ), + &s_gcGZFuncs ); * gzHolder = gz; hb_retptrGC( gzHolder ); } @@ -110,8 +116,8 @@ HB_FUNC( HB_GZDOPEN ) gzFile gz = gzdopen( hb_parni( 1 ), cMode ); if( gz ) { - gzFile * gzHolder = ( gzFile * ) hb_gcAlloc( sizeof( gzFile ), - hb_gz_Destructor ); + gzFile * gzHolder = ( gzFile * ) hb_gcAllocate( sizeof( gzFile ), + &s_gcGZFuncs ); * gzHolder = gz; hb_retptrGC( gzHolder ); } @@ -125,7 +131,7 @@ HB_FUNC( HB_GZDOPEN ) */ HB_FUNC( HB_GZCLOSE ) { - gzFile * gzHolder = ( gzFile * ) hb_parptrGC( hb_gz_Destructor, 1 ); + gzFile * gzHolder = ( gzFile * ) hb_parptrGC( &s_gcGZFuncs, 1 ); if( gzHolder ) { diff --git a/harbour/src/vm/arrays.c b/harbour/src/vm/arrays.c index 1980b2b5a1..ffc35858c6 100644 --- a/harbour/src/vm/arrays.c +++ b/harbour/src/vm/arrays.c @@ -112,7 +112,7 @@ void hb_arrayPushBase( PHB_BASEARRAY pBaseArray ) } /* This releases array when called from the garbage collector */ -static HB_GARBAGE_FUNC( hb_arrayReleaseGarbage ) +static HB_GARBAGE_FUNC( hb_arrayGarbageRelease ) { PHB_BASEARRAY pBaseArray = ( PHB_BASEARRAY ) Cargo; @@ -155,6 +155,30 @@ static HB_GARBAGE_FUNC( hb_arrayReleaseGarbage ) hb_arrayReleaseItems( pBaseArray ); } +static HB_GARBAGE_FUNC( hb_arrayGarbageMark ) +{ + PHB_BASEARRAY pBaseArray = ( PHB_BASEARRAY ) Cargo; + + if( pBaseArray->ulLen ) + { + ULONG ulLen = pBaseArray->ulLen; + HB_ITEM_PTR pItems = pBaseArray->pItems; + + while( ulLen-- ) + { + if( HB_IS_GCITEM( pItems + ulLen ) ) + hb_gcItemRef( pItems + ulLen ); + } + } +} + +static const HB_GC_FUNCS s_gcArrayFuncs = +{ + hb_arrayGarbageRelease, + hb_arrayGarbageMark +}; + + BOOL hb_arrayNew( PHB_ITEM pItem, ULONG ulLen ) /* creates a new array */ { PHB_BASEARRAY pBaseArray; @@ -167,7 +191,7 @@ BOOL hb_arrayNew( PHB_ITEM pItem, ULONG ulLen ) /* creates a new array */ hb_itemClear( pItem ); /* - * allocate memory for items before hb_gcAlloc() to be + * allocate memory for items before hb_gcAllocRaw() to be * safe for automatic GC activation in hb_xgrab() without * calling hb_gcLock()/hb_gcUnlock(). [druzus] */ @@ -180,7 +204,7 @@ BOOL hb_arrayNew( PHB_ITEM pItem, ULONG ulLen ) /* creates a new array */ else pItems = NULL; - pBaseArray = ( PHB_BASEARRAY ) hb_gcAlloc( sizeof( HB_BASEARRAY ), hb_arrayReleaseGarbage ); + pBaseArray = ( PHB_BASEARRAY ) hb_gcAllocRaw( sizeof( HB_BASEARRAY ), &s_gcArrayFuncs ); pBaseArray->pItems = pItems; pBaseArray->ulLen = ulLen; pBaseArray->uiClass = 0; @@ -642,12 +666,12 @@ void * hb_arrayGetPtr( PHB_ITEM pArray, ULONG ulIndex ) return NULL; } -void * hb_arrayGetPtrGC( PHB_ITEM pArray, ULONG ulIndex, HB_GARBAGE_FUNC_PTR pFunc ) +void * hb_arrayGetPtrGC( PHB_ITEM pArray, ULONG ulIndex, const HB_GC_FUNCS * pFuncs ) { - HB_TRACE(HB_TR_DEBUG, ("hb_arrayGetPtrGC(%p, %lu, %p)", pArray, ulIndex, pFunc)); + HB_TRACE(HB_TR_DEBUG, ("hb_arrayGetPtrGC(%p, %lu, %p)", pArray, ulIndex, pFuncs)); if( HB_IS_ARRAY( pArray ) && ulIndex > 0 && ulIndex <= pArray->item.asArray.value->ulLen ) - return hb_itemGetPtrGC( pArray->item.asArray.value->pItems + ulIndex - 1, pFunc ); + return hb_itemGetPtrGC( pArray->item.asArray.value->pItems + ulIndex - 1, pFuncs ); else return NULL; } @@ -1463,13 +1487,10 @@ void hb_cloneNested( PHB_ITEM pDstItem, PHB_ITEM pSrcItem, PHB_NESTED_CLONED pCl hb_itemCopy( pDstItem, pSrcItem ); } -PHB_ITEM hb_arrayClone( PHB_ITEM pSrcArray ) +PHB_ITEM hb_arrayCloneTo( PHB_ITEM pDstArray, PHB_ITEM pSrcArray ) { - PHB_ITEM pDstArray; + HB_TRACE(HB_TR_DEBUG, ("hb_arrayCloneTo(%p,%p)", pDstArray, pSrcArray)); - HB_TRACE(HB_TR_DEBUG, ("hb_arrayClone(%p)", pSrcArray)); - - pDstArray = hb_itemNew( NULL ); if( HB_IS_ARRAY( pSrcArray ) ) { PHB_NESTED_CLONED pClonedList, pCloned; @@ -1495,6 +1516,13 @@ PHB_ITEM hb_arrayClone( PHB_ITEM pSrcArray ) return pDstArray; } +PHB_ITEM hb_arrayClone( PHB_ITEM pArray ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_arrayClone(%p)", pArray)); + + return hb_arrayCloneTo( hb_itemNew( NULL ), pArray ); +} + PHB_ITEM hb_arrayFromStack( USHORT uiLen ) { HB_STACK_TLS_PRELOAD diff --git a/harbour/src/vm/arrayshb.c b/harbour/src/vm/arrayshb.c index 08ec48abaf..a1cf3630c1 100644 --- a/harbour/src/vm/arrayshb.c +++ b/harbour/src/vm/arrayshb.c @@ -412,7 +412,7 @@ HB_FUNC( ACLONE ) PHB_ITEM pSrcArray = hb_param( 1, HB_IT_ARRAY ); if( pSrcArray && ! hb_arrayIsObject( pSrcArray ) ) - hb_itemReturnRelease( hb_arrayClone( pSrcArray ) ); /* AClone() returns the new array */ + hb_arrayCloneTo( hb_stackReturnItem(), pSrcArray ); /* AClone() returns the new array */ } HB_FUNC( HB_APARAMS ) diff --git a/harbour/src/vm/classes.c b/harbour/src/vm/classes.c index 9c5457510d..5a842d144b 100644 --- a/harbour/src/vm/classes.c +++ b/harbour/src/vm/classes.c @@ -2910,9 +2910,8 @@ static BOOL hb_clsAddMsg( USHORT uiClass, const char * szMessage, * and will operate on this value so it's not necessary * to keep the init value. [druzus] */ - pInit = hb_itemClone( pInit ); - hb_arraySet( pClass->pSharedDatas, pNewMeth->uiData, pInit ); - hb_itemRelease( pInit ); + hb_itemCloneTo( hb_arrayGetItemPtr( pClass->pSharedDatas, + pNewMeth->uiData ), pInit ); } pNewMeth->pFuncSym = &s___msgGetShrData; } @@ -3506,11 +3505,8 @@ static PHB_ITEM hb_clsInst( USHORT uiClass ) pDestItm = NULL; if( pDestItm ) - { - PHB_ITEM pInit = hb_itemClone( pInitData->pInitValue ); - hb_itemMove( pDestItm, pInit ); - hb_itemRelease( pInit ); - } + hb_itemCloneTo( pDestItm, pInitData->pInitValue ); + ++pInitData; } while( --ui ); @@ -3742,18 +3738,13 @@ HB_FUNC( __OBJSENDMSG ) */ HB_FUNC( __OBJCLONE ) { - PHB_ITEM pSrcObject = hb_param( 1, HB_IT_OBJECT ); - PHB_ITEM pDstObject; + HB_STACK_TLS_PRELOAD + PHB_ITEM pObject = hb_param( 1, HB_IT_OBJECT ); - if( pSrcObject ) - { - pDstObject = hb_arrayClone( pSrcObject ); - hb_itemReturnRelease( pDstObject ); - } + if( pObject ) + hb_arrayCloneTo( hb_stackReturnItem(), pObject ); else - { hb_errRT_BASE( EG_ARG, 3001, NULL, HB_ERR_FUNCNAME, 0 ); - } } /* diff --git a/harbour/src/vm/codebloc.c b/harbour/src/vm/codebloc.c index 2958c885dc..0f7a6db30f 100644 --- a/harbour/src/vm/codebloc.c +++ b/harbour/src/vm/codebloc.c @@ -68,11 +68,11 @@ static const BYTE s_pCode[ 2 ] = { HB_P_PUSHNIL, HB_P_ENDBLOCK }; /* Release all allocated memory when called from the garbage collector */ -static HB_GARBAGE_FUNC( hb_codeblockDeleteGarbage ) +static HB_GARBAGE_FUNC( hb_codeblockGarbageDelete ) { HB_CODEBLOCK_PTR pCBlock = ( HB_CODEBLOCK_PTR ) Cargo; - HB_TRACE(HB_TR_DEBUG, ("hb_codeblockDeleteGarbage(%p)", Cargo)); + HB_TRACE(HB_TR_DEBUG, ("hb_codeblockGarbageDelete(%p)", Cargo)); /* free space allocated for pcodes - if it was a macro-compiled codeblock */ @@ -105,6 +105,29 @@ static HB_GARBAGE_FUNC( hb_codeblockDeleteGarbage ) } } +static HB_GARBAGE_FUNC( hb_codeblockGarbageMark ) +{ + HB_CODEBLOCK_PTR pCBlock = ( HB_CODEBLOCK_PTR ) Cargo; + + HB_TRACE(HB_TR_DEBUG, ("hb_codeblockGarbageMark(%p)", Cargo)); + + if( pCBlock->uiLocals ) + { + PHB_ITEM pLocals = pCBlock->pLocals; + USHORT uiLocals = pCBlock->uiLocals; + + do + hb_gcItemRef( &pLocals[ uiLocals] ); + while( --uiLocals ); + } +} + +static const HB_GC_FUNCS s_gcCodeblockFuncs = +{ + hb_codeblockGarbageDelete, + hb_codeblockGarbageMark, +}; + /* Creates the codeblock structure * * pBuffer -> the buffer with pcodes (without HB_P_PUSHBLOCK) @@ -129,7 +152,7 @@ HB_CODEBLOCK_PTR hb_codeblockNew( const BYTE * pBuffer, HB_TRACE(HB_TR_DEBUG, ("hb_codeblockNew(%p, %hu, %p, %p, %lu)", pBuffer, uiLocals, pLocalPosTable, pSymbols, ulLen)); /* - * allocate memory for code block body and detach items hb_gcAlloc() + * allocate memory for code block body and detach items hb_gcAllocRaw() * to be safe for automatic GC activation in hb_xgrab() without * calling hb_gcLock()/hb_gcUnlock(). [druzus] */ @@ -215,7 +238,7 @@ HB_CODEBLOCK_PTR hb_codeblockNew( const BYTE * pBuffer, } pBase = hb_stackBaseItem(); - pCBlock = ( HB_CODEBLOCK_PTR ) hb_gcAlloc( sizeof( HB_CODEBLOCK ), hb_codeblockDeleteGarbage ); + pCBlock = ( HB_CODEBLOCK_PTR ) hb_gcAllocRaw( sizeof( HB_CODEBLOCK ), &s_gcCodeblockFuncs ); pCBlock->pCode = pCode; pCBlock->dynBuffer = ulLen != 0; @@ -246,14 +269,14 @@ HB_CODEBLOCK_PTR hb_codeblockMacroNew( const BYTE * pBuffer, ULONG ulLen ) * the passed buffer */ /* - * allocate memory for code block body and detach items hb_gcAlloc() + * allocate memory for code block body and detach items hb_gcAllocRaw() * to be safe for automatic GC activation in hb_xgrab() without * calling hb_gcLock()/hb_gcUnlock(). [druzus] */ pCode = ( BYTE * ) hb_xgrab( ulLen ); memcpy( pCode, pBuffer, ulLen ); - pCBlock = ( HB_CODEBLOCK_PTR ) hb_gcAlloc( sizeof( HB_CODEBLOCK ), hb_codeblockDeleteGarbage ); + pCBlock = ( HB_CODEBLOCK_PTR ) hb_gcAllocRaw( sizeof( HB_CODEBLOCK ), &s_gcCodeblockFuncs ); pBase = hb_stackBaseItem(); /* Store the number of referenced local variables */ pCBlock->pCode = pCode; diff --git a/harbour/src/vm/dynlibhb.c b/harbour/src/vm/dynlibhb.c index 8beccb4dc2..22685f19c7 100644 --- a/harbour/src/vm/dynlibhb.c +++ b/harbour/src/vm/dynlibhb.c @@ -81,6 +81,12 @@ static HB_GARBAGE_FUNC( hb_libRelease ) HB_SYMBOL_UNUSED( Cargo ); } +static const HB_GC_FUNCS s_gcDynlibFuncs = +{ + hb_libRelease, + hb_gcDummyMark +}; + HB_FUNC( HB_LIBLOAD ) { void * hDynLib = NULL; @@ -136,7 +142,7 @@ HB_FUNC( HB_LIBLOAD ) if( hDynLib ) { - void ** pLibPtr = ( void ** ) hb_gcAlloc( sizeof( void * ), hb_libRelease ); + void ** pLibPtr = ( void ** ) hb_gcAllocate( sizeof( void * ), &s_gcDynlibFuncs ); * pLibPtr = hDynLib; hb_retptrGC( pLibPtr ); } @@ -147,7 +153,7 @@ HB_FUNC( HB_LIBLOAD ) HB_FUNC( HB_LIBFREE ) { BOOL fResult = FALSE; - void ** pDynLibPtr = ( void ** ) hb_parptrGC( hb_libRelease, 1 ); + void ** pDynLibPtr = ( void ** ) hb_parptrGC( &s_gcDynlibFuncs, 1 ); if( pDynLibPtr && *pDynLibPtr && hb_vmLockModuleSymbols() ) diff --git a/harbour/src/vm/extend.c b/harbour/src/vm/extend.c index 3c854493eb..393262d872 100644 --- a/harbour/src/vm/extend.c +++ b/harbour/src/vm/extend.c @@ -645,11 +645,11 @@ void * hb_parptr( int iParam ) return NULL; } -void * hb_parptrGC( HB_GARBAGE_FUNC_PTR pFunc, int iParam ) +void * hb_parptrGC( const HB_GC_FUNCS * pFuncs, int iParam ) { HB_STACK_TLS_PRELOAD - HB_TRACE(HB_TR_DEBUG, ("hb_parptrGC(%p,%d)", pFunc, iParam)); + HB_TRACE(HB_TR_DEBUG, ("hb_parptrGC(%p,%d)", pFuncs, iParam)); if( iParam >= -1 && iParam <= hb_pcount() ) { @@ -659,7 +659,7 @@ void * hb_parptrGC( HB_GARBAGE_FUNC_PTR pFunc, int iParam ) pItem = hb_itemUnRef( pItem ); if( HB_IS_POINTER( pItem ) && pItem->item.asPointer.collect && - hb_gcFunc( pItem->item.asPointer.value ) == pFunc ) + hb_gcFuncs( pItem->item.asPointer.value ) == pFuncs ) return pItem->item.asPointer.value; } @@ -1235,11 +1235,11 @@ void * hb_parvptr( int iParam, ... ) return NULL; } -void * hb_parvptrGC( HB_GARBAGE_FUNC_PTR pFunc, int iParam, ... ) +void * hb_parvptrGC( const HB_GC_FUNCS * pFuncs, int iParam, ... ) { HB_STACK_TLS_PRELOAD - HB_TRACE(HB_TR_DEBUG, ("hb_parvptrGC(%p,%d, ...)", pFunc, iParam)); + HB_TRACE(HB_TR_DEBUG, ("hb_parvptrGC(%p,%d, ...)", pFuncs, iParam)); if( iParam >= -1 && iParam <= hb_pcount() ) { @@ -1251,7 +1251,7 @@ void * hb_parvptrGC( HB_GARBAGE_FUNC_PTR pFunc, int iParam, ... ) if( HB_IS_POINTER( pItem ) ) { if( pItem->item.asPointer.collect && - hb_gcFunc( pItem->item.asPointer.value ) == pFunc ) + hb_gcFuncs( pItem->item.asPointer.value ) == pFuncs ) return pItem->item.asPointer.value; } else if( HB_IS_ARRAY( pItem ) ) @@ -1266,7 +1266,7 @@ void * hb_parvptrGC( HB_GARBAGE_FUNC_PTR pFunc, int iParam, ... ) pItem = hb_arrayGetItemPtr( pItem, ulArrayIndex ); if( pItem && HB_IS_POINTER( pItem ) && pItem->item.asPointer.collect && - hb_gcFunc( pItem->item.asPointer.value ) == pFunc ) + hb_gcFuncs( pItem->item.asPointer.value ) == pFuncs ) return pItem->item.asPointer.value; } } diff --git a/harbour/src/vm/garbage.c b/harbour/src/vm/garbage.c index 0c39b5b64e..dafe9fadce 100644 --- a/harbour/src/vm/garbage.c +++ b/harbour/src/vm/garbage.c @@ -101,12 +101,11 @@ */ typedef struct HB_GARBAGE_ { - struct HB_GARBAGE_ *pNext; /* next memory block */ - struct HB_GARBAGE_ *pPrev; /* previous memory block */ - HB_GARBAGE_FUNC_PTR pFunc; /* cleanup function called before memory releasing */ - USHORT locked; /* locking counter */ - BYTE used; /* used/unused block */ - BYTE flags; /* HB_GC_USERSWEEP */ + struct HB_GARBAGE_ * pNext; /* next memory block */ + struct HB_GARBAGE_ * pPrev; /* previous memory block */ + const HB_GC_FUNCS * pFuncs; /* cleanup function called before memory releasing */ + USHORT locked; /* locking counter */ + USHORT used; /* used/unused block */ } HB_GARBAGE, *HB_GARBAGE_PTR; #ifdef HB_ALLOC_ALIGNMENT @@ -131,8 +130,6 @@ typedef struct HB_GARBAGE_ #define HB_GC_USED_FLAG 1 /* the bit for used/unused flag */ #define HB_GC_DELETE 2 /* item marked to delete */ #define HB_GC_DELETELST 4 /* item will be deleted during finalization */ -/* flags stored in 'flags' slot */ -#define HB_GC_USERSWEEP 8 /* memory block with user defined sweep function */ #ifdef HB_GC_AUTO /* number of allocated memory blocks */ @@ -162,20 +159,9 @@ static BOOL s_bCollecting = FALSE; /* flag for used/unused blocks - the meaning of the HB_GC_USED_FLAG bit * is reversed on every collecting attempt */ -static BYTE s_uUsedFlag = HB_GC_USED_FLAG; +static USHORT s_uUsedFlag = HB_GC_USED_FLAG; -/* list of functions that sweeps external memory blocks */ -typedef struct _HB_GARBAGE_EXTERN { - HB_GARBAGE_SWEEPER_PTR pFunc; - void * pBlock; - struct _HB_GARBAGE_EXTERN *pNext; -} HB_GARBAGE_EXTERN, *HB_GARBAGE_EXTERN_PTR; - -static HB_GARBAGE_EXTERN_PTR s_pSweepExtern = NULL; - -static void hb_gcUnregisterSweep( void * Cargo ); - static void hb_gcLink( HB_GARBAGE_PTR *pList, HB_GARBAGE_PTR pAlloc ) { if( *pList ) @@ -205,17 +191,46 @@ static void hb_gcUnlink( HB_GARBAGE_PTR *pList, HB_GARBAGE_PTR pAlloc ) } /* allocates a memory block */ -void * hb_gcAlloc( ULONG ulSize, HB_GARBAGE_FUNC_PTR pCleanupFunc ) +void * hb_gcAllocate( ULONG ulSize, const HB_GC_FUNCS * pFuncs ) { HB_GARBAGE_PTR pAlloc; pAlloc = HB_GARBAGE_NEW( ulSize ); if( pAlloc ) { - pAlloc->pFunc = pCleanupFunc; + pAlloc->pFuncs = pFuncs; + pAlloc->locked = 1; + pAlloc->used = s_uUsedFlag; + HB_GC_LOCK +#ifdef HB_GC_AUTO + if( s_ulBlocks > s_ulBlocksMarked + 100000 ) + { + HB_GC_UNLOCK + hb_gcCollectAll( TRUE ); + HB_GC_LOCK + pAlloc->used = s_uUsedFlag; + } +#endif + hb_gcLink( &s_pLockedBlock, pAlloc ); + HB_GC_UNLOCK + + return HB_BLOCK_PTR( pAlloc ); /* hide the internal data */ + } + else + return NULL; +} + +/* allocates a memory block */ +void * hb_gcAllocRaw( ULONG ulSize, const HB_GC_FUNCS * pFuncs ) +{ + HB_GARBAGE_PTR pAlloc; + + pAlloc = HB_GARBAGE_NEW( ulSize ); + if( pAlloc ) + { + pAlloc->pFuncs = pFuncs; pAlloc->locked = 0; pAlloc->used = s_uUsedFlag; - pAlloc->flags = 0; HB_GC_LOCK #ifdef HB_GC_AUTO @@ -224,6 +239,7 @@ void * hb_gcAlloc( ULONG ulSize, HB_GARBAGE_FUNC_PTR pCleanupFunc ) HB_GC_UNLOCK hb_gcCollectAll( TRUE ); HB_GC_LOCK + pAlloc->used = s_uUsedFlag; } HB_GC_AUTO_INC #endif @@ -236,7 +252,7 @@ void * hb_gcAlloc( ULONG ulSize, HB_GARBAGE_FUNC_PTR pCleanupFunc ) return NULL; } -/* release a memory block allocated with hb_gcAlloc() */ +/* release a memory block allocated with hb_gcAlloc*() */ void hb_gcFree( void *pBlock ) { if( pBlock ) @@ -256,9 +272,6 @@ void hb_gcFree( void *pBlock ) } HB_GC_UNLOCK - if( pAlloc->flags & HB_GC_USERSWEEP ) - hb_gcUnregisterSweep( pBlock ); - HB_GARBAGE_FREE( pAlloc ); } } @@ -269,9 +282,9 @@ void hb_gcFree( void *pBlock ) } /* return cleanup function pointer */ -HB_GARBAGE_FUNC_PTR hb_gcFunc( void *pBlock ) +const HB_GC_FUNCS * hb_gcFuncs( void *pBlock ) { - return HB_GC_PTR( pBlock )->pFunc; + return HB_GC_PTR( pBlock )->pFuncs; } /* increment reference counter */ @@ -317,8 +330,7 @@ void hb_gcRefFree( void * pBlock ) pAlloc->used |= HB_GC_DELETE; /* execute clean-up function */ - if( pAlloc->pFunc ) - ( pAlloc->pFunc )( pBlock ); + pAlloc->pFuncs->clear( pBlock ); if( pAlloc->used & HB_GC_DELETE ) HB_GARBAGE_FREE( pAlloc ); @@ -366,6 +378,16 @@ void hb_gcRefCheck( void * pBlock ) } +HB_GARBAGE_FUNC( hb_gcDummyMark ) +{ + HB_SYMBOL_UNUSED( Cargo ); +} + +HB_GARBAGE_FUNC( hb_gcGripMark ) +{ + hb_gcItemRef( ( HB_ITEM_PTR ) Cargo ); +} + static HB_GARBAGE_FUNC( hb_gcGripRelease ) { /* Item was already released in hb_gcGripDrop() - then we have nothing @@ -374,6 +396,13 @@ static HB_GARBAGE_FUNC( hb_gcGripRelease ) HB_SYMBOL_UNUSED( Cargo ); } + +static const HB_GC_FUNCS s_gcGripFuncs = +{ + hb_gcGripRelease, + hb_gcGripMark +}; + HB_ITEM_PTR hb_gcGripGet( HB_ITEM_PTR pOrigin ) { HB_GARBAGE_PTR pAlloc; @@ -383,10 +412,9 @@ HB_ITEM_PTR hb_gcGripGet( HB_ITEM_PTR pOrigin ) { HB_ITEM_PTR pItem = ( HB_ITEM_PTR ) HB_BLOCK_PTR( pAlloc ); - pAlloc->pFunc = hb_gcGripRelease; + pAlloc->pFuncs = &s_gcGripFuncs; pAlloc->locked = 1; pAlloc->used = s_uUsedFlag; - pAlloc->flags = 0; pItem->type = HB_IT_NIL; @@ -452,6 +480,32 @@ void * hb_gcUnlock( void * pBlock ) { HB_GARBAGE_PTR pAlloc = HB_GC_PTR( pBlock ); + if( pAlloc->locked ) + { + HB_GC_LOCK + if( pAlloc->locked ) + { + if( --pAlloc->locked == 0 ) + { + pAlloc->used = s_uUsedFlag; + + hb_gcUnlink( &s_pLockedBlock, pAlloc ); + hb_gcLink( &s_pCurrBlock, pAlloc ); + HB_GC_AUTO_INC + } + } + HB_GC_UNLOCK + } + } + return pBlock; +} + +void hb_gcAttach( void * pBlock ) +{ + HB_GARBAGE_PTR pAlloc = HB_GC_PTR( pBlock ); + + if( pAlloc->locked ) + { HB_GC_LOCK if( pAlloc->locked ) { @@ -466,7 +520,18 @@ void * hb_gcUnlock( void * pBlock ) } HB_GC_UNLOCK } - return pBlock; +} + +/* mark passed memory block as used so it will be not released by the GC */ +void hb_gcMark( void * pBlock ) +{ + HB_GARBAGE_PTR pAlloc = HB_GC_PTR( pBlock ); + + if( pAlloc->used == s_uUsedFlag ) + { + pAlloc->used ^= HB_GC_USED_FLAG; /* mark this codeblock as used */ + pAlloc->pFuncs->mark( pBlock ); + } } /* Mark a passed item as used so it will be not released by the GC @@ -490,14 +555,10 @@ void hb_gcItemRef( HB_ITEM_PTR pItem ) HB_GARBAGE_PTR pAlloc = HB_GC_PTR( pItem->item.asRefer.BasePtr.array ); if( pAlloc->used == s_uUsedFlag ) { - ULONG ulSize = pItem->item.asRefer.BasePtr.array->ulLen; + /* mark this array as used */ pAlloc->used ^= HB_GC_USED_FLAG; - pItem = pItem->item.asRefer.BasePtr.array->pItems; - while( ulSize ) - { - hb_gcItemRef( pItem++ ); - --ulSize; - } + /* mark also all array elements */ + pAlloc->pFuncs->mark( HB_BLOCK_PTR( pAlloc ) ); } return; } @@ -511,19 +572,12 @@ void hb_gcItemRef( HB_ITEM_PTR pItem ) /* Check this array only if it was not checked yet */ if( pAlloc->used == s_uUsedFlag ) { - ULONG ulSize = pItem->item.asArray.value->ulLen; - /* mark this block as used so it will be no re-checked from + /* 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 */ - pItem = pItem->item.asArray.value->pItems; - while( ulSize ) - { - hb_gcItemRef( pItem++ ); - --ulSize; - } + pAlloc->pFuncs->mark( HB_BLOCK_PTR( pAlloc ) ); } } else if( HB_IS_HASH( pItem ) ) @@ -533,13 +587,10 @@ void hb_gcItemRef( HB_ITEM_PTR pItem ) /* Check this hash table only if it was not checked yet */ if( pAlloc->used == s_uUsedFlag ) { - /* mark this block as used so it will be no re-checked from - * other references - */ + /* mark this hash table as used */ pAlloc->used ^= HB_GC_USED_FLAG; - /* mark also all hash elements */ - hb_hashRefGrabage( pItem ); + pAlloc->pFuncs->mark( HB_BLOCK_PTR( pAlloc ) ); } } else if( HB_IS_BLOCK( pItem ) ) @@ -548,16 +599,10 @@ void hb_gcItemRef( HB_ITEM_PTR pItem ) if( pAlloc->used == s_uUsedFlag ) { - HB_CODEBLOCK_PTR pCBlock = pItem->item.asBlock.value; - USHORT ui = 1; - - pAlloc->used ^= HB_GC_USED_FLAG; /* mark this codeblock as used */ - + /* mark this codeblock as used */ + pAlloc->used ^= HB_GC_USED_FLAG; /* mark as used all detached variables in a codeblock */ - while( ui <= pCBlock->uiLocals ) - { - hb_gcItemRef( &pCBlock->pLocals[ ui++ ] ); - } + pAlloc->pFuncs->mark( HB_BLOCK_PTR( pAlloc ) ); } } else if( HB_IS_POINTER( pItem ) ) @@ -568,83 +613,16 @@ void hb_gcItemRef( HB_ITEM_PTR pItem ) if( pAlloc->used == s_uUsedFlag ) { - if( ! (pAlloc->flags & HB_GC_USERSWEEP) ) - { - /* Mark this pointer as used only if it doesn't have - registerd his own sweeper function that checks if - this pointer is still used. - The sweeper function will be called elsewhere. - */ - pAlloc->used ^= HB_GC_USED_FLAG; /* mark this codeblock as used */ - } + /* 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 */ } -/* Register a function which sweeps memory blocks stored outside of - * internal harbour structures - * - * NOTICE!: Cargo have to be a pointer to memory allocated with - * hb_gcAlloc() - */ -void hb_gcRegisterSweep( HB_GARBAGE_SWEEPER_PTR pSweep, void * Cargo ) -{ - HB_GARBAGE_EXTERN_PTR pExt; - - pExt = ( HB_GARBAGE_EXTERN_PTR ) hb_xgrab( sizeof( HB_GARBAGE_EXTERN ) ); - pExt->pFunc = pSweep; - pExt->pBlock = Cargo; - - HB_GC_LOCK - pExt->pNext = s_pSweepExtern; - s_pSweepExtern = pExt; - HB_GC_UNLOCK - - /* set user sweep flag */ - HB_GC_PTR( Cargo )->flags ^= HB_GC_USERSWEEP; -} - -static void hb_gcUnregisterSweep( void * Cargo ) -{ - HB_GARBAGE_EXTERN_PTR pExt; - HB_GARBAGE_EXTERN_PTR pPrev; - - HB_GC_LOCK - - pPrev = pExt = s_pSweepExtern; - while( pExt ) - { - if( pExt->pBlock == Cargo ) - { - HB_GARBAGE_PTR pAlloc = HB_GC_PTR( Cargo ); - - /* clear user sweep flag */ - pAlloc->flags &= ~ HB_GC_USERSWEEP; - - if( pExt == s_pSweepExtern ) - { - s_pSweepExtern = pExt->pNext; - } - else - { - pPrev->pNext = pExt->pNext; - } - - hb_xfree( (void *) pExt ); - pExt = NULL; - } - else - { - pPrev = pExt; - pExt = pExt->pNext; - } - } - - HB_GC_UNLOCK -} - void hb_gcCollect( void ) { /* TODO: decrease the amount of time spend collecting */ @@ -683,32 +661,6 @@ void hb_gcCollectAll( BOOL fForce ) hb_vmIsStaticRef(); hb_clsIsClassRef(); - if( s_pSweepExtern ) - { - HB_GARBAGE_EXTERN_PTR *pExtPtr = &s_pSweepExtern; - - do - { - pAlloc = HB_GC_PTR( ( *pExtPtr )->pBlock ); - - if( ( ( *pExtPtr )->pFunc )( ( *pExtPtr )->pBlock ) ) - { - /* block is still used */ - pAlloc->used ^= HB_GC_USED_FLAG; - pExtPtr = &( *pExtPtr )->pNext; - } - else - { - HB_GARBAGE_EXTERN_PTR pFree = *pExtPtr; - - pAlloc->flags &= ~ HB_GC_USERSWEEP; - *pExtPtr = ( *pExtPtr )->pNext; - hb_xfree( pFree ); - } - } - while( *pExtPtr ); - } - /* check list of locked block for blocks referenced from * locked block */ @@ -716,11 +668,8 @@ void hb_gcCollectAll( BOOL fForce ) { pAlloc = s_pLockedBlock; do - { /* it is not very elegant method but it works well */ - if( pAlloc->pFunc == hb_gcGripRelease ) - { - hb_gcItemRef( ( HB_ITEM_PTR ) HB_BLOCK_PTR( pAlloc ) ); - } + { + pAlloc->pFuncs->mark( HB_BLOCK_PTR( pAlloc ) ); pAlloc = pAlloc->pNext; } while( s_pLockedBlock != pAlloc ); } @@ -781,8 +730,7 @@ void hb_gcCollectAll( BOOL fForce ) pAlloc = s_pDeletedBlock; do { - if( s_pDeletedBlock->pFunc ) - ( s_pDeletedBlock->pFunc )( HB_BLOCK_PTR( s_pDeletedBlock ) ); + s_pDeletedBlock->pFuncs->clear( HB_BLOCK_PTR( s_pDeletedBlock ) ); s_pDeletedBlock = s_pDeletedBlock->pNext; @@ -829,13 +777,8 @@ void hb_gcReleaseAll( void ) do { /* call a cleanup function */ - if( s_pCurrBlock->pFunc ) - { - HB_TRACE( HB_TR_INFO, ( "Cleanup, %p", s_pCurrBlock ) ); - - s_pCurrBlock->used |= HB_GC_DELETE | HB_GC_DELETELST; - ( s_pCurrBlock->pFunc )( HB_BLOCK_PTR( s_pCurrBlock ) ); - } + s_pCurrBlock->used |= HB_GC_DELETE | HB_GC_DELETELST; + s_pCurrBlock->pFuncs->clear( HB_BLOCK_PTR( s_pCurrBlock ) ); s_pCurrBlock = s_pCurrBlock->pNext; diff --git a/harbour/src/vm/hashes.c b/harbour/src/vm/hashes.c index ae7af8b721..d8bf644b60 100644 --- a/harbour/src/vm/hashes.c +++ b/harbour/src/vm/hashes.c @@ -82,31 +82,12 @@ typedef struct _HB_BASEHASH } HB_BASEHASH, * PHB_BASEHASH, * HB_BASEHASH_PTR; -void hb_hashRefGrabage( PHB_ITEM pHash ) -{ - HB_TRACE(HB_TR_DEBUG, ("hb_hashRefGrabage(%p)", pHash)); - - if( HB_IS_HASH( pHash ) && pHash->item.asHash.value->ulLen > 0 ) - { - PHB_HASHPAIR pPairs = pHash->item.asHash.value->pPairs; - ULONG ulLen = pHash->item.asHash.value->ulLen; - - while( ulLen-- ) - { - if( HB_IS_GCITEM( &pPairs[ ulLen ].key ) ) - hb_gcItemRef( &pPairs[ ulLen ].key ); - if( HB_IS_GCITEM( &pPairs[ ulLen ].value ) ) - hb_gcItemRef( &pPairs[ ulLen ].value ); - } - } -} - /* This releases hash when called from the garbage collector */ -static HB_GARBAGE_FUNC( hb_hashReleaseGarbage ) +static HB_GARBAGE_FUNC( hb_hashGarbageRelease ) { PHB_BASEHASH pBaseHash = ( PHB_BASEHASH ) Cargo; - HB_TRACE(HB_TR_INFO, ("hb_hashReleaseGarbage(%p)", pBaseHash )); + HB_TRACE(HB_TR_INFO, ("hb_hashGarbageRelease(%p)", pBaseHash )); if( pBaseHash->ulSize > 0 ) { @@ -138,6 +119,35 @@ static HB_GARBAGE_FUNC( hb_hashReleaseGarbage ) } } +static HB_GARBAGE_FUNC( hb_hashGarbageMark ) +{ + PHB_BASEHASH pBaseHash = ( PHB_BASEHASH ) Cargo; + + HB_TRACE(HB_TR_INFO, ("hb_hashMarkGarbage(%p)", pBaseHash )); + + if( pBaseHash->ulLen > 0 ) + { + PHB_HASHPAIR pPairs = pBaseHash->pPairs; + ULONG ulLen = pBaseHash->ulLen; + + while( ulLen-- ) + { + if( HB_IS_GCITEM( &pPairs[ ulLen ].key ) ) + hb_gcItemRef( &pPairs[ ulLen ].key ); + if( HB_IS_GCITEM( &pPairs[ ulLen ].value ) ) + hb_gcItemRef( &pPairs[ ulLen ].value ); + } + } + if( pBaseHash->pDefault && HB_IS_GCITEM( pBaseHash->pDefault ) ) + hb_gcItemRef( pBaseHash->pDefault ); +} + +static const HB_GC_FUNCS s_gcHashFuncs = +{ + hb_hashGarbageRelease, + hb_hashGarbageMark +}; + static int hb_hashItemCmp( PHB_ITEM pKey1, PHB_ITEM pKey2, int iFlags ) { if( HB_IS_STRING( pKey1 ) ) @@ -306,11 +316,7 @@ static PHB_ITEM hb_hashValuePtr( PHB_BASEHASH pBaseHash, PHB_ITEM pKey, BOOL fAd hb_itemCopy( &pBaseHash->pPairs[ ulPos ].key, pKey ); pBaseHash->ulLen++; if( pBaseHash->pDefault ) - { - PHB_ITEM pDefault = hb_itemClone( pBaseHash->pDefault ); - hb_itemMove( &pBaseHash->pPairs[ ulPos ].value, pDefault ); - hb_itemRelease( pDefault ); - } + hb_itemCloneTo( &pBaseHash->pPairs[ ulPos ].value, pBaseHash->pDefault ); } return &pBaseHash->pPairs[ ulPos ].value; @@ -399,7 +405,7 @@ PHB_ITEM hb_hashNew( PHB_ITEM pItem ) else if( HB_IS_COMPLEX( pItem ) ) hb_itemClear( pItem ); - pBaseHash = ( PHB_BASEHASH ) hb_gcAlloc( sizeof( HB_BASEHASH ), hb_hashReleaseGarbage ); + pBaseHash = ( PHB_BASEHASH ) hb_gcAllocRaw( sizeof( HB_BASEHASH ), &s_gcHashFuncs ); pBaseHash->pPairs = NULL; pBaseHash->ulSize = 0; pBaseHash->ulLen = 0; @@ -720,8 +726,11 @@ void hb_hashCloneBody( PHB_ITEM pHash, PHB_ITEM pDest, PHB_NESTED_CLONED pCloned hb_hashResize( pDest->item.asHash.value, pHash->item.asHash.value->ulSize ); pDest->item.asHash.value->iFlags = pHash->item.asHash.value->iFlags; if( pHash->item.asHash.value->pDefault ) + { pDest->item.asHash.value->pDefault = hb_itemNew( pHash->item.asHash.value->pDefault ); + hb_gcUnlock( pDest->item.asHash.value->pDefault ); + } for( ulPos = 0; ulPos < pHash->item.asHash.value->ulLen; ++ulPos ) { PHB_ITEM pValue = &pHash->item.asHash.value->pPairs[ ulPos ].value; @@ -734,13 +743,10 @@ void hb_hashCloneBody( PHB_ITEM pHash, PHB_ITEM pDest, PHB_NESTED_CLONED pCloned } } -PHB_ITEM hb_hashClone( PHB_ITEM pHash ) +PHB_ITEM hb_hashCloneTo( PHB_ITEM pDest, PHB_ITEM pHash ) { - PHB_ITEM pDest; + HB_TRACE(HB_TR_DEBUG, ("hb_hashCloneTo(%p,%p)", pDest, pHash)); - HB_TRACE(HB_TR_DEBUG, ("hb_hashClone(%p)", pHash)); - - pDest = hb_itemNew( NULL ); if( HB_IS_HASH( pHash ) ) { PHB_NESTED_CLONED pClonedList, pCloned; @@ -764,6 +770,13 @@ PHB_ITEM hb_hashClone( PHB_ITEM pHash ) return pDest; } +PHB_ITEM hb_hashClone( PHB_ITEM pHash ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_hashClone(%p)", pHash)); + + return hb_hashCloneTo( hb_itemNew( NULL ), pHash ); +} + void hb_hashJoin( PHB_ITEM pDest, PHB_ITEM pSource, int iType ) { HB_TRACE(HB_TR_DEBUG, ("hb_hashJoin(%p,%p,%d)", pDest, pSource, iType)); @@ -882,7 +895,10 @@ void hb_hashSetDefault( PHB_ITEM pHash, PHB_ITEM pValue ) if( pValue && !HB_IS_NIL( pValue ) && ( !HB_IS_HASH( pValue ) || pHash->item.asHash.value != pValue->item.asHash.value ) ) + { pHash->item.asHash.value->pDefault = hb_itemClone( pValue ); + hb_gcUnlock( pHash->item.asHash.value->pDefault ); + } } } diff --git a/harbour/src/vm/hashfunc.c b/harbour/src/vm/hashfunc.c index 4c9b1137ac..5d9cfcc154 100644 --- a/harbour/src/vm/hashfunc.c +++ b/harbour/src/vm/hashfunc.c @@ -313,7 +313,7 @@ HB_FUNC( HB_HCLONE ) PHB_ITEM pHash = hb_param( 1, HB_IT_HASH ); if( pHash ) - hb_itemReturnRelease( hb_hashClone( pHash ) ); + hb_hashCloneTo( hb_stackReturnItem(), pHash ); else hb_errRT_BASE( EG_ARG, 1123, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); } diff --git a/harbour/src/vm/hvm.c b/harbour/src/vm/hvm.c index 7a1e851a16..39f61f2753 100644 --- a/harbour/src/vm/hvm.c +++ b/harbour/src/vm/hvm.c @@ -4366,12 +4366,15 @@ static void hb_vmForTest( void ) /* Test to check the end point of the FO /* Begin Sequence WITH block auto destructor */ static HB_GARBAGE_FUNC( hb_SeqBlockDestructor ) { - PHB_ITEM * pBlockPtr = ( PHB_ITEM * ) Cargo; - - hb_itemMove( hb_errorBlock(), * pBlockPtr ); - hb_itemRelease( * pBlockPtr ); + hb_itemMove( hb_errorBlock(), ( PHB_ITEM ) Cargo ); } +static const HB_GC_FUNCS s_gcSeqBlockFuncs = +{ + hb_SeqBlockDestructor, + hb_gcGripMark +}; + static void hb_vmSeqBlock( void ) { HB_STACK_TLS_PRELOAD @@ -4382,16 +4385,15 @@ static void hb_vmSeqBlock( void ) pItem = hb_stackItemFromTop( -1 ); if( HB_IS_BLOCK( pItem ) ) { - PHB_ITEM * pBlockPtr, pBlock, pHolder; + PHB_ITEM pBlockCopy, pBlock; pBlock = hb_errorBlock(); - pHolder = hb_itemNew( pBlock ); - hb_itemMove( pBlock, pItem ); - pBlockPtr = ( PHB_ITEM * ) hb_gcAlloc( sizeof( PHB_ITEM ), - hb_SeqBlockDestructor ); - * pBlockPtr = pHolder; + pBlockCopy = ( PHB_ITEM ) hb_gcAllocRaw( sizeof( HB_ITEM ), + &s_gcSeqBlockFuncs ); + hb_itemRawCpy( pBlockCopy, pBlock ); + hb_itemRawCpy( pBlock, pItem ); pItem->type = HB_IT_POINTER; - pItem->item.asPointer.value = pBlockPtr; + pItem->item.asPointer.value = pBlockCopy; pItem->item.asPointer.collect = pItem->item.asPointer.single = TRUE; } } @@ -4404,6 +4406,13 @@ static HB_GARBAGE_FUNC( hb_withObjectDestructor ) hb_stackWithObjectSetOffset( * plWithObjectBase ); } +static const HB_GC_FUNCS s_gcWithObjectFuncs = +{ + hb_withObjectDestructor, + hb_gcDummyMark +}; + + static void hb_vmWithObjectStart( void ) { HB_STACK_TLS_PRELOAD @@ -4413,8 +4422,8 @@ static void hb_vmWithObjectStart( void ) HB_TRACE(HB_TR_DEBUG, ("hb_vmWithObjectStart()")); pItem = hb_stackAllocItem(); - plWithObjectBase = ( LONG * ) hb_gcAlloc( sizeof( LONG ), - hb_withObjectDestructor ); + plWithObjectBase = ( LONG * ) hb_gcAllocRaw( sizeof( LONG ), + &s_gcWithObjectFuncs ); * plWithObjectBase = hb_stackWithObjectOffset(); pItem->type = HB_IT_POINTER; pItem->item.asPointer.value = plWithObjectBase; @@ -6298,14 +6307,7 @@ static PHB_ITEM hb_vmTSVRefRead( PHB_ITEM pRefer ) if( !pItem ) { pItem = ( PHB_ITEM ) hb_stackGetTSD( &pTSVRef->threadData ); - if( HB_ITEM_TYPERAW( &pTSVRef->source ) & ( HB_IT_ARRAY | HB_IT_HASH ) ) - { - PHB_ITEM pClone = hb_itemClone( &pTSVRef->source ); - hb_itemCopy( pItem, pClone ); - hb_itemRelease( pClone ); - } - else - hb_itemCopy( pItem, &pTSVRef->source ); + hb_itemCloneTo( pItem, &pTSVRef->source ); } return pItem; } diff --git a/harbour/src/vm/hvmall.c b/harbour/src/vm/hvmall.c index bd6c36e517..30f6b4fa91 100644 --- a/harbour/src/vm/hvmall.c +++ b/harbour/src/vm/hvmall.c @@ -71,6 +71,10 @@ #define INCL_DOSPROCESS #define INCL_NOPMAPI +/* For Linux and mremap() function */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif /* warning the order of included files is important * due to macros used to overload some functions diff --git a/harbour/src/vm/itemapi.c b/harbour/src/vm/itemapi.c index 1e07f4014f..247965105a 100644 --- a/harbour/src/vm/itemapi.c +++ b/harbour/src/vm/itemapi.c @@ -715,13 +715,13 @@ void * hb_itemGetPtr( PHB_ITEM pItem ) return NULL; } -void * hb_itemGetPtrGC( PHB_ITEM pItem, HB_GARBAGE_FUNC_PTR pFunc ) +void * hb_itemGetPtrGC( PHB_ITEM pItem, const HB_GC_FUNCS * pFuncs ) { - HB_TRACE(HB_TR_DEBUG, ("hb_itemGetPtrGC(%p,%p)", pItem, pFunc)); + HB_TRACE(HB_TR_DEBUG, ("hb_itemGetPtrGC(%p,%p)", pItem, pFuncs)); if( pItem && HB_IS_POINTER( pItem ) && pItem->item.asPointer.collect && - hb_gcFunc( pItem->item.asPointer.value ) == pFunc ) + hb_gcFuncs( pItem->item.asPointer.value ) == pFuncs ) return pItem->item.asPointer.value; else return NULL; @@ -1302,6 +1302,8 @@ PHB_ITEM hb_itemPutPtrGC( PHB_ITEM pItem, void * pValue ) pItem->item.asPointer.collect = TRUE; pItem->item.asPointer.single = FALSE; + hb_gcAttach( pValue ); + return pItem; } @@ -2031,17 +2033,27 @@ PHB_ITEM hb_itemClone( PHB_ITEM pItem ) HB_TRACE_STEALTH(HB_TR_DEBUG, ("hb_itemClone(%p)", pItem)); if( HB_IS_ARRAY( pItem ) ) - { return hb_arrayClone( pItem ); - } + else if( HB_IS_HASH( pItem ) ) - { return hb_hashClone( pItem ); - } + else - { return hb_itemNew( pItem ); - } +} + +PHB_ITEM hb_itemCloneTo( PHB_ITEM pDest, PHB_ITEM pSource ) +{ + HB_TRACE_STEALTH(HB_TR_DEBUG, ("hb_itemCloneTo(%p,%p)", pDest, pSource)); + + if( HB_IS_ARRAY( pSource ) ) + return hb_arrayCloneTo( pDest, pSource ); + + else if( HB_IS_HASH( pSource ) ) + return hb_hashCloneTo( pDest, pSource ); + + hb_itemCopy( pDest, pSource ); + return pDest; } diff --git a/harbour/src/vm/maindllh.c b/harbour/src/vm/maindllh.c index 7879d0e8cb..cbc9d4b435 100644 --- a/harbour/src/vm/maindllh.c +++ b/harbour/src/vm/maindllh.c @@ -68,7 +68,7 @@ HB_EXPORT BOOL WINAPI HB_DLL_ENTRY_POINT( HANDLE hInstance, DWORD fdwReason, PVO HB_EXPORT BOOL WINAPI HB_DLL_ENTRY_POINT( HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved ) #endif { - HB_TRACE( HB_TR_DEBUG, ("DllEntryPoint(%p, %p, %d)", hInstance, fdwReason, + HB_TRACE( HB_TR_DEBUG, ("DllEntryPoint(%p, %lu, %p)", hInstance, fdwReason, pvReserved ) ); HB_SYMBOL_UNUSED( hInstance ); diff --git a/harbour/src/vm/maindllp.c b/harbour/src/vm/maindllp.c index bb13cf044d..bf48ec2de0 100644 --- a/harbour/src/vm/maindllp.c +++ b/harbour/src/vm/maindllp.c @@ -146,7 +146,7 @@ HB_EXPORT BOOL WINAPI HB_DLL_ENTRY_POINT( HANDLE hInstance, DWORD fdwReason, PVO HB_EXPORT BOOL WINAPI HB_DLL_ENTRY_POINT( HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved ) #endif { - HB_TRACE( HB_TR_DEBUG, ("DllEntryPoint(%p, %p, %d)", hInstance, fdwReason, + HB_TRACE( HB_TR_DEBUG, ("DllEntryPoint(%p, %lu, %p)", hInstance, fdwReason, pvReserved ) ); HB_SYMBOL_UNUSED( hInstance ); diff --git a/harbour/src/vm/runner.c b/harbour/src/vm/runner.c index f6d03667de..9e832ff3ab 100644 --- a/harbour/src/vm/runner.c +++ b/harbour/src/vm/runner.c @@ -646,17 +646,23 @@ static HB_GARBAGE_FUNC( hb_hrb_Destructor ) } } +static const HB_GC_FUNCS s_gcHrbFuncs = +{ + hb_hrb_Destructor, + hb_gcDummyMark +}; + static PHRB_BODY hb_hrbParam( int iParam ) { - PHRB_BODY * pHrbPtr = ( PHRB_BODY * ) hb_parptrGC( hb_hrb_Destructor, iParam ); + PHRB_BODY * pHrbPtr = ( PHRB_BODY * ) hb_parptrGC( &s_gcHrbFuncs, iParam ); return pHrbPtr ? *pHrbPtr : NULL; } static void hb_hrbReturn( PHRB_BODY pHrbBody ) { - PHRB_BODY * pHrbPtr = ( PHRB_BODY * ) hb_gcAlloc( sizeof( PHRB_BODY ), - hb_hrb_Destructor ); + PHRB_BODY * pHrbPtr = ( PHRB_BODY * ) hb_gcAllocate( sizeof( PHRB_BODY ), + &s_gcHrbFuncs ); *pHrbPtr = pHrbBody; hb_retptrGC( pHrbPtr ); } @@ -798,7 +804,7 @@ HB_FUNC( HB_HRBDO ) HB_FUNC( HB_HRBUNLOAD ) { - PHRB_BODY * pHrbPtr = ( PHRB_BODY * ) hb_parptrGC( hb_hrb_Destructor, 1 ); + PHRB_BODY * pHrbPtr = ( PHRB_BODY * ) hb_parptrGC( &s_gcHrbFuncs, 1 ); if( pHrbPtr ) { diff --git a/harbour/src/vm/thread.c b/harbour/src/vm/thread.c index 296b944f38..ab5aaa8cbb 100644 --- a/harbour/src/vm/thread.c +++ b/harbour/src/vm/thread.c @@ -903,6 +903,12 @@ static HB_GARBAGE_FUNC( hb_threadDestructor ) #endif } +static const HB_GC_FUNCS s_gcThreadFuncs = +{ + hb_threadDestructor, + hb_gcDummyMark +}; + static HB_THREAD_STARTFUNC( hb_threadStartVM ) { #if defined( HB_MT_VM ) @@ -911,7 +917,7 @@ static HB_THREAD_STARTFUNC( hb_threadStartVM ) PHB_THREADSTATE pThread; BOOL fSend = FALSE; - pThread = ( PHB_THREADSTATE ) hb_itemGetPtrGC( pThItm, hb_threadDestructor ); + pThread = ( PHB_THREADSTATE ) hb_itemGetPtrGC( pThItm, &s_gcThreadFuncs ); hb_vmThreadInit( ( void * ) pThread ); @@ -994,7 +1000,7 @@ PHB_THREADSTATE hb_threadStateNew( void ) pThItm = hb_itemNew( NULL ); pThread = ( PHB_THREADSTATE ) - hb_gcAlloc( sizeof( HB_THREADSTATE ), hb_threadDestructor ); + hb_gcAllocRaw( sizeof( HB_THREADSTATE ), &s_gcThreadFuncs ); memset( pThread, 0, sizeof( HB_THREADSTATE ) ); hb_itemPutPtrGC( pThItm, pThread ); @@ -1017,7 +1023,7 @@ PHB_THREADSTATE hb_threadStateNew( void ) static PHB_THREADSTATE hb_thParam( int iParam, int iPos ) { PHB_THREADSTATE pThread = ( PHB_THREADSTATE ) - hb_parvptrGC( hb_threadDestructor, iParam, iPos ); + hb_parvptrGC( &s_gcThreadFuncs, iParam, iPos ); if( pThread ) return pThread; @@ -1641,16 +1647,22 @@ static HB_GARBAGE_FUNC( hb_mutexDestructor ) #endif } +static const HB_GC_FUNCS s_gcMutexFuncs = +{ + hb_mutexDestructor, + hb_gcDummyMark +}; + static PHB_MUTEX hb_mutexPtr( PHB_ITEM pItem ) { - return ( PHB_MUTEX ) hb_itemGetPtrGC( pItem, hb_mutexDestructor ); + return ( PHB_MUTEX ) hb_itemGetPtrGC( pItem, &s_gcMutexFuncs ); } static PHB_ITEM hb_mutexParam( int iParam ) { PHB_ITEM pItem = hb_param( iParam, HB_IT_POINTER ); - if( hb_itemGetPtrGC( pItem, hb_mutexDestructor ) ) + if( hb_itemGetPtrGC( pItem, &s_gcMutexFuncs ) ) return pItem; hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); @@ -1663,7 +1675,7 @@ PHB_ITEM hb_threadMutexCreate( BOOL fSync ) PHB_ITEM pItem; pItem = hb_itemNew( NULL ); - pMutex = ( PHB_MUTEX ) hb_gcAlloc( sizeof( HB_MUTEX ), hb_mutexDestructor ); + pMutex = ( PHB_MUTEX ) hb_gcAllocRaw( sizeof( HB_MUTEX ), &s_gcMutexFuncs ); memset( pMutex, 0, sizeof( HB_MUTEX ) ); pItem = hb_itemPutPtrGC( pItem, pMutex ); diff --git a/harbour/utils/hbi18n/hbi18n.prg b/harbour/utils/hbi18n/hbi18n.prg index a3fab188eb..3cff702500 100644 --- a/harbour/utils/hbi18n/hbi18n.prg +++ b/harbour/utils/hbi18n/hbi18n.prg @@ -57,6 +57,9 @@ #define _HB_I18N_GENHBL 2 #define _HB_I18N_TRANS 3 +ANNOUNCE HB_GTSYS +REQUEST HB_GT_CGI_DEFAULT + PROCEDURE Main( ... ) LOCAL aParams, aFiles LOCAL cFileOut, cFileIn, cExt