From 9aaaadbc6f49d2abf2beb5b4de236f8043ec01bc Mon Sep 17 00:00:00 2001 From: Przemyslaw Czerpak Date: Wed, 27 Sep 2006 22:39:06 +0000 Subject: [PATCH] 2006-09-28 00:40 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) * harbour/make_rpm.sh * check for rpmbuild also when BUGGY_RPM is set * harbour/make_tgz.sh * removed rebuild hbpptest with shared libraries * harbour/include/hbapicls.h + added definitions for hb_clsCreate(), hb_clsAdd(), hb_clsAssociate() * harbour/include/hbapierr.h * harbour/source/rtl/errorapi.c + added hb_errFuncName - pseudo function name which can be used as operation description in new error object. It should help to simplify some code and fix function names when RT error is generated from C function which can be executed from different .prg functions. * harbour/include/hbclass.ch + added some missing Classy(y) compatible object variable type descriptions: Int, Integer, Block * harbour/source/rdd/dbfcdx/dbfcdx1.c ! disabled early retrieving from the cache key position and key count * harbour/include/hbvm.h * harbour/source/vm/hvm.c + added: void hb_vmPushEvalSym( void ) for the code which do not want to access any [P]HB_SYMB structures * changed symbol name in hb_symEval from __EVAL to EVAL and modified hb_symEval registration method to not register hb_vmDoBlock as global function. Having PHB_DYNS address for "EVAL" in hb_symEval.pDynSym allows to eliminate some strcmp() when we are looking for EVAL public symbol. ! fixed symbol table updating in PCODE functions for future multi module .hrb files * harbour/source/vm/proc.c * use hb_symEval.pDynSym instead of strcmp() * harbour/source/vm/arrays.c * harbour/source/vm/debug.c * minor code cleanup * harbour/source/rtl/tclass.prg * harbour/source/vm/classes.c % separate message hash table from methods table - it will cause farther reduction of allocated memory - many thanks to all people who send me statistics about number of used classes and symbols from their code. % use hb_symEval.pDynSym + added support for object variable type scope checking like in Class(y). ! fixed typo in pushing object class variables by reference % s_pClasses is now indexed directly by class handle % some other optimiztions ! make hidden and non virtual invisible in child classes if it overloaded some other non hidden method. In such case the overloaded method is used and can be accessed. ! make friend functions real method class oriented not (super)object for hidden messages --- harbour/ChangeLog | 59 ++ harbour/include/hbapicls.h | 9 + harbour/include/hbapierr.h | 3 + harbour/include/hbclass.ch | 7 +- harbour/include/hbvm.h | 1 + harbour/make_rpm.sh | 14 +- harbour/make_tgz.sh | 2 +- harbour/source/rdd/dbfcdx/dbfcdx1.c | 354 +++---- harbour/source/rtl/errorapi.c | 8 + harbour/source/rtl/tclass.prg | 49 +- harbour/source/vm/arrays.c | 4 +- harbour/source/vm/classes.c | 1390 +++++++++++++++++---------- harbour/source/vm/debug.c | 2 +- harbour/source/vm/hvm.c | 31 +- harbour/source/vm/proc.c | 14 +- 15 files changed, 1246 insertions(+), 701 deletions(-) diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 27759fa2be..904030df9e 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -8,6 +8,65 @@ 2002-12-01 13:30 UTC+0100 Foo Bar */ + * harbour/include/hbextern.ch + - removed __CLS_PARAM() + + * harbour/include/hbclass.ch + * harbour/source/rtl/tclass.prg + * harbour/source/vm/classes.c + * replaced __CLS_PAR00() and __CLS_PARAM() functions by preprocessor + rules. These functions are not longer necessary though I left them + in classes.c for backward binary compatibility. Probably they will + be removed in the future. + ! use function pointers (@()) instead of function names + with REQUEST for super classes ID. It fixes using STATIC class + functions. + +2006-09-28 00:40 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) + * harbour/make_rpm.sh + * check for rpmbuild also when BUGGY_RPM is set + + * harbour/make_tgz.sh + * removed rebuild hbpptest with shared libraries + + * harbour/include/hbapicls.h + + added definitions for hb_clsCreate(), hb_clsAdd(), hb_clsAssociate() + + * harbour/include/hbapierr.h + * harbour/source/rtl/errorapi.c + + added hb_errFuncName - pseudo function name which can be used as + operation description in new error object. It should help to simplify + some code and fix function names when RT error is generated from C + function which can be executed from different .prg functions. + + * harbour/include/hbclass.ch + + added some missing Classy(y) compatible object variable type + descriptions: Int, Integer, Block + + * harbour/source/rdd/dbfcdx/dbfcdx1.c + ! disabled early retrieving from the cache key position and key count + + * harbour/include/hbvm.h + * harbour/source/vm/hvm.c + + added: void hb_vmPushEvalSym( void ) for the code which do not + want to access any [P]HB_SYMB structures + * changed symbol name in hb_symEval from __EVAL to EVAL and modified + hb_symEval registration method to not register hb_vmDoBlock as global + function. Having PHB_DYNS address for "EVAL" in hb_symEval.pDynSym + allows to eliminate some strcmp() when we are looking for EVAL public + symbol. + ! fixed symbol table updating in PCODE functions for future multi module + .hrb files + + * harbour/source/vm/proc.c + * use hb_symEval.pDynSym instead of strcmp() + + * harbour/source/vm/arrays.c + * harbour/source/vm/debug.c + * minor code cleanup + + * harbour/source/rtl/tclass.prg + * harbour/source/vm/classes.c % separate message hash table from methods table - it will cause farther reduction of allocated memory - many thanks to all people who send me statistics about number of used classes and symbols from their code. diff --git a/harbour/include/hbapicls.h b/harbour/include/hbapicls.h index 4107c3435a..bb4e85510c 100644 --- a/harbour/include/hbapicls.h +++ b/harbour/include/hbapicls.h @@ -122,6 +122,15 @@ HB_EXPORT extern BOOL hb_objHasMessage( PHB_ITEM pObject, PHB_DYNS pMessag HB_EXPORT extern void hb_objSendMsg( PHB_ITEM pObj, char *sMsg, ULONG ulArg, ... ); HB_EXPORT extern void hb_objSendMessage( PHB_ITEM pObj, PHB_DYNS pMessage, ULONG ulArg, ... ); + +/* Harbour equivalent for Clipper internal __mdCreate() */ +USHORT hb_clsCreate( USHORT usSize, char * szClassName ); +/* Harbour equivalent for Clipper internal __mdAdd() */ +void hb_clsAdd( USHORT usClassH, char * szMethodName, PHB_FUNC pFuncPtr ); +/* Harbour equivalent for Clipper internal __mdAssociate() */ +void hb_clsAssociate( USHORT usClassH ); + + HB_EXTERN_END #endif /* HB_APICLS_H_ */ diff --git a/harbour/include/hbapierr.h b/harbour/include/hbapierr.h index f6c86d0bd8..a96c48e65a 100644 --- a/harbour/include/hbapierr.h +++ b/harbour/include/hbapierr.h @@ -96,6 +96,9 @@ HB_EXTERN_BEGIN #define HB_ERR_ARGS_BASEPARAMS 0xFFFFFFFF #define HB_ERR_ARGS_SELFPARAMS 0xFFFFFFFE +/* pseudo function name in operation description */ +extern char hb_errFuncName; + /* Standard API */ extern char * hb_errGetDescription ( PHB_ITEM pError ); diff --git a/harbour/include/hbclass.ch b/harbour/include/hbclass.ch index af9525be79..7565d26f04 100644 --- a/harbour/include/hbclass.ch +++ b/harbour/include/hbclass.ch @@ -148,8 +148,11 @@ DECLARE HBClass ; /* CLASSY SYNTAX */ #IFDEF HB_CLS_CSY #xtranslate CREATE CLASS => CLASS -#xtranslate _HB_MEMBER {AS Num => _HB_MEMBER {AS Numeric -#xtranslate _HB_MEMBER {AS Char => _HB_MEMBER {AS Character +#xtranslate _HB_MEMBER {AS Int => _HB_MEMBER {AS Numeric +#xtranslate _HB_MEMBER {AS Integer => _HB_MEMBER {AS Numeric +#xtranslate _HB_MEMBER {AS Num => _HB_MEMBER {AS Numeric +#xtranslate _HB_MEMBER {AS Char => _HB_MEMBER {AS Character +#xtranslate _HB_MEMBER {AS Block => _HB_MEMBER {AS CodeBlock #translate @:([]) => ; ::realclass:([]) diff --git a/harbour/include/hbvm.h b/harbour/include/hbvm.h index 180cf2867f..cbe5e56f13 100644 --- a/harbour/include/hbvm.h +++ b/harbour/include/hbvm.h @@ -141,6 +141,7 @@ extern HB_EXPORT void hb_vmPushStringPcode( char * szText, ULONG length ); extern HB_EXPORT void hb_vmPushDate( long lDate ); /* pushes a long date onto the stack */ extern HB_EXPORT void hb_vmPushSymbol( PHB_SYMB pSym ); /* pushes a function pointer onto the stack */ extern HB_EXPORT void hb_vmPushDynSym( PHB_DYNS pDynSym ); /* pushes a function/method pointer onto the stack */ +extern HB_EXPORT void hb_vmPushEvalSym( void ); /* pushes a codeblock eval symbol onto the stack */ extern HB_EXPORT void hb_vmPushPointer( void * ); /* push an item of HB_IT_POINTER type */ extern HB_EXPORT void hb_vmPushState( void ); /* push current VM state on stack */ extern HB_EXPORT void hb_vmPopState( void ); /* pop current VM state from stack */ diff --git a/harbour/make_rpm.sh b/harbour/make_rpm.sh index 2aa137452b..f3485ed3a9 100644 --- a/harbour/make_rpm.sh +++ b/harbour/make_rpm.sh @@ -149,14 +149,18 @@ then cp ${hb_filename} ${RPMDIR}/SOURCES cp harbour.spec ${RPMDIR}/SPECS fi + if which rpmbuild &>/dev/null + then + RPMBLD="rpmbuild" + else + RPMBLD="rpm" + fi + if [ "${BUGGY_RPM}" = "yes" ] then - rpm -ba harbour.spec ${INST_PARAM} - elif which rpmbuild &>/dev/null - then - rpmbuild -ta ${hb_filename} --rmsource ${INST_PARAM} + ${RPMBLD} -ba harbour.spec ${INST_PARAM} else - rpm -ta ${hb_filename} --rmsource ${INST_PARAM} + ${RPMBLD} -ta ${hb_filename} --rmsource ${INST_PARAM} fi else echo "Cannot find archive file: ${hb_filename}" diff --git a/harbour/make_tgz.sh b/harbour/make_tgz.sh index 4f870c58c2..b4106940ab 100644 --- a/harbour/make_tgz.sh +++ b/harbour/make_tgz.sh @@ -245,7 +245,7 @@ then export L_USR="-L${HB_LIB_INSTALL} -l${name} ${ADD_LIBS}" export PRG_USR="\"-D_DEFAULT_INC_DIR='${_DEFAULT_INC_DIR}'\" ${PRG_USR}" - for utl in hbmake hbrun hbpp hbdoc hbtest hbpptest + for utl in hbmake hbrun hbpp hbdoc hbtest do (cd "utils/${utl}" rm -fR "./${HB_ARCHITECTURE}" diff --git a/harbour/source/rdd/dbfcdx/dbfcdx1.c b/harbour/source/rdd/dbfcdx/dbfcdx1.c index 14cb605837..0fbe4c7983 100644 --- a/harbour/source/rdd/dbfcdx/dbfcdx1.c +++ b/harbour/source/rdd/dbfcdx/dbfcdx1.c @@ -5655,11 +5655,7 @@ static LONG hb_cdxDBOIKeyCount( CDXAREAP pArea, LPCDXTAG pTag, BOOL fFilters ) ULONG ulKeyCount = 0; BOOL fLogOpt = pArea->dbfi.itmCobExpr || !pArea->dbfi.fFilter; - if ( pTag && ( fFilters ? fLogOpt && CURKEY_LOGCNT( pTag ) : CURKEY_RAWCNT( pTag ) ) ) - { - ulKeyCount = fFilters ? pTag->logKeyCount : pTag->rawKeyCount; - } - else if ( pTag ) + if ( pTag ) { BOOL fCheckFilter = ( fLogOpt && fFilters && pArea->dbfi.itmCobExpr ); ULONG ulRecNo = pArea->ulRecNo; @@ -5667,62 +5663,69 @@ static LONG hb_cdxDBOIKeyCount( CDXAREAP pArea, LPCDXTAG pTag, BOOL fFilters ) hb_cdxIndexLockRead( pTag->pIndex ); hb_cdxTagRefreshScope( pTag ); - if ( pTag->topScopeKey || pTag->bottomScopeKey || pTag->UsrUnique || pArea->dbfi.fFilter ) + if ( pTag && ( fFilters ? fLogOpt && CURKEY_LOGCNT( pTag ) : CURKEY_RAWCNT( pTag ) ) ) { - pCurKey = hb_cdxKeyCopy( NULL, pTag->CurKey ); - hb_cdxTagGoTop( pTag ); - while ( !pTag->TagEOF ) - { - if ( !fCheckFilter || hb_cdxCheckRecordFilter( pArea, pTag->CurKey->rec ) ) - ulKeyCount++; - hb_cdxTagSkipNext( pTag ); - } - pTag->fRePos = TRUE; - hb_cdxKeyCopy( pTag->CurKey, pCurKey ); - hb_cdxKeyFree( pCurKey ); - if ( fCheckFilter ) - SELF_GOTO( ( AREAP ) pArea, ulRecNo ); + ulKeyCount = fFilters ? pTag->logKeyCount : pTag->rawKeyCount; } else { - LPCDXPAGE pPage; - pCurKey = hb_cdxKeyCopy( NULL, pTag->CurKey ); - if ( pTag->UsrAscend ) - hb_cdxTagGoTop( pTag ); - else - hb_cdxTagGoBottom( pTag ); - pPage = pTag->RootPage; - while ( pPage->Child ) - pPage = pPage->Child; - ulKeyCount = pPage->iKeys; - if ( pPage->Right != CDX_DUMMYNODE ) + if ( pTag->topScopeKey || pTag->bottomScopeKey || pTag->UsrUnique || pArea->dbfi.fFilter ) { - ULONG ulPage = pPage->Right; - pPage = hb_cdxPageNew( pTag, NULL, CDX_DUMMYNODE ); - pPage->Page = ulPage; - while ( pPage->Page != CDX_DUMMYNODE ) + pCurKey = hb_cdxKeyCopy( NULL, pTag->CurKey ); + hb_cdxTagGoTop( pTag ); + while ( !pTag->TagEOF ) { - hb_cdxPageLoad( pPage ); - ulKeyCount += pPage->iKeys; - pPage->Page = pPage->Right; + if ( !fCheckFilter || hb_cdxCheckRecordFilter( pArea, pTag->CurKey->rec ) ) + ulKeyCount++; + hb_cdxTagSkipNext( pTag ); } - hb_cdxPageFree( pPage, TRUE ); + pTag->fRePos = TRUE; + hb_cdxKeyCopy( pTag->CurKey, pCurKey ); + hb_cdxKeyFree( pCurKey ); + if ( fCheckFilter ) + SELF_GOTO( ( AREAP ) pArea, ulRecNo ); + } + else + { + LPCDXPAGE pPage; + pCurKey = hb_cdxKeyCopy( NULL, pTag->CurKey ); + if ( pTag->UsrAscend ) + hb_cdxTagGoTop( pTag ); + else + hb_cdxTagGoBottom( pTag ); + pPage = pTag->RootPage; + while ( pPage->Child ) + pPage = pPage->Child; + ulKeyCount = pPage->iKeys; + if ( pPage->Right != CDX_DUMMYNODE ) + { + ULONG ulPage = pPage->Right; + pPage = hb_cdxPageNew( pTag, NULL, CDX_DUMMYNODE ); + pPage->Page = ulPage; + while ( pPage->Page != CDX_DUMMYNODE ) + { + hb_cdxPageLoad( pPage ); + ulKeyCount += pPage->iKeys; + pPage->Page = pPage->Right; + } + hb_cdxPageFree( pPage, TRUE ); + } + pTag->fRePos = TRUE; + hb_cdxKeyCopy( pTag->CurKey, pCurKey ); + hb_cdxKeyFree( pCurKey ); + } + if ( !fFilters ) + { + pTag->rawKeyCount = ulKeyCount; + pTag->curKeyState |= CDX_CURKEY_RAWCNT; + } + else if ( fLogOpt ) + { + pTag->logKeyCount = ulKeyCount; + pTag->curKeyState |= CDX_CURKEY_LOGCNT; } - pTag->fRePos = TRUE; - hb_cdxKeyCopy( pTag->CurKey, pCurKey ); - hb_cdxKeyFree( pCurKey ); } hb_cdxIndexUnLockRead( pTag->pIndex ); - if ( !fFilters ) - { - pTag->rawKeyCount = ulKeyCount; - pTag->curKeyState |= CDX_CURKEY_RAWCNT; - } - else if ( fLogOpt ) - { - pTag->logKeyCount = ulKeyCount; - pTag->curKeyState |= CDX_CURKEY_LOGCNT; - } } else /* no filter, no order */ { @@ -5762,12 +5765,6 @@ static LONG hb_cdxDBOIKeyNo( CDXAREAP pArea, LPCDXTAG pTag, BOOL fFilters ) if ( !pArea->fPositioned ) ulKeyNo = 0; - else if ( pTag && ( fFilters ? ( fLogOpt && CURKEY_LOGPOS( pTag ) ) : - ( CURKEY_RAWPOS( pTag ) && - pTag->rawKeyRec == pArea->ulRecNo ) ) ) - { - ulKeyNo = fFilters ? pTag->logKeyPos : pTag->rawKeyPos; - } else if ( pTag ) { BOOL fCheckFilter = ( fLogOpt && fFilters && pArea->dbfi.itmCobExpr ); @@ -5775,80 +5772,90 @@ static LONG hb_cdxDBOIKeyNo( CDXAREAP pArea, LPCDXTAG pTag, BOOL fFilters ) hb_cdxIndexLockRead( pTag->pIndex ); hb_cdxTagRefreshScope( pTag ); - hb_cdxTagOpen( pTag ); - if ( hb_cdxCurKeyRefresh( pArea, pTag ) ) + + if ( fFilters ? ( fLogOpt && CURKEY_LOGPOS( pTag ) ) : + ( CURKEY_RAWPOS( pTag ) && + pTag->rawKeyRec == pArea->ulRecNo ) ) { - if ( pTag->topScopeKey || pTag->bottomScopeKey || pTag->UsrUnique || pArea->dbfi.fFilter ) + ulKeyNo = fFilters ? pTag->logKeyPos : pTag->rawKeyPos; + } + else + { + hb_cdxTagOpen( pTag ); + if ( hb_cdxCurKeyRefresh( pArea, pTag ) ) { - if ( hb_cdxBottomScope( pTag ) && hb_cdxTopScope( pTag ) && - ( !fCheckFilter || hb_cdxCheckRecordFilter( pArea, ulRecNo ) ) ) + if ( pTag->topScopeKey || pTag->bottomScopeKey || pTag->UsrUnique || pArea->dbfi.fFilter ) { + if ( hb_cdxBottomScope( pTag ) && hb_cdxTopScope( pTag ) && + ( !fCheckFilter || hb_cdxCheckRecordFilter( pArea, ulRecNo ) ) ) + { - LPCDXKEY pCurKey = hb_cdxKeyCopy( NULL, pTag->CurKey ); - while ( !pTag->TagBOF ) - { - if ( !fCheckFilter || hb_cdxCheckRecordFilter( pArea, pTag->CurKey->rec ) ) - ulKeyNo++; - hb_cdxTagSkipPrev( pTag ); - } - pTag->fRePos = TRUE; - hb_cdxKeyCopy( pTag->CurKey, pCurKey ); - hb_cdxKeyFree( pCurKey ); - if ( fCheckFilter ) - SELF_GOTO( ( AREAP ) pArea, ulRecNo ); - } - } - else - { - LPCDXPAGE pPage = pTag->RootPage; - while ( pPage->Child ) - pPage = pPage->Child; - if ( pTag->UsrAscend ) - { - ulKeyNo = pPage->iCurKey + 1; - if ( pPage->Left != CDX_DUMMYNODE ) - { - ULONG ulPage = pPage->Left; - pPage = hb_cdxPageNew( pTag, NULL, CDX_DUMMYNODE ); - pPage->Page = ulPage; - while ( pPage->Page != CDX_DUMMYNODE ) + LPCDXKEY pCurKey = hb_cdxKeyCopy( NULL, pTag->CurKey ); + while ( !pTag->TagBOF ) { - hb_cdxPageLoad( pPage ); - ulKeyNo += pPage->iKeys; - pPage->Page = pPage->Left; + if ( !fCheckFilter || hb_cdxCheckRecordFilter( pArea, pTag->CurKey->rec ) ) + ulKeyNo++; + hb_cdxTagSkipPrev( pTag ); } - hb_cdxPageFree( pPage, TRUE ); + pTag->fRePos = TRUE; + hb_cdxKeyCopy( pTag->CurKey, pCurKey ); + hb_cdxKeyFree( pCurKey ); + if ( fCheckFilter ) + SELF_GOTO( ( AREAP ) pArea, ulRecNo ); } } else { - ulKeyNo = pPage->iKeys - pPage->iCurKey; - if ( pPage->Right != CDX_DUMMYNODE ) + LPCDXPAGE pPage = pTag->RootPage; + while ( pPage->Child ) + pPage = pPage->Child; + if ( pTag->UsrAscend ) { - ULONG ulPage = pPage->Right; - pPage = hb_cdxPageNew( pTag, NULL, CDX_DUMMYNODE ); - pPage->Page = ulPage; - while ( pPage->Page != CDX_DUMMYNODE ) + ulKeyNo = pPage->iCurKey + 1; + if ( pPage->Left != CDX_DUMMYNODE ) { - hb_cdxPageLoad( pPage ); - ulKeyNo += pPage->iKeys; - pPage->Page = pPage->Right; + ULONG ulPage = pPage->Left; + pPage = hb_cdxPageNew( pTag, NULL, CDX_DUMMYNODE ); + pPage->Page = ulPage; + while ( pPage->Page != CDX_DUMMYNODE ) + { + hb_cdxPageLoad( pPage ); + ulKeyNo += pPage->iKeys; + pPage->Page = pPage->Left; + } + hb_cdxPageFree( pPage, TRUE ); + } + } + else + { + ulKeyNo = pPage->iKeys - pPage->iCurKey; + if ( pPage->Right != CDX_DUMMYNODE ) + { + ULONG ulPage = pPage->Right; + pPage = hb_cdxPageNew( pTag, NULL, CDX_DUMMYNODE ); + pPage->Page = ulPage; + while ( pPage->Page != CDX_DUMMYNODE ) + { + hb_cdxPageLoad( pPage ); + ulKeyNo += pPage->iKeys; + pPage->Page = pPage->Right; + } + hb_cdxPageFree( pPage, TRUE ); } - hb_cdxPageFree( pPage, TRUE ); } } - } - if ( ulKeyNo != 0 ) - { - if ( !fFilters ) + if ( ulKeyNo != 0 ) { - pTag->rawKeyPos = ulKeyNo; - CURKEY_SETRAWPOS( pTag ); - } - else if ( fLogOpt ) - { - pTag->logKeyPos = ulKeyNo; - CURKEY_SETLOGPOS( pTag ); + if ( !fFilters ) + { + pTag->rawKeyPos = ulKeyNo; + CURKEY_SETRAWPOS( pTag ); + } + else if ( fLogOpt ) + { + pTag->logKeyPos = ulKeyNo; + CURKEY_SETLOGPOS( pTag ); + } } } } @@ -5890,79 +5897,82 @@ static ERRCODE hb_cdxDBOIKeyGoto( CDXAREAP pArea, LPCDXTAG pTag, ULONG ulKeyNo, if ( ulKeyNo == 0 ) retval = SELF_GOTO( ( AREAP ) pArea, 0 ); - else if ( pTag && ! pArea->lpdbPendingRel && ( fFilters ? - fLogOpt && CURKEY_LOGPOS( pTag ) && pTag->logKeyPos == ulKeyNo : - ( CURKEY_RAWPOS( pTag ) && pTag->rawKeyPos == ulKeyNo ) ) ) - { - retval = SELF_GOTO( ( AREAP ) pArea, fFilters ? pTag->logKeyRec : pTag->rawKeyRec ); - } else if ( pTag ) { BOOL fCheckFilter = ( fLogOpt && fFilters && pArea->dbfi.itmCobExpr ); hb_cdxIndexLockRead( pTag->pIndex ); hb_cdxTagRefreshScope( pTag ); - if ( pTag->topScopeKey || pTag->bottomScopeKey || pTag->UsrUnique || pArea->dbfi.fFilter ) + if ( ! pArea->lpdbPendingRel && ( fFilters ? + fLogOpt && CURKEY_LOGPOS( pTag ) && pTag->logKeyPos == ulKeyNo : + ( CURKEY_RAWPOS( pTag ) && pTag->rawKeyPos == ulKeyNo ) ) ) { - hb_cdxTagGoTop( pTag ); - if ( fCheckFilter ) - while ( !pTag->TagEOF ) - { - if ( hb_cdxCheckRecordFilter( pArea, pTag->CurKey->rec ) ) - { - if ( ! --ulKeyCnt ) - break; - } - hb_cdxTagSkipNext( pTag ); - } - else - while( !pTag->TagEOF && --ulKeyCnt ) - hb_cdxTagSkipNext( pTag ); + retval = SELF_GOTO( ( AREAP ) pArea, fFilters ? pTag->logKeyRec : pTag->rawKeyRec ); } else { - LPCDXPAGE pPage, pOwnerPage = NULL; - ULONG ulNextPg; - hb_cdxTagGoTop( pTag ); - pPage = pTag->RootPage; - while ( pPage->Child ) + if ( pTag->topScopeKey || pTag->bottomScopeKey || pTag->UsrUnique || pArea->dbfi.fFilter ) { - pOwnerPage = pPage; - pPage = pPage->Child; - } - while ( (ULONG) pPage->iKeys < ulKeyCnt && pOwnerPage && - ( ulNextPg = pTag->UsrAscend ? - pPage->Right : pPage->Left ) != CDX_DUMMYNODE ) - { - ulKeyCnt -= pPage->iKeys; - pOwnerPage->Child = hb_cdxPageNew( pPage->TagParent, pPage->Owner, ulNextPg ); - hb_cdxPageFree( pPage, FALSE ); - pPage = pOwnerPage->Child; - } - if ( (ULONG) pPage->iKeys >= ulKeyCnt ) - { - pPage->iCurKey = pTag->UsrAscend ? ( SHORT ) ulKeyCnt - 1 : pPage->iKeys - ( SHORT ) ulKeyCnt; - hb_cdxSetCurKey( pPage ); + hb_cdxTagGoTop( pTag ); + if ( fCheckFilter ) + while ( !pTag->TagEOF ) + { + if ( hb_cdxCheckRecordFilter( pArea, pTag->CurKey->rec ) ) + { + if ( ! --ulKeyCnt ) + break; + } + hb_cdxTagSkipNext( pTag ); + } + else + while( !pTag->TagEOF && --ulKeyCnt ) + hb_cdxTagSkipNext( pTag ); } else { - pTag->CurKey->rec = 0; + LPCDXPAGE pPage, pOwnerPage = NULL; + ULONG ulNextPg; + hb_cdxTagGoTop( pTag ); + pPage = pTag->RootPage; + while ( pPage->Child ) + { + pOwnerPage = pPage; + pPage = pPage->Child; + } + while ( (ULONG) pPage->iKeys < ulKeyCnt && pOwnerPage && + ( ulNextPg = pTag->UsrAscend ? + pPage->Right : pPage->Left ) != CDX_DUMMYNODE ) + { + ulKeyCnt -= pPage->iKeys; + pOwnerPage->Child = hb_cdxPageNew( pPage->TagParent, pPage->Owner, ulNextPg ); + hb_cdxPageFree( pPage, FALSE ); + pPage = pOwnerPage->Child; + } + if ( (ULONG) pPage->iKeys >= ulKeyCnt ) + { + pPage->iCurKey = pTag->UsrAscend ? ( SHORT ) ulKeyCnt - 1 : pPage->iKeys - ( SHORT ) ulKeyCnt; + hb_cdxSetCurKey( pPage ); + } + else + { + pTag->CurKey->rec = 0; + } + } + retval = SELF_GOTO( ( AREAP ) pArea, pTag->CurKey->rec ); + if ( pArea->fPositioned ) + { + if ( !fFilters ) + { + pTag->rawKeyPos = ulKeyNo; + CURKEY_SETRAWPOS( pTag ); + } + else if ( fLogOpt ) + { + pTag->logKeyPos = ulKeyNo; + CURKEY_SETLOGPOS( pTag ); + } } } hb_cdxIndexUnLockRead( pTag->pIndex ); - retval = SELF_GOTO( ( AREAP ) pArea, pTag->CurKey->rec ); - if ( pArea->fPositioned ) - { - if ( !fFilters ) - { - pTag->rawKeyPos = ulKeyNo; - CURKEY_SETRAWPOS( pTag ); - } - else if ( fLogOpt ) - { - pTag->logKeyPos = ulKeyNo; - CURKEY_SETLOGPOS( pTag ); - } - } } else { diff --git a/harbour/source/rtl/errorapi.c b/harbour/source/rtl/errorapi.c index aa7a417647..fb3a3dc413 100644 --- a/harbour/source/rtl/errorapi.c +++ b/harbour/source/rtl/errorapi.c @@ -86,6 +86,8 @@ better shows what is really the problem. [vszakats] */ #define HB_ERROR_LAUNCH_MAX 8 +char hb_errFuncName = 0; + static HB_ERROR_INFO_PTR s_errorHandler = NULL; static HB_ITEM_PTR s_errorBlock; static int s_iLaunchCount = 0; @@ -439,6 +441,12 @@ PHB_ITEM hb_errPutOperation( PHB_ITEM pError, const char * szOperation ) { HB_TRACE(HB_TR_DEBUG, ("hb_errPutOperation(%p, %s)", pError, szOperation)); + if( szOperation == &hb_errFuncName ) + { + PHB_SYMB pSym = hb_itemGetSymbol( hb_stackBaseItem() ); + if( pSym ) + szOperation = pSym->szName; + } hb_vmPushSymbol( hb_dynsymGetSymbol( "_OPERATION" ) ); hb_vmPush( pError ); hb_vmPushString( ( char * ) szOperation, strlen( szOperation ) ); diff --git a/harbour/source/rtl/tclass.prg b/harbour/source/rtl/tclass.prg index 2098ec0c14..7e51af6b46 100644 --- a/harbour/source/rtl/tclass.prg +++ b/harbour/source/rtl/tclass.prg @@ -202,6 +202,7 @@ STATIC PROCEDURE Create() LOCAL Self := QSelf() LOCAL n LOCAL nLen + LOCAL nScope LOCAL nLenDatas := Len( ::aDatas ) //Datas local to the class !! LOCAL nClassBegin LOCAL hClass @@ -239,17 +240,21 @@ STATIC PROCEDURE Create() //Local message... FOR n := 1 TO nLenDatas + nScope := ::aDatas[ n ][ HB_OO_DATA_SCOPE ] + IF ::aDatas[ n ][ HB_OO_DATA_PERSISTENT ] + nScope := _SetBit( nScope, HB_OO_CLSTP_PERSIST ) + ENDIF __clsAddMsg( hClass, ::aDatas[ n ][ HB_OO_DATA_SYMBOL ] , n, ; - HB_OO_MSG_ACCESS, ::aDatas[ n ][ HB_OO_DATA_VALUE ], ::aDatas[ n ][ HB_OO_DATA_SCOPE ],; - ::aDatas[ n ][ HB_OO_DATA_PERSISTENT ] ) + HB_OO_MSG_ACCESS, ::aDatas[ n ][ HB_OO_DATA_VALUE ], nScope ) __clsAddMsg( hClass, "_" + ::aDatas[ n ][ HB_OO_DATA_SYMBOL ] , n, ; - HB_OO_MSG_ASSIGN, , ::aDatas[ n ][ HB_OO_DATA_SCOPE ] ) + HB_OO_MSG_ASSIGN, , ::aDatas[ n ][ HB_OO_DATA_SCOPE ],; + ::aDatas[ n ][ HB_OO_DATA_TYPE ] ) NEXT nLen := Len( ::aMethods ) FOR n := 1 TO nLen - __clsAddMsg( hClass, ::aMethods[ n ][ HB_OO_MTHD_SYMBOL ], ::aMethods[ n ][ HB_OO_MTHD_PFUNCTION ], HB_OO_MSG_METHOD, NIL, ::aMethods[ n ][ HB_OO_MTHD_SCOPE ],; - ::aMethods[ n ][ HB_OO_MTHD_PERSISTENT ] ) + __clsAddMsg( hClass, ::aMethods[ n ][ HB_OO_MTHD_SYMBOL ], ::aMethods[ n ][ HB_OO_MTHD_PFUNCTION ],; + HB_OO_MSG_METHOD, NIL, ::aMethods[ n ][ HB_OO_MTHD_SCOPE ] ) NEXT nLen := Len( ::aClsDatas ) @@ -264,8 +269,7 @@ STATIC PROCEDURE Create() nLen := Len( ::aInlines ) FOR n := 1 TO nLen __clsAddMsg( hClass, ::aInlines[ n ][ HB_OO_MTHD_SYMBOL ], ::aInlines[ n ][ HB_OO_MTHD_PFUNCTION ],; - HB_OO_MSG_INLINE, NIL, ::aInlines[ n ][ HB_OO_MTHD_SCOPE ],; - ::aInlines[ n ][ HB_OO_MTHD_PERSISTENT ] ) + HB_OO_MSG_INLINE, NIL, ::aInlines[ n ][ HB_OO_MTHD_SCOPE ] ) NEXT nLen := Len( ::aVirtuals ) @@ -309,8 +313,9 @@ STATIC PROCEDURE AddData( cData, xInit, cType, nScope, lNoinit, lPersistent ) LOCAL Self := QSelf() - if lNoInit==NIL;lNoInit:=.F.;endif - if lPersistent == nil; lpersistent := .f.; endif + DEFAULT lNoInit TO .F. + DEFAULT lPersistent TO .F. + DEFAULT nScope TO HB_OO_CLSTP_EXPORTED // Default Init for Logical and numeric IF ! lNoInit .AND. cType != NIL .AND. xInit == NIL @@ -355,7 +360,7 @@ STATIC PROCEDURE AddClassData( cData, xInit, cType, nScope, lNoInit ) LOCAL Self := QSelf() - if lNoInit==NIL;lNoInit:=.F.;endif + DEFAULT lNoInit TO .F. // Default Init for Logical and numeric IF ! lNoInit .AND. cType != NIL .AND. xInit == NIL @@ -400,6 +405,13 @@ STATIC PROCEDURE AddInline( cMethod, bCode, nScope, lPersistent ) LOCAL Self := QSelf(), nAt + DEFAULT lPersistent TO .F. + DEFAULT nScope TO HB_OO_CLSTP_EXPORTED + + IF lPersistent + nScope := _SetBit( nScope, HB_OO_CLSTP_PERSIST ) + ENDIF + /* Remove possible ( )*/ IF ( nAt := At( "(", cMethod ) ) > 0 cMethod := RTrim( Left( cMethod, nAt - 1 ) ) @@ -415,6 +427,13 @@ STATIC PROCEDURE AddMethod( cMethod, nFuncPtr, nScope, lPersistent ) LOCAL Self := QSelf(), nAt + DEFAULT lPersistent TO .F. + DEFAULT nScope TO HB_OO_CLSTP_EXPORTED + + IF lPersistent + nScope := _SetBit( nScope, HB_OO_CLSTP_PERSIST ) + ENDIF + /* Remove possible ( )*/ IF ( nAt := At( "(", cMethod ) ) > 0 cMethod := RTrim( Left( cMethod, nAt - 1 ) ) @@ -500,4 +519,12 @@ STATIC FUNCTION InitClass() RETURN Self -//----------------------------------------------------------------------------// \ No newline at end of file +//----------------------------------------------------------------------------// + +STATIC FUNCTION _SetBit( nValue1, nValue2 ) + IF nValue1 % ( nValue2 + nValue2 ) < nValue2 + nValue1 += nValue2 + ENDIF +RETURN nValue1 + +//----------------------------------------------------------------------------// diff --git a/harbour/source/vm/arrays.c b/harbour/source/vm/arrays.c index e7207fdca3..b739c0cb9b 100644 --- a/harbour/source/vm/arrays.c +++ b/harbour/source/vm/arrays.c @@ -301,7 +301,7 @@ HB_EXPORT BOOL hb_arrayAddForward( PHB_ITEM pArray, PHB_ITEM pValue ) { HB_TRACE(HB_TR_DEBUG, ("hb_arrayAddForward(%p, %p)", pArray, pValue)); - if( pArray->type == HB_IT_ARRAY ) + if( HB_IS_ARRAY( pArray ) ) { PHB_BASEARRAY pBaseArray = ( PHB_BASEARRAY ) pArray->item.asArray.value; @@ -892,7 +892,7 @@ static void hb_arrayCloneBody( PHB_BASEARRAY pSrcBaseArray, PHB_BASEARRAY pDstBa for( ulLen = pSrcBaseArray->ulLen; ulLen; --ulLen, ++pSrcItem, ++pDstItem ) { /* Clipper clones nested array ONLY if NOT an Object!!! */ - if( pSrcItem->type == HB_IT_ARRAY && pSrcItem->item.asArray.value->uiClass == 0 ) + if( HB_IS_ARRAY( pSrcItem ) && pSrcItem->item.asArray.value->uiClass == 0 ) { PHB_NESTED_CLONED pCloned = pClonedList; PHB_BASEARRAY pBaseArray = pSrcItem->item.asArray.value; diff --git a/harbour/source/vm/classes.c b/harbour/source/vm/classes.c index b5bbd19f3a..5cbf56f7ca 100644 --- a/harbour/source/vm/classes.c +++ b/harbour/source/vm/classes.c @@ -68,7 +68,6 @@ * __objSendMsg() * * Copyright 1999-2001 Viktor Szakats - * hb___msgEval() * __CLASSNEW() * __CLASSINSTANCE() * __CLASSADD() @@ -157,7 +156,7 @@ typedef struct PHB_ITEM pInitValue; /* Init Value for data */ USHORT uiType; /* HB_OO_MSG_DATA, HB_OO_MSG_CLASSDATA or HB_OO_MSG_INITIALIZED */ USHORT uiData; /* Item position in instance area or class data */ - USHORT uiOffset; /* Supper cast instance are offset */ + USHORT uiOffset; /* Supper cast instance area offset for HB_OO_MSG_DATA or real class item position */ USHORT uiSprClass; /* The real class where method were defined */ } INITDATA, * PINITDATA; @@ -169,6 +168,9 @@ typedef struct USHORT uiScope; /* Scoping value */ USHORT uiData; /* Item position for instance data, class or shared data (Harbour like, begin from 1) */ USHORT uiOffset; /* position in pInitData for class datas (from 1) or offset to instance area in inherited instance data and supercast messages (from 0) */ + HB_TYPE itemType; /* Type of item in restricted assignment */ + USHORT uiPrevCls; + USHORT uiPrevMth; #ifndef HB_NO_PROFILER ULONG ulCalls; /* profiler support */ ULONG ulTime; /* profiler support */ @@ -176,6 +178,8 @@ typedef struct #endif } METHOD, * PMETHOD; + +#define HB_MSG_POOL typedef struct { char * szName; /* Class name */ @@ -189,16 +193,20 @@ typedef struct PHB_ITEM pInlines; /* Array for inline codeblocks */ PHB_SYMB * pFriendSyms; /* Friend functions' symbols */ ULONG ulOpFlags; /* Flags for overloaded operators */ - BOOL fHasDestructor; /* has the class destructor message? */ - BOOL fHasOnError; /* has the class OnError message? */ + USHORT fHasDestructor; /* has the class destructor message? */ + USHORT fHasOnError; /* has the class OnError message? */ + USHORT fLocked; /* Class is locked against modifications */ USHORT uiMethods; /* Total Method initialised Counter */ USHORT uiInitDatas; /* Total Method initialised Counter */ USHORT uiDatas; /* Total Data Counter */ USHORT uiDataFirst; /* First instance item from this class */ USHORT uiFriendSyms; /* Number of friend function's symbols */ USHORT uiFriendModule; /* Number of friend symbols in pFriendModule */ - USHORT fLocked; /* Lock the class agains modifications */ USHORT uiHashKey; +#ifdef HB_MSG_POOL + USHORT * puiMsgIdx; + USHORT uiMethodCount; +#endif } CLASS, * PCLASS; #define BUCKETBITS 2 @@ -207,7 +215,14 @@ typedef struct #define HASHBITS 3 #define HASH_KEY ( ( 1 << HASHBITS ) - 1 ) #define HASH_KEYMAX ( 1 << ( 16 - BUCKETBITS ) ) -#define hb_clsMthNum(p) ( ( ( ULONG ) (p)->uiHashKey + 1 ) << BUCKETBITS ) +#define hb_clsInited(p) ( (p)->pMethods != NULL ) +#define hb_clsBucketPos( p, m ) ( ( (p)->uiSymNum & (m) ) << BUCKETBITS ) + +#ifdef HB_MSG_POOL +# define hb_clsMthNum(p) ( ( ULONG ) (p)->uiMethodCount ) +#else +# define hb_clsMthNum(p) ( ( ( ULONG ) (p)->uiHashKey + 1 ) << BUCKETBITS ) +#endif #if defined( HB_REAL_BLOCK_SCOPE ) # undef HB_CLASSY_BLOCK_SCOPE @@ -232,14 +247,14 @@ static HARBOUR hb___msgSuper( void ); static HARBOUR hb___msgRealClass( void ); static HARBOUR hb___msgNoMethod( void ); static HARBOUR hb___msgScopeErr( void ); +static HARBOUR hb___msgTypeErr( void ); static HARBOUR hb___msgNull( void ); -static HARBOUR hb___msgClsH( void ); -static HARBOUR hb___msgClsName( void ); -static HARBOUR hb___msgClsSel( void ); -static HARBOUR hb___msgEval( void ); +static HARBOUR hb___msgClassH( void ); +static HARBOUR hb___msgClassName( void ); +static HARBOUR hb___msgClassSel( void ); /* static HARBOUR hb___msgClass( void ); */ -/* static HARBOUR hb___msgClsParent( void ); */ +/* static HARBOUR hb___msgClassParent( void ); */ /* * The positions of items in symbol table below have to correspond @@ -292,15 +307,15 @@ static HB_SYMB s___msgSuper = { "__msgSuper", {HB_FS_MESSAGE}, {hb___m static HB_SYMB s___msgRealClass = { "__RealClass", {HB_FS_MESSAGE}, {hb___msgRealClass}, NULL }; static HB_SYMB s___msgNoMethod = { "__msgNoMethod", {HB_FS_MESSAGE}, {hb___msgNoMethod}, NULL }; static HB_SYMB s___msgScopeErr = { "__msgScopeErr", {HB_FS_MESSAGE}, {hb___msgScopeErr}, NULL }; +static HB_SYMB s___msgTypeErr = { "__msgTypeErr", {HB_FS_MESSAGE}, {hb___msgTypeErr}, NULL }; -static HB_SYMB s___msgClassName = { "CLASSNAME", {HB_FS_MESSAGE}, {hb___msgClsName}, NULL }; -static HB_SYMB s___msgClassH = { "CLASSH", {HB_FS_MESSAGE}, {hb___msgClsH}, NULL }; -static HB_SYMB s___msgClassSel = { "CLASSSEL", {HB_FS_MESSAGE}, {hb___msgClsSel}, NULL }; -static HB_SYMB s___msgEval = { "EVAL", {HB_FS_MESSAGE}, {hb___msgEval}, NULL }; +static HB_SYMB s___msgClassName = { "CLASSNAME", {HB_FS_MESSAGE}, {hb___msgClassName}, NULL }; +static HB_SYMB s___msgClassH = { "CLASSH", {HB_FS_MESSAGE}, {hb___msgClassH}, NULL }; +static HB_SYMB s___msgClassSel = { "CLASSSEL", {HB_FS_MESSAGE}, {hb___msgClassSel}, NULL }; static HB_SYMB s___msgExec = { "EXEC", {HB_FS_MESSAGE}, {hb___msgNull}, NULL }; static HB_SYMB s___msgName = { "NAME", {HB_FS_MESSAGE}, {hb___msgNull}, NULL }; /* -static HB_SYMB s___msgClsParent = { "ISDERIVEDFROM", {HB_FS_MESSAGE}, {hb___msgClsParent}, NULL }; +static HB_SYMB s___msgClsParent = { "ISDERIVEDFROM", {HB_FS_MESSAGE}, {hb___msgClassParent},NULL }; static HB_SYMB s___msgClass = { "CLASS", {HB_FS_MESSAGE}, {hb___msgClass}, NULL }; */ @@ -318,7 +333,9 @@ static USHORT s_uiClasses = 0; /* ================================================ */ -static USHORT hb_clsMsgBucket( PHB_DYNS pMsg, USHORT uiMask ) + +#if 0 +static USHORT hb_clsBucketPos( PHB_DYNS pMsg, USHORT uiMask ) { /* * we can use PHB_DYNS address as base for hash key. @@ -340,9 +357,9 @@ static USHORT hb_clsMsgBucket( PHB_DYNS pMsg, USHORT uiMask ) * the whole 16bit area and we will never have any problems until number * of symbols is limited to 2^16. [druzus] */ - return ( pMsg->uiSymNum & uiMask ) << BUCKETBITS; } +#endif /* * hb_clsDictRealloc( PCLASS ) @@ -352,7 +369,11 @@ static USHORT hb_clsMsgBucket( PHB_DYNS pMsg, USHORT uiMask ) static BOOL hb_clsDictRealloc( PCLASS pClass ) { ULONG ulNewHashKey, ulLimit, ul; +#ifdef HB_MSG_POOL + USHORT * puiMsgIdx; +#else PMETHOD pNewMethods; +#endif HB_TRACE(HB_TR_DEBUG, ("hb_clsDictRealloc(%p)", pClass)); @@ -368,6 +389,45 @@ static BOOL hb_clsDictRealloc( PCLASS pClass ) return FALSE; } +#ifdef HB_MSG_POOL + puiMsgIdx = ( USHORT * ) hb_xgrab( ( ulNewHashKey << BUCKETBITS ) * sizeof( USHORT ) ); + memset( puiMsgIdx, 0, ( ulNewHashKey << BUCKETBITS ) * sizeof( USHORT ) ); + + for( ul = 0; ul < ulLimit; ul++ ) + { + USHORT uiMsg = pClass->puiMsgIdx[ ul ]; + if( pClass->puiMsgIdx[ ul ] ) + { + USHORT uiBucket = BUCKETSIZE; + USHORT * puiIdx = puiMsgIdx + hb_clsBucketPos( + pClass->pMethods[ uiMsg ].pMessage, ulNewHashKey - 1 ); + do + { + if( * puiIdx == 0 ) /* this message position is empty */ + { + * puiIdx = uiMsg; + break; + } + ++puiIdx; + } while( --uiBucket ); + + /* Not enough go back to the beginning */ + if( ! uiBucket ) + { + hb_xfree( puiMsgIdx ); + break; + } + } + } + } + while( ul < ulLimit ); + + pClass->uiHashKey = ( USHORT ) ( ulNewHashKey - 1 ); + hb_xfree( pClass->puiMsgIdx ); + pClass->puiMsgIdx = puiMsgIdx; + +#else + pNewMethods = ( PMETHOD ) hb_xgrab( ( ulNewHashKey << BUCKETBITS ) * sizeof( METHOD ) ); memset( pNewMethods, 0, ( ulNewHashKey << BUCKETBITS ) * sizeof( METHOD ) ); @@ -377,7 +437,7 @@ static BOOL hb_clsDictRealloc( PCLASS pClass ) if( pMessage ) { - PMETHOD pMethod = pNewMethods + hb_clsMsgBucket( pMessage, ulNewHashKey - 1 ); + PMETHOD pMethod = pNewMethods + hb_clsBucketPos( pMessage, ulNewHashKey - 1 ); USHORT uiBucket = BUCKETSIZE; do @@ -404,6 +464,7 @@ static BOOL hb_clsDictRealloc( PCLASS pClass ) pClass->uiHashKey = ( USHORT ) ( ulNewHashKey - 1 ); hb_xfree( pClass->pMethods ); pClass->pMethods = pNewMethods; +#endif return TRUE; } @@ -414,72 +475,51 @@ static void hb_clsDictInit( PCLASS pClass, USHORT uiHashKey ) HB_TRACE(HB_TR_DEBUG, ("hb_clsDictInit(%p,%hu)", pClass, uiHashKey)); - ulSize = ( ( ( ULONG ) uiHashKey + 1 ) << BUCKETBITS ) * sizeof( METHOD ); pClass->uiHashKey = uiHashKey; +#ifdef HB_MSG_POOL + ulSize = ( ( ( ULONG ) uiHashKey + 1 ) << BUCKETBITS ) * sizeof( USHORT ); + pClass->puiMsgIdx = ( USHORT * ) hb_xgrab( ulSize ); + memset( pClass->puiMsgIdx, 0, ulSize ); + + pClass->uiMethodCount = 1; + pClass->pMethods = ( PMETHOD ) hb_xgrab( sizeof( METHOD ) ); + memset( pClass->pMethods, 0, sizeof( METHOD ) ); +#else + ulSize = ( ( ( ULONG ) uiHashKey + 1 ) << BUCKETBITS ) * sizeof( METHOD ); pClass->pMethods = ( PMETHOD ) hb_xgrab( ulSize ); memset( pClass->pMethods, 0, ulSize ); -} - -static void hb_clsCopyClass( PCLASS pClsDst, PCLASS pClsSrc ) -{ - PMETHOD pMethod; - ULONG ulLimit; - - HB_TRACE(HB_TR_DEBUG, ("hb_clsCopyClass(%p,%p)", pClsDst, pClsSrc)); - - hb_clsDictInit( pClsDst, pClsSrc->uiHashKey ); - pClsDst->fHasOnError = pClsSrc->fHasOnError; - pClsDst->fHasDestructor = pClsSrc->fHasDestructor; - - /* CLASS DATA Not Shared ( new array, new value ) */ - pClsDst->pClassDatas = hb_arrayClone( pClsSrc->pClassDatas ); - /* do not copy shared data array - just simply create new one */ - pClsDst->pSharedDatas = hb_itemArrayNew( 0 ); - pClsDst->pInlines = hb_arrayClone( pClsSrc->pInlines ); - pClsDst->uiDatas = pClsSrc->uiDatas; - pClsDst->ulOpFlags = pClsSrc->ulOpFlags; - - if( pClsSrc->uiInitDatas ) - { - ULONG ulSize = ( ULONG ) pClsSrc->uiInitDatas * sizeof( INITDATA ); - USHORT uiData; - - pClsDst->uiInitDatas = pClsSrc->uiInitDatas; - pClsDst->pInitData = ( PINITDATA ) hb_xgrab( ulSize ); - memcpy( pClsDst->pInitData, pClsSrc->pInitData, ulSize ); - for( uiData = 0; uiData < pClsDst->uiInitDatas; ++uiData ) - { - if( pClsDst->pInitData[ uiData ].uiType == HB_OO_MSG_INITIALIZED ) - pClsDst->pInitData[ uiData ].uiType = HB_OO_MSG_CLASSDATA; - pClsDst->pInitData[ uiData ].pInitValue = - hb_itemNew( pClsDst->pInitData[ uiData ].pInitValue ); - } - } - - ulLimit = hb_clsMthNum( pClsDst ); - memcpy( pClsDst->pMethods, pClsSrc->pMethods, ulLimit * sizeof( METHOD ) ); - pClsDst->uiMethods = pClsSrc->uiMethods; - - pMethod = pClsDst->pMethods; - do - { - if( pMethod->pMessage ) - { - pMethod->uiScope |= HB_OO_CLSTP_SUPER; - } - ++pMethod; - } - while( --ulLimit ); +#endif } static PMETHOD hb_clsFindMsg( PCLASS pClass, PHB_DYNS pMsg ) { +#ifdef HB_MSG_POOL + + USHORT uiBucket, * puiMsgIdx; + + HB_TRACE(HB_TR_DEBUG, ("hb_clsFindMsg(%p,%p)", pClass, pMsg)); + + puiMsgIdx = pClass->puiMsgIdx + hb_clsBucketPos( pMsg, pClass->uiHashKey ); + uiBucket = BUCKETSIZE; + + do + { + if( pClass->pMethods[ * puiMsgIdx ].pMessage == pMsg ) + { + return &pClass->pMethods[ * puiMsgIdx ]; + } + ++puiMsgIdx; + } + while( --uiBucket ); + +#else + PMETHOD pMethod; USHORT uiBucket; HB_TRACE(HB_TR_DEBUG, ("hb_clsFindMsg(%p,%p)", pClass, pMsg)); - pMethod = pClass->pMethods + hb_clsMsgBucket( pMsg, pClass->uiHashKey ); + pMethod = pClass->pMethods + hb_clsBucketPos( pMsg, pClass->uiHashKey ); uiBucket = BUCKETSIZE; do @@ -489,6 +529,7 @@ static PMETHOD hb_clsFindMsg( PCLASS pClass, PHB_DYNS pMsg ) ++pMethod; } while( --uiBucket ); +#endif return NULL; } @@ -499,7 +540,31 @@ static PMETHOD hb_clsAllocMsg( PCLASS pClass, PHB_DYNS pMsg ) do { - PMETHOD pMethod = pClass->pMethods + hb_clsMsgBucket( pMsg, pClass->uiHashKey ); + +#ifdef HB_MSG_POOL + + USHORT uiBucket = BUCKETSIZE, * puiMsgIdx = pClass->puiMsgIdx + + hb_clsBucketPos( pMsg, pClass->uiHashKey ); + + do + { + if( * puiMsgIdx == 0 ) + { + pClass->pMethods = ( PMETHOD ) hb_xrealloc( pClass->pMethods, + sizeof( METHOD ) * ( pClass->uiMethodCount + 1 ) ); + memset( &pClass->pMethods[ pClass->uiMethodCount ], 0, sizeof( METHOD ) ); + * puiMsgIdx = pClass->uiMethodCount++; + return &pClass->pMethods[ * puiMsgIdx ]; + } + else if( pClass->pMethods[ * puiMsgIdx ].pMessage == pMsg ) + return &pClass->pMethods[ * puiMsgIdx ]; + ++puiMsgIdx; + } + while( --uiBucket ); + +#else + + PMETHOD pMethod = pClass->pMethods + hb_clsBucketPos( pMsg, pClass->uiHashKey ); USHORT uiBucket = BUCKETSIZE; do @@ -509,37 +574,72 @@ static PMETHOD hb_clsAllocMsg( PCLASS pClass, PHB_DYNS pMsg ) ++pMethod; } while( --uiBucket ); + +#endif + } while( hb_clsDictRealloc( pClass ) ); return NULL; } -static BOOL hb_clsClearMsg( PCLASS pClass, PMETHOD pMethod ) +static BOOL hb_clsCanClearMethod( PMETHOD pMethod, BOOL fError ) { - if( pMethod->pFuncSym == &s___msgEvalInline ) - { /* INLINE method deleted, delete INLINE block */ - hb_itemClear( hb_arrayGetItemPtr( pClass->pInlines, pMethod->uiData ) ); + HB_SYMBOL_UNUSED( pMethod ); + HB_SYMBOL_UNUSED( fError ); +#if 0 + if( pMethod->pFuncSym == &s___msgSuper ) + { + if( fError ) + hb_errRT_BASE( EG_ARG, 3000, "Cannot delete supercast messages", &hb_errFuncName, 0 ); + return FALSE; } - +#endif return TRUE; } static void hb_clsFreeMsg( PCLASS pClass, PHB_DYNS pMsg ) { +#ifdef HB_MSG_POOL + + USHORT uiBucket, * puiMsgIdx; + + HB_TRACE(HB_TR_DEBUG, ("hb_clsFreeMsg(%p,%p)", pClass, pMsg)); + + + puiMsgIdx = pClass->puiMsgIdx + hb_clsBucketPos( pMsg, pClass->uiHashKey ); + uiBucket = BUCKETSIZE; + + do + { + if( * puiMsgIdx && pClass->pMethods[ * puiMsgIdx ].pMessage == pMsg ) + { + if( hb_clsCanClearMethod( &pClass->pMethods[ * puiMsgIdx ], TRUE ) ) + { + memset( &pClass->pMethods[ * puiMsgIdx ], 0, sizeof( METHOD ) ); + pClass->uiMethods--; /* Decrease number of messages */ + } + return; + } + ++puiMsgIdx; + } + while( --uiBucket ); + +#else + PMETHOD pMethod; USHORT uiBucket; HB_TRACE(HB_TR_DEBUG, ("hb_clsFreeMsg(%p,%p)", pClass, pMsg)); - pMethod = pClass->pMethods + hb_clsMsgBucket( pMsg, pClass->uiHashKey ); + pMethod = pClass->pMethods + hb_clsBucketPos( pMsg, pClass->uiHashKey ); uiBucket = BUCKETSIZE; do { if( pMethod->pMessage == pMsg ) { - if( hb_clsClearMsg( pClass, pMethod ) ) + if( hb_clsCanClearMethod( pMethod, TRUE ) ) { /* Move messages */ while( --uiBucket ) @@ -555,6 +655,22 @@ static void hb_clsFreeMsg( PCLASS pClass, PHB_DYNS pMsg ) ++pMethod; } while( --uiBucket ); + +#endif +} + +static BOOL hb_clsHasParent( PCLASS pClass, PHB_DYNS pParentSym ) +{ + PMETHOD pMethod = hb_clsFindMsg( pClass, pParentSym ); + + return pMethod && pMethod->pFuncSym == &s___msgSuper; +} + +static USHORT hb_clsParentInstanceOffset( PCLASS pClass, PHB_DYNS pParentSym ) +{ + PMETHOD pMethod = hb_clsFindMsg( pClass, pParentSym ); + + return ( pMethod && pMethod->pFuncSym == &s___msgSuper ) ? pMethod->uiOffset : 0; } static USHORT hb_clsAddInitValue( PCLASS pClass, PHB_ITEM pItem, @@ -606,6 +722,178 @@ static USHORT hb_clsAddInitValue( PCLASS pClass, PHB_ITEM pItem, return pClass->uiInitDatas; } +static USHORT hb_clsFindRealClassDataOffset( PMETHOD pMethod ) +{ + PMETHOD pRealMth; + + HB_TRACE(HB_TR_DEBUG, ("hb_clsFindRealClassDataOffset(%p)", pMethod)); + + pRealMth = hb_clsFindMsg( &s_pClasses[ pMethod->uiSprClass ], + pMethod->pMessage ); + if( pRealMth && pRealMth->uiSprClass == pMethod->uiSprClass && + ( pRealMth->pFuncSym == &s___msgSetClsData || + pRealMth->pFuncSym == &s___msgGetClsData ) ) + { + return pRealMth->uiData; + } + return 0; +} + +static USHORT hb_clsFindClassDataOffset( PCLASS pClass, PMETHOD pNewMethod ) +{ + USHORT uiData; + + HB_TRACE(HB_TR_DEBUG, ("hb_clsFindClassDataOffset(%p,%p)", pClass, pNewMethod)); + + uiData = hb_clsFindRealClassDataOffset( pNewMethod ); + if( uiData ) + { + ULONG ulLimit = hb_clsMthNum( pClass ); + PMETHOD pMethod = pClass->pMethods; + do + { + if( pMethod->pMessage && pMethod != pNewMethod && + pMethod->uiSprClass == pNewMethod->uiSprClass && + ( pMethod->pFuncSym == &s___msgSetClsData || + pMethod->pFuncSym == &s___msgGetClsData ) && + uiData == hb_clsFindRealClassDataOffset( pMethod ) ) + { + return pMethod->uiData; + } + ++pMethod; + } + while( --ulLimit ); + } + + return 0; +} + +static BOOL hb_clsUpdateHiddenMessages( PMETHOD pSrcMethod, PMETHOD pDstMethod, + PCLASS pDstClass ) +{ + PMETHOD pNewMethod = pSrcMethod; + + HB_TRACE(HB_TR_DEBUG, ("hb_clsUpdateHiddenMessages(%p,%p,%p)", pSrcMethod, pDstMethod, pDstClass)); + + if( ! pDstMethod->pMessage || + ( hb_clsCanClearMethod( pDstMethod, FALSE ) && + pDstMethod->uiPrevCls != pDstMethod->uiSprClass && + ( pDstMethod->uiScope & HB_OO_CLSTP_HIDDEN ) && + ( pDstMethod->uiScope & HB_OO_CLSTP_NONVIRTUAL ) ) ) + { + while( pNewMethod && + pNewMethod->uiPrevCls != pNewMethod->uiSprClass && + ( pNewMethod->uiScope & HB_OO_CLSTP_HIDDEN ) && + ( pNewMethod->uiScope & HB_OO_CLSTP_NONVIRTUAL ) ) + { + pNewMethod = hb_clsFindMsg( &s_pClasses[ pNewMethod->uiPrevCls ], + pNewMethod->pMessage ); + } + if( pNewMethod && pNewMethod != pSrcMethod && + !( pNewMethod->uiScope & HB_OO_CLSTP_HIDDEN ) && + hb_clsCanClearMethod( pDstMethod, FALSE ) ) + { + USHORT uiPrevCls = pDstMethod->uiPrevCls, + uiPrevMth = pDstMethod->uiPrevMth; + + memcpy( pDstMethod, pNewMethod, sizeof( METHOD ) ); + pDstMethod->uiPrevCls = uiPrevCls; + pDstMethod->uiPrevMth = uiPrevMth; + pDstMethod->uiScope |= HB_OO_CLSTP_OVERLOADED | HB_OO_CLSTP_SUPER; + if( pDstMethod->pFuncSym == &s___msgSetData || + pDstMethod->pFuncSym == &s___msgGetData ) + { + pDstMethod->uiOffset = hb_clsParentInstanceOffset( pDstClass, + s_pClasses[ pDstMethod->uiSprClass ].pClassSym ); + } + else if( pDstMethod->pFuncSym == &s___msgSetClsData || + pDstMethod->pFuncSym == &s___msgGetClsData ) + { + PCLASS pSrcClass = &s_pClasses[ pDstMethod->uiSprClass ]; + USHORT uiData; + + uiData = hb_clsFindClassDataOffset( pDstClass, pDstMethod ); + + if( uiData == 0 ) + { + uiData = hb_arrayLen( pDstClass->pClassDatas ) + 1; + hb_arraySize( pDstClass->pClassDatas, uiData ); + } + if( pDstMethod->uiOffset ) + { + pDstMethod->uiOffset = hb_clsAddInitValue( pDstClass, + pSrcClass->pInitData[ pDstMethod->uiOffset - 1 ].pInitValue, + HB_OO_MSG_CLASSDATA, uiData, 0, pDstMethod->uiSprClass ); + } + pDstMethod->uiData = uiData; + } + return TRUE; + } + } + + return FALSE; +} + +static void hb_clsCopyClass( PCLASS pClsDst, PCLASS pClsSrc ) +{ + PMETHOD pMethod; + ULONG ulLimit; + + HB_TRACE(HB_TR_DEBUG, ("hb_clsCopyClass(%p,%p)", pClsDst, pClsSrc)); + + hb_clsDictInit( pClsDst, pClsSrc->uiHashKey ); + pClsDst->fHasOnError = pClsSrc->fHasOnError; + pClsDst->fHasDestructor = pClsSrc->fHasDestructor; + + /* CLASS DATA Not Shared ( new array, new value ) */ + pClsDst->pClassDatas = hb_arrayClone( pClsSrc->pClassDatas ); + /* do not copy shared data array - just simply create new one */ + pClsDst->pSharedDatas = hb_itemArrayNew( 0 ); + pClsDst->pInlines = hb_arrayClone( pClsSrc->pInlines ); + pClsDst->uiDatas = pClsSrc->uiDatas; + pClsDst->ulOpFlags = pClsSrc->ulOpFlags; + + if( pClsSrc->uiInitDatas ) + { + ULONG ulSize = ( ULONG ) pClsSrc->uiInitDatas * sizeof( INITDATA ); + USHORT uiData; + + pClsDst->uiInitDatas = pClsSrc->uiInitDatas; + pClsDst->pInitData = ( PINITDATA ) hb_xgrab( ulSize ); + memcpy( pClsDst->pInitData, pClsSrc->pInitData, ulSize ); + for( uiData = 0; uiData < pClsDst->uiInitDatas; ++uiData ) + { + if( pClsDst->pInitData[ uiData ].uiType == HB_OO_MSG_INITIALIZED ) + pClsDst->pInitData[ uiData ].uiType = HB_OO_MSG_CLASSDATA; + pClsDst->pInitData[ uiData ].pInitValue = + hb_itemNew( pClsDst->pInitData[ uiData ].pInitValue ); + } + } + + ulLimit = hb_clsMthNum( pClsSrc ); +#ifdef HB_MSG_POOL + memcpy( pClsDst->puiMsgIdx, pClsSrc->puiMsgIdx, + ( ( ( ULONG ) pClsSrc->uiHashKey + 1 ) << BUCKETBITS ) * sizeof( USHORT ) ); + pClsDst->uiMethodCount = pClsSrc->uiMethodCount; + pClsDst->pMethods = ( PMETHOD ) hb_xrealloc( pClsDst->pMethods, + ulLimit * sizeof( METHOD ) ); +#endif + memcpy( pClsDst->pMethods, pClsSrc->pMethods, ulLimit * sizeof( METHOD ) ); + pClsDst->uiMethods = pClsSrc->uiMethods; + + pMethod = pClsDst->pMethods; + do + { + if( pMethod->pMessage ) + { + hb_clsUpdateHiddenMessages( pMethod, pMethod, pClsDst ); + pMethod->uiScope |= HB_OO_CLSTP_SUPER; + } + ++pMethod; + } + while( --ulLimit ); +} + static BOOL hb_clsIsFriendSymbol( PCLASS pClass, PHB_SYMB pSym ) { USHORT uiCount; @@ -668,7 +956,6 @@ void hb_clsInit( void ) s___msgClassName.pDynSym = hb_dynsymGetCase( s___msgClassName.szName ); /* Standard messages */ s___msgClassH.pDynSym = hb_dynsymGetCase( s___msgClassH.szName ); /* Not present in classdef. */ s___msgClassSel.pDynSym = hb_dynsymGetCase( s___msgClassSel.szName ); - s___msgEval.pDynSym = hb_dynsymGetCase( s___msgEval.szName ); s___msgExec.pDynSym = hb_dynsymGetCase( s___msgExec.szName ); s___msgName.pDynSym = hb_dynsymGetCase( s___msgName.szName ); s___msgNew.pDynSym = hb_dynsymGetCase( s___msgNew.szName ); @@ -713,6 +1000,10 @@ static void hb_clsRelease( PCLASS pClass ) hb_xfree( pClass->pMethods ); if( pClass->uiFriendSyms ) hb_xfree( pClass->pFriendSyms ); +#ifdef HB_MSG_POOL + if( pClass->puiMsgIdx ) + hb_xfree( pClass->puiMsgIdx ); +#endif if( pClass->pClassDatas ) hb_itemRelease( pClass->pClassDatas ); if( pClass->pSharedDatas ) @@ -740,9 +1031,9 @@ void hb_clsReleaseAll( void ) do { - hb_clsRelease( &s_pClasses[ --uiClass ] ); + hb_clsRelease( &s_pClasses[ uiClass ] ); } - while( uiClass ); + while( --uiClass ); hb_xfree( s_pClasses ); s_pClasses = NULL; @@ -762,7 +1053,7 @@ void hb_clsIsClassRef( void ) */ #if 0 USHORT uiClass = s_uiClasses; - PCLASS pClass = s_pClasses; + PCLASS pClass = s_pClasses + 1; HB_TRACE(HB_TR_DEBUG, ("hb_clsIsClassRef()")); @@ -795,25 +1086,11 @@ void hb_clsIsClassRef( void ) #endif } -static BOOL hb_clsHasParent( PCLASS pClass, PHB_DYNS pParentSym ) -{ - PMETHOD pMethod = hb_clsFindMsg( pClass, pParentSym ); - - return pMethod && pMethod->pFuncSym == &s___msgSuper; -} - -static USHORT hb_clsParentInstanceOffset( PCLASS pClass, PHB_DYNS pParentSym ) -{ - PMETHOD pMethod = hb_clsFindMsg( pClass, pParentSym ); - - return ( pMethod && pMethod->pFuncSym == &s___msgSuper ) ? pMethod->uiOffset : 0; -} - HB_EXPORT BOOL hb_clsIsParent( USHORT uiClass, char * szParentName ) { if( uiClass && uiClass <= s_uiClasses ) { - PCLASS pClass = &s_pClasses[ uiClass - 1 ]; + PCLASS pClass = &s_pClasses[ uiClass ]; if( strcmp( pClass->szName, szParentName ) == 0 ) return TRUE; @@ -822,7 +1099,7 @@ HB_EXPORT BOOL hb_clsIsParent( USHORT uiClass, char * szParentName ) PHB_DYNS pMsg = hb_dynsymFindName( szParentName ); if( pMsg ) - return hb_clsHasParent( &s_pClasses[ uiClass - 1 ], pMsg ); + return hb_clsHasParent( &s_pClasses[ uiClass ], pMsg ); } } @@ -844,70 +1121,48 @@ HB_EXPORT USHORT hb_objGetClass( PHB_ITEM pItem ) */ HB_EXPORT char * hb_objGetClsName( PHB_ITEM pObject ) { - char * szClassName; - HB_TRACE(HB_TR_DEBUG, ("hb_objGetClsName(%p)", pObject)); if( HB_IS_ARRAY( pObject ) ) { - if( ! pObject->item.asArray.value->uiClass ) - szClassName = "ARRAY"; + if( pObject->item.asArray.value->uiClass != 0 ) + return s_pClasses[ pObject->item.asArray.value->uiClass ].szName; else - szClassName = - s_pClasses[ pObject->item.asArray.value->uiClass - 1 ].szName; + return "ARRAY"; } - else /* built in types */ - { - switch( pObject->type ) - { - case HB_IT_NIL: - szClassName = "NIL"; - break; + /* built in types */ + else if( HB_IS_NIL( pObject ) ) + return "NIL"; - case HB_IT_STRING: - case HB_IT_MEMO: - szClassName = "CHARACTER"; - break; + else if( HB_IS_STRING( pObject ) ) + return "CHARACTER"; - case HB_IT_BLOCK: - szClassName = "BLOCK"; - break; + else if( HB_IS_NUMERIC( pObject ) ) + return "NUMERIC"; - case HB_IT_DATE: - szClassName = "DATE"; - break; + else if( HB_IS_DATE( pObject ) ) + return "DATE"; - case HB_IT_INTEGER: - case HB_IT_LONG: - case HB_IT_DOUBLE: - szClassName = "NUMERIC"; - break; + else if( HB_IS_LOGICAL( pObject ) ) + return "LOGICAL"; - case HB_IT_LOGICAL: - szClassName = "LOGICAL"; - break; + else if( HB_IS_BLOCK( pObject ) ) + return "BLOCK"; - case HB_IT_POINTER: - szClassName = "POINTER"; - break; + else if( HB_IS_POINTER( pObject ) ) + return "POINTER"; - case HB_IT_SYMBOL: - szClassName = "SYMBOL"; - break; + else if( HB_IS_SYMBOL( pObject ) ) + return "SYMBOL"; - default: - szClassName = "UNKNOWN"; - break; - } - } - - return szClassName; + else + return "UNKNOWN"; } HB_EXPORT char * hb_clsName( USHORT uiClass ) { if( uiClass && uiClass <= s_uiClasses ) - return s_pClasses[ uiClass - 1 ].szName; + return s_pClasses[ uiClass ].szName; else return NULL; } @@ -932,12 +1187,12 @@ HB_EXPORT char * hb_objGetRealClsName( PHB_ITEM pObject, char * szName ) if( pMsg ) { - PMETHOD pMethod = hb_clsFindMsg( &s_pClasses[ uiClass - 1 ], pMsg ); + PMETHOD pMethod = hb_clsFindMsg( &s_pClasses[ uiClass ], pMsg ); if( pMethod ) uiClass = pMethod->uiSprClass; } if( uiClass && uiClass <= s_uiClasses ) - return s_pClasses[ uiClass - 1 ].szName; + return s_pClasses[ uiClass ].szName; } } @@ -958,7 +1213,7 @@ char * hb_clsRealMethodName( void ) if( pStack->uiClass && pStack->uiClass <= s_uiClasses ) { - PCLASS pClass = &s_pClasses[ pStack->uiClass - 1 ]; + PCLASS pClass = &s_pClasses[ pStack->uiClass ]; if( ( ULONG ) pStack->uiMethod < hb_clsMthNum( pClass ) ) { @@ -983,7 +1238,7 @@ static LONG hb_clsSenderOffset( void ) if( lOffset > 0 && HB_IS_BLOCK( hb_stackItem( lOffset + 1 ) ) && ( hb_stackItem( lOffset )->item.asSymbol.value == &hb_symEval || hb_stackItem( lOffset )->item.asSymbol.value->pDynSym == - s___msgEval.pDynSym ) ) + hb_symEval.pDynSym ) ) { lOffset = hb_stackItem( lOffset )->item.asSymbol.stackstate->lBaseItem; @@ -1019,7 +1274,7 @@ static USHORT hb_clsSenderMethodClasss( void ) PHB_STACK_STATE pStack = hb_stackItem( lOffset )->item.asSymbol.stackstate; if( pStack->uiClass ) - return ( s_pClasses[ pStack->uiClass - 1 ].pMethods + + return ( s_pClasses[ pStack->uiClass ].pMethods + pStack->uiMethod )->uiSprClass; } return 0; @@ -1034,7 +1289,7 @@ static PHB_SYMB hb_clsSenderSymbol( void ) { pSym = hb_stackItem( lOffset )->item.asSymbol.value; - if( pSym == &hb_symEval || pSym->pDynSym == s___msgEval.pDynSym ) + if( pSym == &hb_symEval || pSym->pDynSym == hb_symEval.pDynSym ) { PHB_ITEM pBlock = hb_stackItem( lOffset + 1 ); @@ -1078,11 +1333,11 @@ static PHB_SYMB hb_clsValidScope( PMETHOD pMethod, PHB_STACK_STATE pStack ) */ if( pMethod->uiScope & HB_OO_CLSTP_OVERLOADED ) { - PCLASS pClass = &s_pClasses[ uiSenderClass - 1 ]; + PCLASS pClass = &s_pClasses[ uiSenderClass ]; PMETHOD pHiddenMthd = hb_clsFindMsg( pClass, pMethod->pMessage ); - if( pHiddenMthd && pHiddenMthd->uiSprClass == uiSenderClass && - pHiddenMthd->uiScope & HB_OO_CLSTP_NONVIRTUAL ) + if( pHiddenMthd && ( pHiddenMthd->uiScope & HB_OO_CLSTP_NONVIRTUAL ) && + pHiddenMthd->uiSprClass == uiSenderClass ) { pStack->uiClass = uiSenderClass; pStack->uiMethod = ( USHORT ) ( pHiddenMthd - pClass->pMethods ); @@ -1092,24 +1347,32 @@ static PHB_SYMB hb_clsValidScope( PMETHOD pMethod, PHB_STACK_STATE pStack ) if( pMethod->uiScope & HB_OO_CLSTP_HIDDEN ) { - if( ! hb_clsIsFriendSymbol( &s_pClasses[ pStack->uiClass - 1 ], - s_pClasses[ uiSenderClass - 1 ].pClassFuncSym ) ) + if( ! hb_clsIsFriendSymbol( &s_pClasses[ pMethod->uiSprClass ], + s_pClasses[ uiSenderClass ].pClassFuncSym ) ) return &s___msgScopeErr; } else if( pMethod->uiScope & HB_OO_CLSTP_PROTECTED && - ! hb_clsHasParent( &s_pClasses[ pStack->uiClass - 1 ], - s_pClasses[ uiSenderClass - 1 ].pClassSym ) && - ! hb_clsHasParent( &s_pClasses[ uiSenderClass - 1 ], - s_pClasses[ pStack->uiClass - 1 ].pClassSym ) && - ! hb_clsIsFriendSymbol( &s_pClasses[ pStack->uiClass - 1 ], - s_pClasses[ uiSenderClass - 1 ].pClassFuncSym ) ) + ! hb_clsHasParent( &s_pClasses[ pStack->uiClass ], + s_pClasses[ uiSenderClass ].pClassSym ) && + ! hb_clsHasParent( &s_pClasses[ uiSenderClass ], + s_pClasses[ pStack->uiClass ].pClassSym ) && + ! hb_clsIsFriendSymbol( &s_pClasses[ pMethod->uiSprClass ], + s_pClasses[ uiSenderClass ].pClassFuncSym ) && + ( pStack->uiClass == pMethod->uiSprClass || + ! hb_clsIsFriendSymbol( &s_pClasses[ pStack->uiClass ], + s_pClasses[ uiSenderClass ].pClassFuncSym ) ) ) return &s___msgScopeErr; } else if( pMethod->uiScope & ( HB_OO_CLSTP_HIDDEN | HB_OO_CLSTP_PROTECTED ) ) { - if( ! hb_clsIsFriendSymbol( &s_pClasses[ pStack->uiClass - 1 ], - hb_clsSenderSymbol() ) ) - return &s___msgScopeErr; + PHB_SYMB pSym = hb_clsSenderSymbol(); + + if( ! hb_clsIsFriendSymbol( &s_pClasses[ pMethod->uiSprClass ], pSym ) ) + { + if( ( pMethod->uiScope & HB_OO_CLSTP_HIDDEN ) || + ! hb_clsIsFriendSymbol( &s_pClasses[ pStack->uiClass ], pSym ) ) + return &s___msgScopeErr; + } } } @@ -1133,46 +1396,63 @@ PHB_SYMB hb_objGetMethod( PHB_ITEM pObject, PHB_SYMB pMessage, if( HB_IS_ARRAY( pObject ) ) { - USHORT uiClass = pObject->item.asArray.value->uiClass; - - if( pStack ) + if( pObject->item.asArray.value->uiClass ) { - pStack->uiClass = uiClass; - if( pObject->item.asArray.value->uiPrevCls ) + pClass = &s_pClasses[ pObject->item.asArray.value->uiClass ]; + if( pStack ) { - /* - * Copy real object - do not move! the same super casted - * object can be used more then once and we mustn't destroy it. - * We can safely use hb_stackReturnItem() here. - */ - hb_itemCopy( hb_stackReturnItem(), pObject->item.asArray.value->pItems ); - /* move real object back to the stack */ - hb_itemMove( pObject, hb_stackReturnItem() ); - } - } - if( uiClass && uiClass <= s_uiClasses ) - { - PMETHOD pMethod; - - pClass = &s_pClasses[ uiClass - 1 ]; - pMethod = hb_clsFindMsg( pClass, pMsg ); - if( pMethod ) - { - if( pStack ) + pStack->uiClass = pObject->item.asArray.value->uiClass; + if( pObject->item.asArray.value->uiPrevCls ) { - pStack->uiMethod = ( USHORT ) ( pMethod - pClass->pMethods ); - return hb_clsValidScope( pMethod, pStack ); + /* + * Copy real object - do not move! the same super casted + * object can be used more then once and we mustn't destroy it. + * We can safely use hb_stackReturnItem() here. + */ + hb_itemCopy( hb_stackReturnItem(), pObject->item.asArray.value->pItems ); + /* move real object back to the stack */ + hb_itemMove( pObject, hb_stackReturnItem() ); } - return pMethod->pFuncSym; +#ifdef HB_MSG_POOL + { + USHORT uiBucket = BUCKETSIZE, * puiMsgIdx = + pClass->puiMsgIdx + hb_clsBucketPos( pMsg, pClass->uiHashKey ); + + do + { + PMETHOD pMethod = &pClass->pMethods[ * puiMsgIdx ]; + if( pMethod->pMessage == pMsg ) + { + pStack->uiMethod = * puiMsgIdx; + return hb_clsValidScope( pMethod, pStack ); + } + ++puiMsgIdx; + } + while( --uiBucket ); + } +#else + { + PMETHOD pMethod = hb_clsFindMsg( pClass, pMsg ); + if( pMethod ) + { + pStack->uiMethod = ( USHORT ) ( pMethod - pClass->pMethods ); + return hb_clsValidScope( pMethod, pStack ); + } + } +#endif + } + else + { + PMETHOD pMethod = hb_clsFindMsg( pClass, pMsg ); + if( pMethod ) + return pMethod->pFuncSym; } } } else if( HB_IS_BLOCK( pObject ) ) { - if( pMessage == &hb_symEval ) - return pMessage; - else if( pMsg == s___msgEval.pDynSym ) + if( pMessage == &hb_symEval || pMsg == hb_symEval.pDynSym ) return &hb_symEval; } else if( HB_IS_BYREF( pObject ) ) @@ -1274,9 +1554,6 @@ PHB_SYMB hb_objGetMethod( PHB_ITEM pObject, PHB_SYMB pMessage, return &s___msgClassSel; /* - else if( pMsg == s___msgEval.pDynSym ) - return &s___msgEval; - else if( pMsg == s___msgClsParent.pDynSym ) return &s___msgClsParent; @@ -1313,12 +1590,12 @@ BOOL hb_objGetVarRef( PHB_ITEM pObject, PHB_SYMB pMessage, if( pExecSym->value.pFunPtr == hb___msgSetData ) { USHORT uiObjClass = pObject->item.asArray.value->uiClass; - PCLASS pClass = &s_pClasses[ pStack->uiClass - 1 ]; + PCLASS pClass = &s_pClasses[ pStack->uiClass ]; PMETHOD pMethod = pClass->pMethods + pStack->uiMethod; ULONG ulIndex = pMethod->uiData; if( pStack->uiClass != uiObjClass ) - ulIndex += hb_clsParentInstanceOffset( &s_pClasses[ uiObjClass - 1 ], + ulIndex += hb_clsParentInstanceOffset( &s_pClasses[ uiObjClass ], s_pClasses[ pMethod->uiSprClass ].pClassSym ); else ulIndex += pMethod->uiOffset; @@ -1339,14 +1616,14 @@ BOOL hb_objGetVarRef( PHB_ITEM pObject, PHB_SYMB pMessage, } else if( pExecSym->value.pFunPtr == hb___msgSetShrData ) { - PCLASS pClass = &s_pClasses[ pStack->uiClass - 1 ]; + PCLASS pClass = &s_pClasses[ pStack->uiClass ]; PMETHOD pMethod = pClass->pMethods + pStack->uiMethod; - return hb_arrayGetItemRef( s_pClasses[ pMethod->uiSprClass - 1 ].pSharedDatas, + return hb_arrayGetItemRef( s_pClasses[ pMethod->uiSprClass ].pSharedDatas, pMethod->uiData, hb_stackReturnItem() ); } else if( pExecSym->value.pFunPtr == hb___msgScopeErr ) - hb___msgScopeErr(); + (pExecSym->value.pFunPtr)(); } return FALSE; @@ -1358,7 +1635,7 @@ BOOL hb_objGetVarRef( PHB_ITEM pObject, PHB_SYMB pMessage, BOOL hb_clsHasDestructor( USHORT uiClass ) { if( uiClass && uiClass <= s_uiClasses ) - return s_pClasses[ uiClass - 1 ].fHasDestructor; + return s_pClasses[ uiClass ].fHasDestructor; else return FALSE; } @@ -1368,11 +1645,10 @@ BOOL hb_clsHasDestructor( USHORT uiClass ) */ void hb_objDestructorCall( PHB_ITEM pObject ) { - if( pObject->type == HB_IT_ARRAY && - pObject->item.asArray.value->uiClass != 0 && + if( HB_IS_OBJECT( pObject ) && pObject->item.asArray.value->uiClass <= s_uiClasses ) { - PCLASS pClass = &s_pClasses[ pObject->item.asArray.value->uiClass - 1 ]; + PCLASS pClass = &s_pClasses[ pObject->item.asArray.value->uiClass ]; if( pClass->fHasDestructor ) { @@ -1396,10 +1672,9 @@ BOOL hb_objHasOperator( PHB_ITEM pObject, USHORT uiOperator ) { HB_TRACE(HB_TR_DEBUG, ("hb_objHasOperator(%p,%hu)", pObject, uiOperator)); - if( pObject->type == HB_IT_ARRAY && - pObject->item.asArray.value->uiClass != 0 ) + if( HB_IS_OBJECT( pObject ) ) { - PCLASS pClass = &s_pClasses[ pObject->item.asArray.value->uiClass - 1 ]; + PCLASS pClass = &s_pClasses[ pObject->item.asArray.value->uiClass ]; return ( pClass->ulOpFlags & ( 1UL << uiOperator ) ) != 0; } @@ -1583,10 +1858,84 @@ static USHORT hb_clsUpdateScope( USHORT uiScope, BOOL fAssign ) return uiScope; } +static HB_TYPE hb_clsGetItemType( PHB_ITEM pItem ) +{ + if( pItem ) + { + if( HB_IS_STRING( pItem ) ) + { + switch( hb_itemGetCPtr( pItem )[ 0 ] ) + { + case 'C': + case 'c': + case '\0': + return HB_IT_STRING; + + case 'D': + case 'd': + return HB_IT_DATE; + + case 'L': + case 'l': + return HB_IT_LOGICAL; + + case 'I': + case 'i': + return HB_IT_NUMINT; + + case 'N': + case 'n': + return HB_IT_NUMERIC; + + case 'A': + case 'a': + return HB_IT_ARRAY; + + case 'B': + case 'b': + return HB_IT_BLOCK; + + case 'P': + case 'p': + return HB_IT_POINTER; + + case 'S': + case 's': + return HB_IT_SYMBOL; + } + } + else if( HB_IS_ARRAY( pItem ) ) + return HB_IT_ARRAY; + + else if( HB_IS_NUMINT( pItem ) ) + return HB_IT_NUMINT; + + else if( HB_IS_NUMERIC( pItem ) ) + return HB_IT_NUMERIC; + + else if( HB_IS_DATE( pItem ) ) + return HB_IT_DATE; + + else if( HB_IS_LOGICAL( pItem ) ) + return HB_IT_LOGICAL; + + else if( HB_IS_BLOCK( pItem ) ) + return HB_IT_BLOCK; + + else if( HB_IS_POINTER( pItem ) ) + return HB_IT_POINTER; + + else if( HB_IS_SYMBOL( pItem ) ) + return HB_IT_SYMBOL; + } + + return 0; +} + /* ================================================ */ /* - * __clsAddMsg( , , , , [xInit], , ) + * __clsAddMsg( , , , , [xInit], , ) * * Add a message to the class. * @@ -1609,20 +1958,24 @@ static USHORT hb_clsUpdateScope( USHORT uiScope, BOOL fAssign ) * HB_OO_MSG_CLASSDATA : Optional initializer for DATA * HB_OO_MSG_SUPER : Superclass handle * - * HB_OO_CLSTP_EXPORTED 1 : default for data and method + * * HB_OO_CLSTP_EXPORTED 1 : default for data and method * HB_OO_CLSTP_PROTECTED 2 : method or data protected * HB_OO_CLSTP_HIDDEN 4 : method or data hidden - * HB_OO_CLSTP_CTOR 8 : method constructor + * * HB_OO_CLSTP_CTOR 8 : method constructor * HB_OO_CLSTP_READONLY 16 : data read only * HB_OO_CLSTP_SHARED 32 : (method or) data shared - * HB_OO_CLSTP_CLASS 64 : message is the name of a superclass - * HB_OO_CLSTP_SUPER 128 : message is herited + * * HB_OO_CLSTP_CLASS 64 : message is the name of a superclass + * * HB_OO_CLSTP_SUPER 128 : message is herited * HB_OO_CLSTP_PERSIST 256 : message is persistent (PROPERTY) * HB_OO_CLSTP_NONVIRTUAL 512 : Class method constructor * HB_OO_CLSTP_OVERLOADED 1024 : Class method constructor * * HB_OO_CLSTP_CLASSCTOR 2048 : Class method constructor * HB_OO_CLSTP_CLASSMETH 4096 : Class method + * + * item type restriction in assignment - not empty character value + * where first letter is item type or item of a given value + * */ HB_FUNC( __CLSADDMSG ) @@ -1631,11 +1984,11 @@ HB_FUNC( __CLSADDMSG ) if( uiClass && uiClass <= s_uiClasses ) { - PCLASS pClass = &s_pClasses[ uiClass - 1 ]; + PCLASS pClass = &s_pClasses[ uiClass ]; PHB_DYNS pMessage; PMETHOD pNewMeth; - USHORT uiOperator, uiSprClass = 0, uiIndex = 0; + USHORT uiOperator, uiSprClass = 0, uiIndex = 0, uiPrevCls, uiPrevMth; PHB_SYMB pOpSym, pFuncSym = NULL; PHB_ITEM pBlock = NULL; BOOL fOK; @@ -1643,13 +1996,11 @@ HB_FUNC( __CLSADDMSG ) char * szMessage = hb_parc( 2 ); USHORT nType = ( USHORT ) hb_parni( 4 ); USHORT uiScope = ( USHORT ) ( ISNUM( 6 ) ? hb_parni( 6 ) : HB_OO_CLSTP_EXPORTED ); + HB_TYPE itemType = hb_clsGetItemType( hb_param( 7, HB_IT_ANY ) ); if( pClass->fLocked ) return; - if( hb_parl( 7 ) ) - uiScope |= HB_OO_CLSTP_PERSIST; - /* translate names of operator overloading messages */ if( nType == HB_OO_MSG_DESTRUCTOR ) pMessage = s___msgDestructor.pDynSym; @@ -1781,6 +2132,9 @@ HB_FUNC( __CLSADDMSG ) if( ! pNewMeth ) return; + uiPrevCls = uiClass; + uiPrevMth = ( USHORT ) ( pClass->pMethods - pNewMeth ); + #ifndef HB_VIRTUAL_HIDDEN if( uiScope & HB_OO_CLSTP_HIDDEN ) uiScope |= HB_OO_CLSTP_NONVIRTUAL; @@ -1794,7 +2148,9 @@ HB_FUNC( __CLSADDMSG ) ( ( pNewMeth->uiScope & HB_OO_CLSTP_NONVIRTUAL ) && pNewMeth->uiSprClass != uiClass ); - if( ! hb_clsClearMsg( pClass, pNewMeth ) ) + uiPrevCls = pNewMeth->uiPrevCls; + uiPrevMth = pNewMeth->uiPrevMth; + if( ! hb_clsCanClearMethod( pNewMeth, TRUE ) ) return; memset( pNewMeth, 0, sizeof( METHOD ) ); @@ -1802,7 +2158,9 @@ HB_FUNC( __CLSADDMSG ) uiScope |= HB_OO_CLSTP_OVERLOADED; } pNewMeth->pMessage = pMessage; - pNewMeth->uiSprClass = uiClass ; /* now used !! */ + pNewMeth->uiSprClass = uiClass; + pNewMeth->uiPrevCls = uiPrevCls; + pNewMeth->uiPrevMth = uiPrevMth; switch( nType ) { @@ -1825,6 +2183,7 @@ HB_FUNC( __CLSADDMSG ) pNewMeth->pFuncSym = &s___msgSetData; pNewMeth->uiData = uiIndex; pNewMeth->uiOffset = pClass->uiDataFirst; + pNewMeth->itemType = itemType; } break; @@ -1840,8 +2199,9 @@ HB_FUNC( __CLSADDMSG ) case HB_OO_MSG_CLSASSIGN: - pNewMeth->uiScope = hb_clsUpdateScope( uiScope, TRUE ); pNewMeth->uiData = uiIndex; + pNewMeth->itemType = itemType; + pNewMeth->uiScope = hb_clsUpdateScope( uiScope, TRUE ); /* Class(y) does not allow to write to HIDDEN+READONLY instance variables, [druzus] */ if( pNewMeth->uiScope & HB_OO_CLSTP_READONLY && @@ -1900,9 +2260,8 @@ HB_FUNC( __CLSADDMSG ) pNewMeth->pFuncSym = &s___msgEvalInline; pNewMeth->uiScope = uiScope; - pNewMeth->uiData = ( USHORT ) ( hb_arrayLen( pClass->pInlines ) + 1 ); - hb_arraySize( pClass->pInlines, pNewMeth->uiData ); - hb_arraySet( pClass->pInlines, pNewMeth->uiData, pBlock ); + hb_arrayAdd( pClass->pInlines, pBlock ); + pNewMeth->uiData = ( USHORT ) hb_arrayLen( pClass->pInlines ); break; case HB_OO_MSG_VIRTUAL: @@ -1946,43 +2305,44 @@ HB_FUNC( __CLSADDMSG ) } } - /* - * := __clsNew( , , [], [], [] ) + * __clsNew( , , + * [], [], + * [] ) -> * * Create a new class * - * Name of the class - * Number of DATAs in the class - * Optional array with handle(s) of superclass(es) - * Class function symbol - * when true all functions and classes from the same + * Name of the class + * Number of DATAs in the class + * Optional array with handle(s) of superclass(es) + * Class function symbol, when NULLpublic function + * with the same name as szClassName is used + * when true all functions and classes from the same * module as pClassFunc are defined as friends */ -HB_FUNC( __CLSNEW ) +static USHORT hb_clsNew( char * szClassName, USHORT uiDatas, + PHB_ITEM pSuperArray, PHB_SYMB pClassFunc, + BOOL fModuleFriendly ) { PCLASS pNewCls; PMETHOD pMethod; - PHB_ITEM pahSuper; USHORT ui, uiSuper, uiSuperCls; - BOOL fModuleFriendly; - PHB_SYMB pClassFunc; USHORT * puiClassData = NULL, uiClassDataSize = 0; - pahSuper = hb_param( 3, HB_IT_ARRAY ); - uiSuper = ( USHORT ) ( pahSuper ? hb_arrayLen( pahSuper ) : 0 ); - - pClassFunc = hb_vmGetRealFuncSym( hb_itemGetSymbol( hb_param( 4, HB_IT_SYMBOL ) ) ); - fModuleFriendly = hb_parl( 5 ); + uiSuper = ( USHORT ) ( pSuperArray ? hb_arrayLen( pSuperArray ) : 0 ); + pClassFunc = hb_vmGetRealFuncSym( pClassFunc ); if( s_pClasses ) - s_pClasses = ( PCLASS ) hb_xrealloc( s_pClasses, sizeof( CLASS ) * ( s_uiClasses + 1 ) ); + s_pClasses = ( PCLASS ) hb_xrealloc( s_pClasses, sizeof( CLASS ) * ( s_uiClasses + 2 ) ); else - s_pClasses = ( PCLASS ) hb_xgrab( sizeof( CLASS ) ); + { + s_pClasses = ( PCLASS ) hb_xgrab( sizeof( CLASS ) * 2 ); + memset( s_pClasses, 0, sizeof( CLASS ) ); + } - pNewCls = s_pClasses + s_uiClasses++; + pNewCls = s_pClasses + ++s_uiClasses; memset( pNewCls, 0, sizeof( CLASS ) ); - pNewCls->szName = hb_strdup( hb_parc( 1 ) ); + pNewCls->szName = hb_strdup( szClassName ); pNewCls->pClassSym = hb_dynsymGet( pNewCls->szName ); if( !pClassFunc ) pClassFunc = hb_vmGetRealFuncSym( pNewCls->pClassSym->pSymbol ); @@ -1993,13 +2353,13 @@ HB_FUNC( __CLSNEW ) for( ui = 1; ui <= uiSuper; ++ui ) { - uiSuperCls = ( USHORT ) hb_arrayGetNI( pahSuper, ui ); + uiSuperCls = ( USHORT ) hb_arrayGetNI( pSuperArray, ui ); if( uiSuperCls && uiSuperCls < s_uiClasses ) { PCLASS pSprCls; - pSprCls = &s_pClasses[ uiSuperCls - 1 ]; - if( !pNewCls->pMethods ) /* This is the first superclass */ + pSprCls = &s_pClasses[ uiSuperCls ]; + if( ! hb_clsInited( pNewCls ) ) /* This is the first superclass */ { hb_clsCopyClass( pNewCls, pSprCls ); } @@ -2032,13 +2392,12 @@ HB_FUNC( __CLSNEW ) if( pSprCls->pMethods[ ul ].pMessage && pSprCls->pMethods[ ul ].pFuncSym == &s___msgSuper ) { - PCLASS pCls = &s_pClasses[ - pSprCls->pMethods[ ul ].uiSprClass - 1 ]; + PCLASS pCls = &s_pClasses[ pSprCls->pMethods[ ul ].uiSprClass ]; pMethod = hb_clsAllocMsg( pNewCls, pSprCls->pMethods[ ul ].pMessage ); if( ! pMethod ) - return; + return 0; if( pMethod->pMessage == NULL ) { pNewCls->uiMethods++; @@ -2052,7 +2411,7 @@ HB_FUNC( __CLSNEW ) /* add class casting if not exist */ pMethod = hb_clsAllocMsg( pNewCls, pSprCls->pClassSym ); if( ! pMethod ) - return; + return 0; if( pMethod->pMessage == NULL ) { pNewCls->uiMethods++; @@ -2077,7 +2436,7 @@ HB_FUNC( __CLSNEW ) pSprCls->pInitData[ ui ].pInitValue, HB_OO_MSG_DATA, pSprCls->pInitData[ ui ].uiData, hb_clsParentInstanceOffset( pNewCls, - s_pClasses[ uiCls - 1 ].pClassSym ), + s_pClasses[ uiCls ].pClassSym ), uiCls ); } } @@ -2091,7 +2450,7 @@ HB_FUNC( __CLSNEW ) { pMethod = hb_clsAllocMsg( pNewCls, pSprCls->pMethods[ ul ].pMessage ); if( ! pMethod ) - return; + return 0; /* Ok, this bucket is empty */ if( pMethod->pMessage == NULL ) @@ -2099,49 +2458,47 @@ HB_FUNC( __CLSNEW ) /* Now, we can increment the msg count */ pNewCls->uiMethods++; memcpy( pMethod, pSprCls->pMethods + ul, sizeof( METHOD ) ); - - if( pMethod->pFuncSym == &s___msgEvalInline ) + if( ! hb_clsUpdateHiddenMessages( pMethod, pMethod, pNewCls ) ) { - hb_arrayAdd( pNewCls->pInlines, - hb_arrayGetItemPtr( pSprCls->pInlines, pMethod->uiData ) ); - pMethod->uiData = ( USHORT ) hb_arrayLen( pNewCls->pInlines ); - } - else if( pMethod->pFuncSym == &s___msgSetClsData || - pMethod->pFuncSym == &s___msgGetClsData ) - { - if( pMethod->uiData > nLenClsDatas ) - hb_errInternal( HB_EI_CLSINVMETHOD, NULL, "__clsNew", NULL ); - - if( puiClassData[ pMethod->uiData - 1 ] == 0 ) + if( pMethod->pFuncSym == &s___msgSetClsData || + pMethod->pFuncSym == &s___msgGetClsData ) { - puiClassData[ pMethod->uiData - 1 ] = ( USHORT ) - hb_arrayLen( pNewCls->pClassDatas ) + 1; - hb_arraySize( pNewCls->pClassDatas, - puiClassData[ pMethod->uiData - 1 ] ); + if( pMethod->uiData > nLenClsDatas ) + hb_errInternal( HB_EI_CLSINVMETHOD, NULL, "__clsNew", NULL ); + + if( puiClassData[ pMethod->uiData - 1 ] == 0 ) + { + puiClassData[ pMethod->uiData - 1 ] = ( USHORT ) + hb_arrayLen( pNewCls->pClassDatas ) + 1; + hb_arraySize( pNewCls->pClassDatas, + puiClassData[ pMethod->uiData - 1 ] ); + } + if( pMethod->uiOffset ) + { + pMethod->uiOffset = hb_clsAddInitValue( pNewCls, + pSprCls->pInitData[ pMethod->uiOffset - 1 ].pInitValue, + HB_OO_MSG_CLASSDATA, puiClassData[ pMethod->uiData - 1 ], + 0, uiSuperCls ); + } + pMethod->uiData = puiClassData[ pMethod->uiData - 1 ]; } - if( pMethod->uiOffset ) + else if( pMethod->pFuncSym == &s___msgSetData || + pMethod->pFuncSym == &s___msgGetData ) { - pMethod->uiOffset = hb_clsAddInitValue( pNewCls, - pSprCls->pInitData[ pMethod->uiOffset - 1 ].pInitValue, - HB_OO_MSG_CLASSDATA, puiClassData[ pMethod->uiData - 1 ], - 0, uiSuperCls ); + pMethod->uiOffset = hb_clsParentInstanceOffset( pNewCls, + s_pClasses[ pMethod->uiSprClass ].pClassSym ); } - pMethod->uiData = puiClassData[ pMethod->uiData - 1 ]; + pMethod->uiScope |= HB_OO_CLSTP_SUPER; } - else if( pMethod->pFuncSym == &s___msgSetData || - pMethod->pFuncSym == &s___msgGetData ) - { - USHORT uiIndex = pMethod->uiData + pMethod->uiOffset; - if( uiIndex > pSprCls->uiDatas ) - hb_errInternal( HB_EI_CLSINVMETHOD, NULL, "__clsNew", NULL ); - pMethod->uiOffset = hb_clsParentInstanceOffset( pNewCls, - s_pClasses[ pMethod->uiSprClass - 1 ].pClassSym ); - } - pMethod->uiScope |= HB_OO_CLSTP_SUPER; } - else if( pSprCls->pMethods[ ul ].uiScope & - ( HB_OO_CLSTP_OVERLOADED | HB_OO_CLSTP_NONVIRTUAL ) ) - pMethod->uiScope |= HB_OO_CLSTP_OVERLOADED; + else + { + if( pSprCls->pMethods[ ul ].uiScope & + ( HB_OO_CLSTP_OVERLOADED | HB_OO_CLSTP_NONVIRTUAL ) ) + pMethod->uiScope |= HB_OO_CLSTP_OVERLOADED; + + hb_clsUpdateHiddenMessages( pSprCls->pMethods + ul, pMethod, pNewCls ); + } } } pNewCls->ulOpFlags |= pSprCls->ulOpFlags; @@ -2151,7 +2508,7 @@ HB_FUNC( __CLSNEW ) if( puiClassData ) hb_xfree( puiClassData ); - if( !pNewCls->pMethods ) + if( ! hb_clsInited( pNewCls ) ) { hb_clsDictInit( pNewCls, HASH_KEY ); pNewCls->pClassDatas = hb_itemArrayNew( 0 ); @@ -2162,7 +2519,7 @@ HB_FUNC( __CLSNEW ) /* add self class casting */ pMethod = hb_clsAllocMsg( pNewCls, pNewCls->pClassSym ); if( ! pMethod ) - return; + return 0; if( pMethod->pMessage == NULL ) { pNewCls->uiMethods++; @@ -2174,9 +2531,60 @@ HB_FUNC( __CLSNEW ) } pNewCls->uiDataFirst = pNewCls->uiDatas; - pNewCls->uiDatas += ( USHORT ) hb_parni( 2 ); + pNewCls->uiDatas += uiDatas; - hb_retni( s_uiClasses ); + return s_uiClasses; +} + +/* + * hb_clsNew( , < ) -> + * + * := __clsNew( , , [], [], [] ) + * + * Create a new class + * + * Name of the class + * Number of DATAs in the class + * Optional array with handle(s) of superclass(es) + * Class function symbol + * when true all functions and classes from the same + * module as pClassFunc are defined as friends + */ +HB_FUNC( __CLSNEW ) +{ + char * szClassName; + PHB_ITEM pDatas, pSuperArray, pClassFunc, pModFriend; + + szClassName = hb_parc( 1 ); + + pDatas = hb_param( 2, HB_IT_ANY ); + + pSuperArray = hb_param( 3, HB_IT_ANY ); + if( pSuperArray && HB_IS_NIL( pSuperArray ) ) + pSuperArray = NULL; + + pClassFunc = hb_param( 4, HB_IT_ANY ); + if( pClassFunc && HB_IS_NIL( pClassFunc ) ) + pClassFunc = NULL; + + pModFriend = hb_param( 5, HB_IT_ANY ); + if( pModFriend && HB_IS_NIL( pModFriend ) ) + pModFriend = NULL; + + if( szClassName && + ( ! pDatas || HB_IS_NUMERIC( pDatas ) ) && + ( ! pSuperArray || HB_IS_ARRAY( pSuperArray ) ) && + ( ! pClassFunc || HB_IS_SYMBOL( pClassFunc ) ) && + ( ! pModFriend || HB_IS_LOGICAL( pModFriend ) ) ) + { + USHORT uiClass; + uiClass = hb_clsNew( szClassName, ( USHORT ) hb_itemGetNI( pDatas ), + pSuperArray, hb_itemGetSymbol( pClassFunc ), + hb_itemGetL( pModFriend ) ); + hb_retni( uiClass ); + } + else + hb_errRT_BASE( EG_ARG, 3000, NULL, "__CLSNEW", HB_ERR_ARGS_BASEPARAMS ); } /* @@ -2190,7 +2598,7 @@ HB_FUNC( __CLSADDFRIEND ) if( uiClass && uiClass <= s_uiClasses ) { - PCLASS pClass = &s_pClasses[ uiClass - 1 ]; + PCLASS pClass = &s_pClasses[ uiClass ]; if( !pClass->fLocked ) { @@ -2216,20 +2624,20 @@ HB_FUNC( __CLSDELMSG ) PHB_ITEM pString = hb_param( 2, HB_IT_STRING ); if( uiClass && uiClass <= s_uiClasses && pString && - ! s_pClasses[ uiClass - 1 ].fLocked ) + ! s_pClasses[ uiClass ].fLocked ) { PHB_DYNS pMsg = hb_dynsymFindName( pString->item.asString.value ); if( pMsg ) - hb_clsFreeMsg( &s_pClasses[ uiClass - 1 ], pMsg ); + hb_clsFreeMsg( &s_pClasses[ uiClass ], pMsg ); } } /* - * [] := hb_clsInst( ) + * hb_clsInst( ) -> * - * Create a (super)object from class definition + * Create a new object from class definition */ static PHB_ITEM hb_clsInst( USHORT uiClass ) { @@ -2237,7 +2645,7 @@ static PHB_ITEM hb_clsInst( USHORT uiClass ) if( uiClass && uiClass <= s_uiClasses ) { - PCLASS pClass = &s_pClasses[ uiClass - 1 ]; + PCLASS pClass = &s_pClasses[ uiClass ]; pSelf = hb_itemNew( NULL ); hb_arrayNew( pSelf, pClass->uiDatas ); @@ -2290,7 +2698,7 @@ HB_FUNC( __CLSINST ) PHB_ITEM pSelf = hb_clsInst( ( USHORT ) hb_parni( 1 ) ); if( pSelf ) - hb_itemRelease( hb_itemReturn( pSelf ) ); + hb_itemRelease( hb_itemReturnForward( pSelf ) ); } /* @@ -2302,7 +2710,7 @@ HB_FUNC( __CLSLOCK ) USHORT uiClass = ( USHORT ) hb_parni( 1 ); if( uiClass && uiClass <= s_uiClasses ) - s_pClasses[ uiClass - 1 ].fLocked = TRUE; + s_pClasses[ uiClass ].fLocked = TRUE; } /* @@ -2316,13 +2724,13 @@ HB_FUNC( __CLSMODMSG ) PHB_ITEM pString = hb_param( 2, HB_IT_STRING ); if( uiClass && uiClass <= s_uiClasses && pString && - ! s_pClasses[ uiClass - 1 ].fLocked ) + ! s_pClasses[ uiClass ].fLocked ) { PHB_DYNS pMsg = hb_dynsymFindName( pString->item.asString.value ); if( pMsg ) { - PCLASS pClass = &s_pClasses[ uiClass - 1 ]; + PCLASS pClass = &s_pClasses[ uiClass ]; PMETHOD pMethod = hb_clsFindMsg( pClass, pMsg ); if( pMethod ) @@ -2340,7 +2748,8 @@ HB_FUNC( __CLSMODMSG ) if( pBlock == NULL ) hb_errRT_BASE( EG_ARG, 3000, "Cannot modify INLINE method", "__CLSMODMSG", 0 ); else - hb_arraySet( pClass->pInlines, pMethod->uiData, pBlock ); + hb_arraySet( s_pClasses[ pMethod->uiSprClass ].pInlines, + pMethod->uiData, pBlock ); } else /* Modify METHOD */ { @@ -2433,7 +2842,7 @@ HB_FUNC( __OBJCLONE ) if( pSrcObject ) { pDstObject = hb_arrayClone( pSrcObject ); - hb_itemRelease( hb_itemReturn( pDstObject ) ); + hb_itemRelease( hb_itemReturnForward( pDstObject ) ); } else { @@ -2457,11 +2866,11 @@ HB_FUNC( __CLSINSTSUPER ) if( pDynSym ) { - for( uiClass = 0; uiClass < s_uiClasses; uiClass++ ) + for( uiClass = 1; uiClass <= s_uiClasses; uiClass++ ) { if( s_pClasses[ uiClass ].pClassSym == pDynSym ) { - uiClassH = uiClass + 1; + uiClassH = uiClass; break; } } @@ -2480,15 +2889,15 @@ HB_FUNC( __CLSINSTSUPER ) { uiClass = pObject->item.asArray.value->uiClass; - if( s_pClasses[ uiClass - 1 ].pClassSym == pDynSym ) + if( s_pClasses[ uiClass ].pClassSym == pDynSym ) uiClassH = uiClass; else { - for( uiClass = 0; uiClass < s_uiClasses; uiClass++ ) + for( uiClass = 1; uiClass <= s_uiClasses; uiClass++ ) { if( s_pClasses[ uiClass ].pClassSym == pDynSym ) { - uiClassH = uiClass + 1; + uiClassH = uiClass; break; } } @@ -2503,7 +2912,7 @@ HB_FUNC( __CLSINSTSUPER ) if( HB_IS_OBJECT( pObject ) ) { uiClass = pObject->item.asArray.value->uiClass; - if( s_pClasses[ uiClass - 1 ].pClassSym == pDynSym ) + if( s_pClasses[ uiClass ].pClassSym == pDynSym ) uiClassH = uiClass; } } @@ -2549,7 +2958,7 @@ HB_FUNC( __CLS_CNTCLSDATA ) USHORT uiClass = ( USHORT ) hb_parni( 1 ); hb_retni( uiClass && uiClass <= s_uiClasses ? - hb_arrayLen( s_pClasses[ uiClass - 1 ].pClassDatas ) : 0 ); + hb_arrayLen( s_pClasses[ uiClass ].pClassDatas ) : 0 ); } /* @@ -2562,7 +2971,7 @@ HB_FUNC( __CLS_CNTSHRDATA ) USHORT uiClass = ( USHORT ) hb_parni( 1 ); hb_retni( uiClass && uiClass <= s_uiClasses ? - hb_arrayLen( s_pClasses[ uiClass - 1 ].pSharedDatas ) : 0 ); + hb_arrayLen( s_pClasses[ uiClass ].pSharedDatas ) : 0 ); } /* @@ -2575,7 +2984,7 @@ HB_FUNC( __CLS_CNTDATA ) USHORT uiClass = ( USHORT ) hb_parni( 1 ); hb_retni( uiClass && uiClass <= s_uiClasses ? - s_pClasses[ uiClass - 1 ].uiDatas : 0 ); + s_pClasses[ uiClass ].uiDatas : 0 ); } /* @@ -2587,12 +2996,12 @@ HB_FUNC( __CLS_DECDATA ) { USHORT uiClass = ( USHORT ) hb_parni( 1 ); - if( uiClass && uiClass <= s_uiClasses && s_pClasses[ uiClass - 1 ].uiDatas ) + if( uiClass && uiClass <= s_uiClasses && s_pClasses[ uiClass ].uiDatas ) { - if( s_pClasses[ uiClass - 1 ].fLocked ) - hb_retni( s_pClasses[ uiClass - 1 ].uiDatas ); + if( s_pClasses[ uiClass ].fLocked ) + hb_retni( s_pClasses[ uiClass ].uiDatas ); else - hb_retni( --s_pClasses[ uiClass - 1 ].uiDatas ); + hb_retni( --s_pClasses[ uiClass ].uiDatas ); } else hb_retni( 0 ); @@ -2608,10 +3017,10 @@ HB_FUNC( __CLS_INCDATA ) if( uiClass && uiClass <= s_uiClasses ) { - if( s_pClasses[ uiClass - 1 ].fLocked ) - hb_retni( s_pClasses[ uiClass - 1 ].uiDatas ); + if( s_pClasses[ uiClass ].fLocked ) + hb_retni( s_pClasses[ uiClass ].uiDatas ); else - hb_retni( ++s_pClasses[ uiClass - 1 ].uiDatas ); + hb_retni( ++s_pClasses[ uiClass ].uiDatas ); } else hb_retni( 0 ); @@ -2650,7 +3059,6 @@ HB_FUNC( __CLASSNAME ) } /* NOTE: Undocumented Clipper function */ -/* NOTE: Based on hb___msgClsSel() */ HB_FUNC( __CLASSSEL ) { @@ -2659,7 +3067,7 @@ HB_FUNC( __CLASSSEL ) if( uiClass && uiClass <= s_uiClasses ) { - PCLASS pClass = &s_pClasses[ uiClass - 1 ]; + PCLASS pClass = &s_pClasses[ uiClass ]; PMETHOD pMethod = pClass->pMethods; ULONG ulLimit = hb_clsMthNum( pClass ), ulPos = 0; @@ -2683,7 +3091,7 @@ HB_FUNC( __CLASSSEL ) hb_arraySize( pReturn, ulPos ); } - hb_itemRelease( hb_itemReturn( pReturn ) ); + hb_itemRelease( hb_itemReturnForward( pReturn ) ); } /* to be used from Classes ERROR HANDLER method */ @@ -2721,9 +3129,9 @@ HB_FUNC( __SENDER ) } /* - * Added by RāC&JfL + * ClassH( ) -> * - * based on hb___msgClsH( void ) + * Returns class handle of */ HB_FUNC( __CLASSH ) { @@ -2732,29 +3140,6 @@ HB_FUNC( __CLASSH ) hb_retni( pObject ? pObject->item.asArray.value->uiClass : 0 ); } -/* - * based on hb___msgEval( void ) - */ -HB_FUNC( __EVAL ) -{ - PHB_ITEM pObject = hb_param( 1, HB_IT_ANY ); - USHORT uiPCount = hb_pcount(); - - if( pObject && HB_IS_BLOCK( pObject ) ) - { - USHORT uiParam; - - hb_vmPushSymbol( &hb_symEval ); - hb_vmPush( pObject ); /* Push block */ - for( uiParam = 1; uiParam <= uiPCount; ++uiParam ) - hb_vmPush( hb_stackItemFromBase( uiParam ) ); - - hb_vmDo( ( USHORT ) uiPCount ); - } - else - hb_errRT_BASE_SubstR( EG_NOMETHOD, 1004, NULL, "EVAL", pObject ? 1 : 0, pObject ); -} - /* ================================================ */ /* @@ -2762,7 +3147,7 @@ HB_FUNC( __EVAL ) * * Returns class handle of */ -static HARBOUR hb___msgClsH( void ) +static HARBOUR hb___msgClassH( void ) { hb_retni( hb_stackBaseItem()->item.asSymbol.stackstate->uiClass ); } @@ -2773,12 +3158,12 @@ static HARBOUR hb___msgClsH( void ) * * Return class name of . Can also be used for all types. */ -static HARBOUR hb___msgClsName( void ) +static HARBOUR hb___msgClassName( void ) { USHORT uiClass = hb_stackBaseItem()->item.asSymbol.stackstate->uiClass; if( uiClass ) - hb_retc( s_pClasses[ uiClass - 1 ].szName ); + hb_retc( s_pClasses[ uiClass ].szName ); else hb_retc( hb_objGetClsName( hb_stackSelfItem() ) ); } @@ -2789,14 +3174,14 @@ static HARBOUR hb___msgClsName( void ) * * Returns all the messages in */ -static HARBOUR hb___msgClsSel( void ) +static HARBOUR hb___msgClassSel( void ) { USHORT uiClass = hb_stackBaseItem()->item.asSymbol.stackstate->uiClass; if( uiClass && uiClass <= s_uiClasses ) { PHB_ITEM pReturn = hb_itemNew( NULL ); - PCLASS pClass = &s_pClasses[ uiClass - 1 ]; + PCLASS pClass = &s_pClasses[ uiClass ]; PMETHOD pMethod = pClass->pMethods; ULONG ulLimit = hb_clsMthNum( pClass ), ulPos = 0; USHORT nParam; @@ -2837,7 +3222,7 @@ static HARBOUR hb___msgClsSel( void ) if( ulPos < ( ULONG ) pClass->uiMethods ) hb_arraySize( pReturn, ulPos ); - hb_itemRelease( hb_itemReturn( pReturn ) ); + hb_itemRelease( hb_itemReturnForward( pReturn ) ); } } @@ -2850,7 +3235,7 @@ static HARBOUR hb___msgClsSel( void ) */ static HARBOUR hb___msgClass( void ) { - hb_itemReturn( hb_stackSelfItem() ); + hb_itemReturnForward( hb_stackSelfItem() ); } /* Added by JfL&RaC @@ -2859,7 +3244,7 @@ static HARBOUR hb___msgClass( void ) * Return true if is derived from xParam. * xParam can be either an obj or a classname */ -static HARBOUR hb___msgClsParent( void ) +static HARBOUR hb___msgClassParent( void ) { char * szParentName = NULL; PHB_ITEM pItem; @@ -2890,14 +3275,15 @@ static HARBOUR hb___msgClsParent( void ) static HARBOUR hb___msgEvalInline( void ) { PHB_STACK_STATE pStack = hb_stackBaseItem()->item.asSymbol.stackstate; - PCLASS pClass = &s_pClasses[ pStack->uiClass - 1 ]; + PCLASS pClass = &s_pClasses[ pStack->uiClass ]; PMETHOD pMethod = pClass->pMethods + pStack->uiMethod; USHORT uiPCount = hb_pcount(), uiParam; PHB_ITEM pBlock; hb_vmPushSymbol( &hb_symEval ); - hb_vmPush( hb_arrayGetItemPtr( pClass->pInlines, pMethod->uiData ) ); + hb_vmPush( hb_arrayGetItemPtr( s_pClasses[ pMethod->uiSprClass ].pInlines, + pMethod->uiData ) ); pBlock = hb_stackItemFromTop( -1 ); /* Push block */ pBlock->item.asBlock.hclass = pStack->uiClass; pBlock->item.asBlock.method = pStack->uiMethod; @@ -2912,31 +3298,6 @@ static HARBOUR hb___msgEvalInline( void ) hb_vmDo( uiPCount + 1 ); } -/* - * __msgEval() - * - * Internal function for the internal EVAL method. - */ -static HARBOUR hb___msgEval( void ) -{ - HB_ITEM_PTR pSelf = hb_stackSelfItem(); - - if( HB_IS_BLOCK( pSelf ) ) - { - USHORT uiParam; - USHORT uiPCount = hb_pcount(); - - hb_vmPushSymbol( &hb_symEval ); - hb_vmPush( pSelf ); - for( uiParam = 1; uiParam <= uiPCount; uiParam++ ) - hb_vmPush( hb_stackItemFromBase( uiParam ) ); - - hb_vmDo( ( USHORT ) uiPCount ); - } - else - hb_errRT_BASE_SubstR( EG_NOMETHOD, 1004, NULL, "EVAL", HB_ERR_ARGS_SELFPARAMS ); -} - /* * __msgNoMethod() * @@ -2977,11 +3338,11 @@ static HARBOUR hb___msgScopeErr( void ) char szProcName[ HB_SYMBOL_NAME_LEN + HB_SYMBOL_NAME_LEN + 5 ]; PHB_ITEM pObject = hb_stackSelfItem(); PMETHOD pMethod = s_pClasses[ - hb_stackBaseItem()->item.asSymbol.stackstate->uiClass - 1 ].pMethods + + hb_stackBaseItem()->item.asSymbol.stackstate->uiClass ].pMethods + hb_stackBaseItem()->item.asSymbol.stackstate->uiMethod; strcpy( szProcName, s_pClasses[ - pObject->item.asArray.value->uiClass - 1 ].szName ); + pObject->item.asArray.value->uiClass ].szName ); strcat( szProcName, ":" ); strcat( szProcName, pMethod->pMessage->pSymbol->szName ); @@ -2991,6 +3352,21 @@ static HARBOUR hb___msgScopeErr( void ) hb_errRT_BASE( EG_NOMETHOD, 42, "Scope violation (protected)", szProcName, 0 ); } +static HARBOUR hb___msgTypeErr( void ) +{ + char szProcName[ HB_SYMBOL_NAME_LEN + HB_SYMBOL_NAME_LEN + 5 ]; + PHB_ITEM pObject = hb_stackSelfItem(); + PMETHOD pMethod = s_pClasses[ + hb_stackBaseItem()->item.asSymbol.stackstate->uiClass ].pMethods + + hb_stackBaseItem()->item.asSymbol.stackstate->uiMethod; + + strcpy( szProcName, s_pClasses[ + pObject->item.asArray.value->uiClass ].szName ); + strcat( szProcName, ":" ); + strcat( szProcName, pMethod->pMessage->pSymbol->szName + 1 ); + hb_errRT_BASE( EG_NOMETHOD, 44, "Assigned value is wrong class", szProcName, HB_ERR_ARGS_BASEPARAMS ); +} + /* * __msgSuper() * @@ -2999,21 +3375,20 @@ static HARBOUR hb___msgScopeErr( void ) static HARBOUR hb___msgSuper( void ) { PHB_ITEM pObject = hb_stackSelfItem(); - PHB_ITEM pCopy = hb_itemArrayNew(1); + PHB_ITEM pReturn = hb_stackReturnItem(); PMETHOD pMethod = s_pClasses[ - hb_stackBaseItem()->item.asSymbol.stackstate->uiClass - 1 ].pMethods + + hb_stackBaseItem()->item.asSymbol.stackstate->uiClass ].pMethods + hb_stackBaseItem()->item.asSymbol.stackstate->uiMethod; + /* create a fake object array */ + hb_arrayNew( pReturn, 1 ); /* Now save the Self object as the 1st elem. */ - hb_arraySet( pCopy, 1, pObject ); - + hb_arraySet( pReturn, 1, pObject ); /* And transform it into a fake object */ /* backup of actual handel */ - pCopy->item.asArray.value->uiPrevCls = pObject->item.asArray.value->uiClass; + pReturn->item.asArray.value->uiPrevCls = pObject->item.asArray.value->uiClass; /* superclass handel casting */ - pCopy->item.asArray.value->uiClass = pMethod->uiSprClass; - - hb_itemRelease( hb_itemReturn( pCopy ) ); + pReturn->item.asArray.value->uiClass = pMethod->uiSprClass; } /* @@ -3027,25 +3402,24 @@ static HARBOUR hb___msgRealClass( void ) PHB_ITEM pObject = hb_stackSelfItem(); USHORT uiClass = hb_clsSenderMethodClasss(); - if( uiClass && - hb_clsSenderObjectClasss() == pObject->item.asArray.value->uiClass && - uiClass != pObject->item.asArray.value->uiClass ) + if( uiClass && uiClass != pObject->item.asArray.value->uiClass && + hb_clsSenderObjectClasss() == pObject->item.asArray.value->uiClass ) { - PHB_ITEM pCopy = hb_itemArrayNew(1); + PHB_ITEM pReturn = hb_stackReturnItem(); + /* create a fake object array */ + hb_arrayNew( pReturn, 1 ); /* Now save the Self object as the 1st elem. */ - hb_arraySet( pCopy, 1, pObject ); - + hb_arraySet( pReturn, 1, pObject ); /* And transform it into a fake object */ /* backup of actual handel */ - pCopy->item.asArray.value->uiPrevCls = pObject->item.asArray.value->uiClass; + pReturn->item.asArray.value->uiPrevCls = pObject->item.asArray.value->uiClass; /* superclass handel casting */ - pCopy->item.asArray.value->uiClass = uiClass; - hb_itemRelease( hb_itemReturn( pCopy ) ); + pReturn->item.asArray.value->uiClass = uiClass; } else { - hb_itemReturn( pObject ); + hb_itemReturnForward( pObject ); } } @@ -3057,7 +3431,7 @@ static HARBOUR hb___msgRealClass( void ) static HARBOUR hb___msgGetClsData( void ) { PCLASS pClass = &s_pClasses[ - hb_stackBaseItem()->item.asSymbol.stackstate->uiClass - 1 ]; + hb_stackBaseItem()->item.asSymbol.stackstate->uiClass ]; PMETHOD pMethod = pClass->pMethods + hb_stackBaseItem()->item.asSymbol.stackstate->uiMethod; @@ -3073,13 +3447,29 @@ static HARBOUR hb___msgGetClsData( void ) static HARBOUR hb___msgSetClsData( void ) { PCLASS pClass = &s_pClasses[ - hb_stackBaseItem()->item.asSymbol.stackstate->uiClass - 1 ]; + hb_stackBaseItem()->item.asSymbol.stackstate->uiClass ]; PMETHOD pMethod = pClass->pMethods + hb_stackBaseItem()->item.asSymbol.stackstate->uiMethod; PHB_ITEM pReturn = hb_stackItemFromBase( 1 ); + if( !pReturn ) + return; + else if( HB_IS_BYREF( pReturn ) ) + pReturn = hb_itemUnRef( pReturn ); + + if( pMethod->itemType && ! ( pMethod->itemType & pReturn->type ) ) + { + if( pMethod->itemType == HB_IT_NUMINT && HB_IS_NUMERIC( pReturn ) ) + hb_itemPutNInt( pReturn, hb_itemGetNInt( pReturn ) ); + else + { + (s___msgTypeErr.value.pFunPtr)(); + return; + } + } + hb_arraySet( pClass->pClassDatas, pMethod->uiData, pReturn ); - hb_itemReturn( pReturn ); + hb_itemReturnForward( pReturn ); } /* @@ -3090,11 +3480,11 @@ static HARBOUR hb___msgSetClsData( void ) static HARBOUR hb___msgGetShrData( void ) { PCLASS pClass = &s_pClasses[ - hb_stackBaseItem()->item.asSymbol.stackstate->uiClass - 1 ]; + hb_stackBaseItem()->item.asSymbol.stackstate->uiClass ]; PMETHOD pMethod = pClass->pMethods + hb_stackBaseItem()->item.asSymbol.stackstate->uiMethod; - hb_arrayGet( s_pClasses[ pMethod->uiSprClass - 1 ].pSharedDatas, + hb_arrayGet( s_pClasses[ pMethod->uiSprClass ].pSharedDatas, pMethod->uiData, hb_stackReturnItem() ); } @@ -3106,14 +3496,30 @@ static HARBOUR hb___msgGetShrData( void ) static HARBOUR hb___msgSetShrData( void ) { PCLASS pClass = &s_pClasses[ - hb_stackBaseItem()->item.asSymbol.stackstate->uiClass - 1 ]; + hb_stackBaseItem()->item.asSymbol.stackstate->uiClass ]; PMETHOD pMethod = pClass->pMethods + hb_stackBaseItem()->item.asSymbol.stackstate->uiMethod; PHB_ITEM pReturn = hb_stackItemFromBase( 1 ); - hb_arraySet( s_pClasses[ pMethod->uiSprClass - 1 ].pSharedDatas, + if( !pReturn ) + return; + else if( HB_IS_BYREF( pReturn ) ) + pReturn = hb_itemUnRef( pReturn ); + + if( pMethod->itemType && ! ( pMethod->itemType & pReturn->type ) ) + { + if( pMethod->itemType == HB_IT_NUMINT && HB_IS_NUMERIC( pReturn ) ) + hb_itemPutNInt( pReturn, hb_itemGetNInt( pReturn ) ); + else + { + (s___msgTypeErr.value.pFunPtr)(); + return; + } + } + + hb_arraySet( s_pClasses[ pMethod->uiSprClass ].pSharedDatas, pMethod->uiData, pReturn ); - hb_itemReturn( pReturn ); + hb_itemReturnForward( pReturn ); } /* @@ -3126,25 +3532,21 @@ static HARBOUR hb___msgGetData( void ) PHB_ITEM pObject = hb_stackSelfItem(); USHORT uiObjClass = pObject->item.asArray.value->uiClass; USHORT uiClass = hb_stackBaseItem()->item.asSymbol.stackstate->uiClass; - PCLASS pClass = &s_pClasses[ uiClass - 1 ]; + PCLASS pClass = &s_pClasses[ uiClass ]; PMETHOD pMethod = pClass->pMethods + hb_stackBaseItem()->item.asSymbol.stackstate->uiMethod; ULONG ulIndex = pMethod->uiData; if( uiClass != uiObjClass ) { - ulIndex += hb_clsParentInstanceOffset( &s_pClasses[ uiObjClass - 1 ], - s_pClasses[ pMethod->uiSprClass - 1 ].pClassSym ); + ulIndex += hb_clsParentInstanceOffset( &s_pClasses[ uiObjClass ], + s_pClasses[ pMethod->uiSprClass ].pClassSym ); } else { ulIndex += pMethod->uiOffset; } - /* will arise only if the class has been modified after first instance */ - if( ulIndex > hb_arrayLen( pObject ) ) /* Resize needed */ - hb_arraySize( pObject, ulIndex ); /* Make large enough */ - hb_arrayGet( pObject, ulIndex, hb_stackReturnItem() ); } @@ -3159,15 +3561,31 @@ static HARBOUR hb___msgSetData( void ) PHB_ITEM pObject = hb_stackSelfItem(); USHORT uiObjClass = pObject->item.asArray.value->uiClass; USHORT uiClass = hb_stackBaseItem()->item.asSymbol.stackstate->uiClass; - PCLASS pClass = &s_pClasses[ uiClass - 1 ]; + PCLASS pClass = &s_pClasses[ uiClass ]; PMETHOD pMethod = pClass->pMethods + hb_stackBaseItem()->item.asSymbol.stackstate->uiMethod; ULONG ulIndex = pMethod->uiData; + if( !pReturn ) + return; + else if( HB_IS_BYREF( pReturn ) ) + pReturn = hb_itemUnRef( pReturn ); + + if( pMethod->itemType && ! ( pMethod->itemType & pReturn->type ) ) + { + if( pMethod->itemType == HB_IT_NUMINT && HB_IS_NUMERIC( pReturn ) ) + hb_itemPutNInt( pReturn, hb_itemGetNInt( pReturn ) ); + else + { + (s___msgTypeErr.value.pFunPtr)(); + return; + } + } + if( uiClass != uiObjClass ) { - ulIndex += hb_clsParentInstanceOffset( &s_pClasses[ uiObjClass - 1 ], - s_pClasses[ pMethod->uiSprClass - 1 ].pClassSym ); + ulIndex += hb_clsParentInstanceOffset( &s_pClasses[ uiObjClass ], + s_pClasses[ pMethod->uiSprClass ].pClassSym ); } else { @@ -3177,10 +3595,8 @@ static HARBOUR hb___msgSetData( void ) /* will arise only if the class has been modified after first instance */ if( ulIndex > hb_arrayLen( pObject ) ) /* Resize needed ? */ hb_arraySize( pObject, ulIndex ); /* Make large enough */ - hb_arraySet( pObject, ulIndex, pReturn ); - - hb_itemReturn( pReturn ); + hb_itemReturnForward( pReturn ); } /* No comment :-) */ @@ -3196,56 +3612,11 @@ static HARBOUR hb___msgNull( void ) } -/* NOTE: Used by the preprocessor to implement Classy compatibility to Harbour - Receive an variable number of param and return an array of it. - No param will return a NULL array */ - - -HB_FUNC( __CLS_PARAM ) -{ - PHB_ITEM array; - USHORT uiParam = ( USHORT ) hb_pcount(); - USHORT n; - - if( uiParam >= 1 ) - { - array = hb_itemArrayNew( uiParam ); - for( n = 1; n <= uiParam; n++ ) - { - hb_arraySet( array, n, hb_param( n, HB_IT_ANY ) ); - } - } - else - { - array = hb_itemArrayNew( 1 ); - hb_itemPutC( hb_arrayGetItemPtr( array, 1 ), "HBObject" ); - } - - hb_itemRelease( hb_itemReturn( array ) ); -} - -/* This one is used when HB_NOTOBJECT is defined before HBCLASS.CH */ -/* it will avoid any default object to be inherited */ -HB_FUNC( __CLS_PAR00 ) -{ - PHB_ITEM array; - USHORT uiParam = ( USHORT ) hb_pcount(); - USHORT n; - - array = hb_itemArrayNew( uiParam ); - for( n = 1; n <= uiParam; n++ ) - { - hb_arraySet( array, n, hb_param( n, HB_IT_ANY ) ); - } - - hb_itemRelease( hb_itemReturn( array ) ); -} - #ifndef HB_NO_PROFILER void hb_mthAddTime( ULONG ulClockTicks ) { PMETHOD pMethod = - s_pClasses[ hb_stackSelfItem()->item.asArray.value->uiClass - 1 ]. + s_pClasses[ hb_stackSelfItem()->item.asArray.value->uiClass ]. pMethods + hb_stackBaseItem()->item.asSymbol.stackstate->uiMethod; pMethod->ulCalls++; @@ -3267,7 +3638,7 @@ HB_FUNC( __GETMSGPRF ) /* profiler: returns a method called and consumed times * if( pMsg ) { - PMETHOD pMethod = hb_clsFindMsg( &s_pClasses[ uiClass - 1 ], pMsg ); + PMETHOD pMethod = hb_clsFindMsg( &s_pClasses[ uiClass ], pMsg ); if( pMethod ) { @@ -3296,7 +3667,7 @@ HB_FUNC( __CLSGETPROPERTIES ) if( uiClass && uiClass <= s_uiClasses ) { - PCLASS pClass = &s_pClasses[ uiClass - 1 ]; + PCLASS pClass = &s_pClasses[ uiClass ]; PMETHOD pMethod = pClass->pMethods; ULONG ulLimit = hb_clsMthNum( pClass ); PHB_ITEM pItem = NULL; @@ -3318,7 +3689,7 @@ HB_FUNC( __CLSGETPROPERTIES ) hb_itemRelease( pItem ); } - hb_itemRelease( hb_itemReturn( pReturn ) ); + hb_itemRelease( hb_itemReturnForward( pReturn ) ); } /* Real dirty function, though very usefull under certain circunstances: @@ -3333,8 +3704,11 @@ HB_FUNC( HB_SETCLSHANDLE ) /* ( oObject, nClassHandle ) --> nPrevClassHandle */ if( pObject ) { + USHORT uiClass = ( USHORT ) hb_parni( 2 ); + uiPrevClassHandle = pObject->item.asArray.value->uiClass; - pObject->item.asArray.value->uiClass = ( USHORT ) hb_parni( 2 ); + if( uiClass <= s_uiClasses ) + pObject->item.asArray.value->uiClass = uiClass; } hb_retnl( uiPrevClassHandle ); @@ -3343,18 +3717,7 @@ HB_FUNC( HB_SETCLSHANDLE ) /* ( oObject, nClassHandle ) --> nPrevClassHandle */ /* Harbour equivalent for Clipper internal __mdCreate() */ USHORT hb_clsCreate( USHORT usSize, char * szClassName ) { - static PHB_DYNS pDynSym = NULL; - - if( pDynSym == NULL ) - pDynSym = hb_dynsymGet( "__CLSNEW" ); - - hb_vmPushDynSym( pDynSym ); - hb_vmPushNil(); - hb_vmPushString( szClassName, strlen( szClassName ) ); - hb_vmPushLong( usSize ); - hb_vmFunction( 2 ); - - return ( USHORT ) hb_parni( -1 ); + return hb_clsNew( szClassName, usSize, NULL, NULL, FALSE ); } /* Harbour equivalent for Clipper internal __mdAdd() */ @@ -3388,7 +3751,52 @@ void hb_clsAssociate( USHORT usClassH ) PHB_ITEM pSelf = hb_clsInst( usClassH ); if( pSelf ) - hb_itemRelease( hb_itemReturn( pSelf ) ); + hb_itemRelease( hb_itemReturnForward( pSelf ) ); +} + +/* NOTE: Used by the preprocessor to implement Classy compatibility to Harbour + Receive an variable number of param and return an array of it. + No param will return a NULL array */ + + +HB_FUNC( __CLS_PARAM ) +{ + PHB_ITEM array; + USHORT uiParam = ( USHORT ) hb_pcount(); + USHORT n; + + if( uiParam >= 1 ) + { + array = hb_itemArrayNew( uiParam ); + for( n = 1; n <= uiParam; n++ ) + { + hb_arraySet( array, n, hb_param( n, HB_IT_ANY ) ); + } + } + else + { + array = hb_itemArrayNew( 1 ); + hb_itemPutC( hb_arrayGetItemPtr( array, 1 ), "HBObject" ); + } + + hb_itemRelease( hb_itemReturnForward( array ) ); +} + +/* This one is used when HB_NOTOBJECT is defined before HBCLASS.CH */ +/* it will avoid any default object to be inherited */ +HB_FUNC( __CLS_PAR00 ) +{ + PHB_ITEM array; + USHORT uiParam = ( USHORT ) hb_pcount(); + USHORT n; + + array = hb_itemArrayNew( uiParam ); + for( n = 1; n <= uiParam; n++ ) + { + hb_arraySet( array, n, hb_param( n, HB_IT_ANY ) ); + } + + hb_itemRelease( hb_itemReturnForward( array ) ); } /* diff --git a/harbour/source/vm/debug.c b/harbour/source/vm/debug.c index e2345759c8..ca0179e522 100644 --- a/harbour/source/vm/debug.c +++ b/harbour/source/vm/debug.c @@ -63,7 +63,7 @@ static void AddToArray( PHB_ITEM pItem, PHB_ITEM pReturn, ULONG ulPos ) { HB_TRACE(HB_TR_DEBUG, ("AddToArray(%p, %p, %lu)", pItem, pReturn, ulPos)); - if( pItem->type == HB_IT_SYMBOL ) + if( HB_IS_SYMBOL( pItem ) ) { /* Symbol is pushed as text */ PHB_ITEM pArrayItem = hb_arrayGetItemPtr( pReturn, ulPos ); diff --git a/harbour/source/vm/hvm.c b/harbour/source/vm/hvm.c index 7774ca94af..11193a970e 100644 --- a/harbour/source/vm/hvm.c +++ b/harbour/source/vm/hvm.c @@ -228,7 +228,7 @@ BOOL hb_bTracePrgCalls = FALSE; /* prg tracing is off */ /* virtual machine state */ -HB_SYMB hb_symEval = { "__EVAL", {HB_FS_PUBLIC}, {hb_vmDoBlock}, NULL }; /* symbol to evaluate codeblocks */ +HB_SYMB hb_symEval = { "EVAL", {HB_FS_PUBLIC}, {hb_vmDoBlock}, NULL }; /* symbol to evaluate codeblocks */ static HB_ITEM s_aStatics; /* Harbour array to hold all application statics variables */ @@ -398,18 +398,20 @@ HB_EXPORT void hb_vmInit( BOOL bStartMainProc ) s_lRecoverBase = 0; s_uiActionRequest = 0; + hb_vmSymbolInit_RT(); /* initialize symbol table with runtime support functions */ + s_pDynsDbgEntry = hb_dynsymFind( "__DBGENTRY" ); hb_xinit(); hb_stackInit(); hb_errInit(); - hb_dynsymNew( &hb_symEval ); /* initialize dynamic symbol for evaluating codeblocks */ + /* initialize dynamic symbol for evaluating codeblocks */ + hb_symEval.pDynSym = hb_dynsymGetCase( hb_symEval.szName ); hb_setInitialize(); /* initialize Sets */ hb_conInit(); /* initialize Console */ hb_memvarsInit(); - hb_vmSymbolInit_RT(); /* initialize symbol table with runtime support functions */ hb_clsInit(); /* initialize Classy/OO system */ /* Set the language to the default */ @@ -4326,7 +4328,7 @@ HB_EXPORT PHB_ITEM hb_vmEvalBlockOrMacro( PHB_ITEM pItem ) { HB_TRACE(HB_TR_DEBUG, ("hb_vmEvalBlockOrMacro(%p)", pItem)); - if( pItem->type == HB_IT_BLOCK ) + if( HB_IS_BLOCK( pItem ) ) { hb_vmPushSymbol( &hb_symEval ); hb_vmPush( pItem ); @@ -4353,7 +4355,7 @@ HB_EXPORT PHB_ITEM hb_vmEvalBlockOrMacro( PHB_ITEM pItem ) */ HB_EXPORT void hb_vmDestroyBlockOrMacro( PHB_ITEM pItem ) { - if( pItem->type == HB_IT_POINTER ) + if( HB_IS_POINTER( pItem ) ) { HB_MACRO_PTR pMacro = ( HB_MACRO_PTR ) hb_itemGetPtr( pItem ); if( pMacro ) @@ -4820,6 +4822,17 @@ HB_EXPORT void hb_vmPushDynSym( PHB_DYNS pDynSym ) pItem->item.asSymbol.stackstate = NULL; } +HB_EXPORT void hb_vmPushEvalSym( void ) +{ + PHB_ITEM pItem = hb_stackAllocItem(); + + HB_TRACE(HB_TR_DEBUG, ("hb_vmPushEvalSym()")); + + pItem->type = HB_IT_SYMBOL; + pItem->item.asSymbol.value = &hb_symEval; + pItem->item.asSymbol.stackstate = NULL; +} + /* -3 -> HB_P_PUSHBLOCK * -2 -1 -> size of codeblock * 0 +1 -> number of expected parameters @@ -5715,8 +5728,9 @@ void hb_vmExitSymbolGroup( void * hDynLib ) } } -PHB_SYMBOLS -hb_vmRegisterSymbols( PHB_SYMB pModuleSymbols, USHORT uiSymbols, char * szModuleName, ULONG ulID, BOOL fDynLib, BOOL fClone ) +PHB_SYMBOLS hb_vmRegisterSymbols( PHB_SYMB pModuleSymbols, USHORT uiSymbols, + char * szModuleName, ULONG ulID, + BOOL fDynLib, BOOL fClone ) { PHB_SYMBOLS pNewSymbols; BOOL fRecycled, fInitStatics = FALSE; @@ -5800,7 +5814,8 @@ hb_vmRegisterSymbols( PHB_SYMB pModuleSymbols, USHORT uiSymbols, char * szModule fInitStatics = TRUE; } - if( ( hSymScope & HB_FS_PCODEFUNC ) != 0 && ( fRecycled || fClone ) ) + if( ( hSymScope & HB_FS_PCODEFUNC ) && ( hSymScope & HB_FS_LOCAL ) && + ( fRecycled || fClone ) ) { pSymbol->value.pCodeFunc->pSymbols = pNewSymbols->pModuleSymbols; } diff --git a/harbour/source/vm/proc.c b/harbour/source/vm/proc.c index 3790953c35..cebb1f3f9b 100644 --- a/harbour/source/vm/proc.c +++ b/harbour/source/vm/proc.c @@ -59,7 +59,7 @@ * * Copyright 2001 JFL (Mafact) * Adding the MethodName() just calling Procname() - * Special treatment in case of Object and __Eval (only for methodname) + * Special treatment in case of Object and Eval (only for methodname) * skipping block and adding (b) before the method name * * See doc/license.txt for licensing terms. @@ -122,7 +122,7 @@ HB_FUNC( PROCFILE ) { pSym = hb_stackItem( lOffset )->item.asSymbol.value; - if( pSym == &hb_symEval || strcmp( pSym->szName, "EVAL" ) == 0 ) + if( pSym == &hb_symEval || pSym->pDynSym == hb_symEval.pDynSym ) { PHB_ITEM pSelf = hb_stackItem( lOffset + 1 ); @@ -144,6 +144,7 @@ char * hb_procname( int iLevel, char * szName, BOOL fMethodName ) { long lOffset = hb_stackBaseProcOffset( iLevel ); + szName[ 0 ] = '\0'; if( lOffset >= 0 ) { PHB_ITEM pBase, pSelf; @@ -167,9 +168,8 @@ char * hb_procname( int iLevel, char * szName, BOOL fMethodName ) } } - szName[ 0 ] = '\0'; if( pBase->item.asSymbol.value == &hb_symEval || - strcmp( pBase->item.asSymbol.value->szName, "EVAL" ) == 0 ) + pBase->item.asSymbol.value->pDynSym == hb_symEval.pDynSym ) { strcat( szName, "(b)" ); @@ -189,8 +189,6 @@ char * hb_procname( int iLevel, char * szName, BOOL fMethodName ) strcat( szName, pBase->item.asSymbol.value->szName ); } } - else - strcpy( szName, "" ); return szName; } @@ -217,7 +215,7 @@ BOOL hb_procinfo( int iLevel, char * szName, USHORT * puiLine, char * szFile ) if( szName ) { szName[ 0 ] = '\0'; - if( pSym == &hb_symEval || strcmp( pSym->szName, "EVAL" ) == 0 ) + if( pSym == &hb_symEval || pSym->pDynSym == hb_symEval.pDynSym ) { strcat( szName, "(b)" ); @@ -245,7 +243,7 @@ BOOL hb_procinfo( int iLevel, char * szName, USHORT * puiLine, char * szFile ) char * szModule; if( HB_IS_BLOCK( pSelf ) && - ( pSym == &hb_symEval || strcmp( pSym->szName, "EVAL" ) == 0 ) ) + ( pSym == &hb_symEval || pSym->pDynSym == hb_symEval.pDynSym ) ) pSym = pSelf->item.asBlock.value->pDefSymb; szModule = hb_vmFindModuleSymbolName( hb_vmGetRealFuncSym( pSym ) );