2006-09-16 23:20 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
* harbour/contrib/rdd_ads/ads1.c
* synced with recent Brian fixes in xHarbour
* harbour/include/hbapi.h
+ added 'method' member to hb_struBlock structure
* harbour/source/vm/hvm.c
* initialize 'method' member in hb_struBlock structure
* harbour/source/vm/proc.c
* changed the name of last parameter of hb_procname() from
bSkipBlock to fMethodName and modified to use information
about the class of executed codeblock from new hb_struBlock
members
* harbour/source/vm/classes.c
* removed hb_objGetpMethod() - I hope it's not longer used
* added real codeblock scoping.
In Clipper there is no information where the codeblock where
created and what priviladges/scopes it should has.
Class(y) to resovle this problem when codeblock is executed scans
the HVM stack for the nearest method call and takes scopes defined
for this method. It's a workaround which allow to break standard
access rights though seems reasonable when it's not possible to
store information where the block is created. I've added to block
item structure information about class and method where code block
was created so we can use the exact method priviladges.
Now Harbour classy code can work exactly like Class(y) when compiled
with -DHB_CLASSY_BLOCK_SCOPE and with real code block scoping when
compiled with -DHB_REAL_BLOCK_SCOPE. I set the second (real code
block scopes) as default. If you think we should be strict Class(y)
compatible here then please inform me and I'll change default setting.
+ tests/clsscope.prg
+ added demonstration/test code for class method scoping
This commit is contained in:
@@ -8,6 +8,43 @@
|
||||
2002-12-01 13:30 UTC+0100 Foo Bar <foo.bar@foobar.org>
|
||||
*/
|
||||
|
||||
* harbour/source/vm/classes.c
|
||||
* temporary restored hb_objGetpMethod()
|
||||
+ added __ClsCntClasses()
|
||||
! allocated real methods for OnError and Destructor to keep
|
||||
the same behavior in these methods as in any others, f.e.
|
||||
scoping checking or debugging.
|
||||
|
||||
* harbour/common.mak
|
||||
* harbour/utils/hbtest/Makefile
|
||||
* harbour/utils/hbtest/hbtest.prg
|
||||
+ harbour/utils/hbtest/rt_class.prg
|
||||
+ added tests for our classy code. Now destructors and instance
|
||||
area allocating/casting. Some other in the future.
|
||||
|
||||
2006-09-16 23:20 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
|
||||
* harbour/contrib/rdd_ads/ads1.c
|
||||
* synced with recent Brian fixes in xHarbour
|
||||
|
||||
* harbour/include/hbapi.h
|
||||
+ added 'method' member to hb_struBlock structure
|
||||
|
||||
* harbour/source/vm/hvm.c
|
||||
* initialize 'method' member in hb_struBlock structure
|
||||
|
||||
* harbour/source/vm/proc.c
|
||||
* changed the name of last parameter of hb_procname() from
|
||||
bSkipBlock to fMethodName and modified to use information
|
||||
about the class of executed codeblock from new hb_struBlock
|
||||
members
|
||||
|
||||
* harbour/source/vm/classes.c
|
||||
* removed hb_objGetpMethod() - I hope it's not longer used
|
||||
* added real codeblock scoping.
|
||||
In Clipper there is no information where the codeblock where
|
||||
created and what priviladges/scopes it should has.
|
||||
Class(y) to resovle this problem when codeblock is executed scans
|
||||
the HVM stack for the nearest method call and takes scopes defined
|
||||
for this method. It's a workaround which allow to break standard
|
||||
access rights though seems reasonable when it's not possible to
|
||||
store information where the block is created. I've added to block
|
||||
|
||||
@@ -223,6 +223,36 @@ static void DumpArea( ADSAREAP pArea ) /* For debugging: call this to dump ads
|
||||
}
|
||||
#endif
|
||||
|
||||
static BOOL adsIndexKeyCmp( ADSHANDLE hIndex, UNSIGNED8 * pszKey, UNSIGNED16 u16KeyLen )
|
||||
{
|
||||
UNSIGNED32 u32RetVal;
|
||||
UNSIGNED16 u16Found = FALSE;
|
||||
UNSIGNED16 u16CurKeyLen = ADS_MAX_KEY_LENGTH;
|
||||
UNSIGNED8 pucCurKey[ADS_MAX_KEY_LENGTH + 1];
|
||||
|
||||
/*
|
||||
* test if current record has fields that match the given key expression.
|
||||
* This is used to evaluate if a seek expression continues to eval to .t.
|
||||
* when skipping through filtered records
|
||||
*/
|
||||
|
||||
u32RetVal = AdsExtractKey( hIndex, pucCurKey, &u16CurKeyLen );
|
||||
if( u32RetVal == AE_SUCCESS )
|
||||
{
|
||||
if( u16CurKeyLen )
|
||||
{
|
||||
if( u16CurKeyLen >= u16KeyLen &&
|
||||
memcmp( (UNSIGNED8*) pucCurKey, (UNSIGNED8*) pszKey, u16KeyLen ) == 0 )
|
||||
{
|
||||
u16Found = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return u16Found;
|
||||
}
|
||||
|
||||
|
||||
static int adsGetFileType( USHORT uiRddID )
|
||||
{
|
||||
return ( uiRddID == s_uiRddIdADSCDX ? ADS_CDX :
|
||||
@@ -838,6 +868,8 @@ static ERRCODE adsSeek( ADSAREAP pArea, BOOL bSoftSeek, PHB_ITEM pKey, BOOL bFin
|
||||
u16KeyType, u16Found, u16KeyLen;
|
||||
UNSIGNED8 *pszKey;
|
||||
double dValue;
|
||||
UNSIGNED8 *pucSavedKey = NULL;
|
||||
UNSIGNED16 u16SavedKeyLen = ADS_MAX_KEY_LENGTH; // this may be longer than the actual seek expression, so we don't pass it along
|
||||
|
||||
HB_TRACE(HB_TR_DEBUG, ("adsSeek(%p, %d, %p, %d)", pArea, bSoftSeek, pKey, bFindLast));
|
||||
|
||||
@@ -938,27 +970,73 @@ static ERRCODE adsSeek( ADSAREAP pArea, BOOL bSoftSeek, PHB_ITEM pKey, BOOL bFin
|
||||
if( pArea->lpdbRelations )
|
||||
SELF_SYNCCHILDREN( ( AREAP ) pArea );
|
||||
|
||||
/* -----------------5/1/2002 3:04AM BH ------------------
|
||||
/* ----------------- BH ------------------
|
||||
If a filter is set that is not valid for ADS, we need to skip
|
||||
off of any invalid records (IOW, filter at the Harbour level if ADS can't
|
||||
because the filter has UDFs or PUBLICVAR references).
|
||||
We could avoid calling this if we had a static set to know if the current
|
||||
filter is not valid for ADS.
|
||||
To make sure the skipped-to record still matches the seeked key, we need to
|
||||
be able to construct a comparable key for the subsequent record.
|
||||
This is annoyingly complex with the various ads key types for various table types.
|
||||
AdsExtractKey would seem to be the api of choice, but here on the starting end the
|
||||
key we seek on does NOT match the format of what we get back from AdsExtractKey.
|
||||
So I'm saving off the first found record's key, and passing that to our
|
||||
adsIndexKeyCmp() to compare to the new record's key.
|
||||
We're relying on testing to verify that partial key searches and binary
|
||||
raw keys all end up working right.
|
||||
--------------------------------------------------*/
|
||||
if( pArea->dbfi.itmCobExpr && !pArea->dbfi.fOptimized && !pArea->fEof )
|
||||
{
|
||||
/* remember FOUND flag for updating after SKIPFILTER() */
|
||||
/* Remember FOUND flag for updating after SKIPFILTER() */
|
||||
u16Found = pArea->fFound;
|
||||
|
||||
if( u16Found )
|
||||
if( u16Found && u16KeyLen > 0 )
|
||||
{
|
||||
/* remember the record number for faster checking if we should update
|
||||
fFound after SKIPFILTER */
|
||||
/*
|
||||
* remember the record number for faster checking if we should update
|
||||
* fFound after SKIPFILTER. Also get its extracted key to simplify
|
||||
* that comparison
|
||||
*/
|
||||
UNSIGNED32 u32RetVal;
|
||||
pucSavedKey = (UNSIGNED8*) hb_xgrab( ADS_MAX_KEY_LENGTH + 1 );
|
||||
|
||||
AdsGetRecordNum( pArea->hTable, ADS_IGNOREFILTERS, &u32RecNo );
|
||||
u32RetVal = AdsExtractKey( pArea->hOrdCurrent, pucSavedKey, &u16SavedKeyLen );
|
||||
|
||||
if( u32RetVal != AE_SUCCESS )
|
||||
{
|
||||
u16SavedKeyLen = 0;
|
||||
}
|
||||
else if( u16SavedKeyLen > u16KeyLen )
|
||||
{
|
||||
/* Initial found key from index is longer than Seek key:
|
||||
Did a partial search */
|
||||
if( AdsGetKeyType( pArea->hOrdCurrent, &u16KeyType ) == AE_SUCCESS &&
|
||||
( u16KeyType == ADS_STRING || u16KeyType == ADS_RAW ) )
|
||||
{
|
||||
/*
|
||||
* do partial comparison below on String and Raw indexes only.
|
||||
* Note that we can search a different type index with a string
|
||||
* expression, but ads does internal conversions and the length
|
||||
* of our string may be drastically different than the real key
|
||||
*/
|
||||
u16SavedKeyLen = u16KeyLen;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: Possible optimization: if !softseek, skipfilter should abort
|
||||
* skipping once keys no longer match.
|
||||
* Perhaps use temp replacement of scope for this -- but remember ads
|
||||
* does scopes on client and if last good scoped record fails the filter,
|
||||
* the server will skip to the end anyway
|
||||
*/
|
||||
if( SELF_SKIPFILTER( ( AREAP ) pArea, bFindLast ? -1 : 1 ) != SUCCESS )
|
||||
{
|
||||
if ( pucSavedKey )
|
||||
{
|
||||
hb_xfree( pucSavedKey );
|
||||
}
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
@@ -968,14 +1046,21 @@ static ERRCODE adsSeek( ADSAREAP pArea, BOOL bSoftSeek, PHB_ITEM pKey, BOOL bFin
|
||||
{
|
||||
u16Found = FALSE;
|
||||
}
|
||||
else
|
||||
/* seek empty string is synonymous with GoTop */
|
||||
else if( u16KeyLen > 0 )
|
||||
{
|
||||
AdsGetRecordNum( pArea->hTable, ADS_IGNOREFILTERS, &u32NewRec );
|
||||
/* SkipFilter moved us? see if index key is still a match. */
|
||||
if( u32RecNo != u32NewRec )
|
||||
{
|
||||
/* TODO: we should check here if FOUND is still TRUE by
|
||||
comparing curent index key expression - now dirty hack */
|
||||
u16Found = FALSE;
|
||||
if( u16SavedKeyLen == 0 )
|
||||
{
|
||||
u16Found = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
u16Found = adsIndexKeyCmp( pArea->hOrdCurrent, pucSavedKey, u16SavedKeyLen );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -989,6 +1074,11 @@ static ERRCODE adsSeek( ADSAREAP pArea, BOOL bSoftSeek, PHB_ITEM pKey, BOOL bFin
|
||||
*/
|
||||
pArea->fBof = FALSE;
|
||||
|
||||
if ( pucSavedKey )
|
||||
{
|
||||
hb_xfree( pucSavedKey );
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@@ -2720,10 +2810,8 @@ static ERRCODE adsOpen( ADSAREAP pArea, LPDBOPENINFO pOpenInfo )
|
||||
pArea->fShared = pOpenInfo->fShared;
|
||||
pArea->fReadonly = pOpenInfo->fReadonly;
|
||||
|
||||
//TraceLog( NULL, "Before count: %i \n", uiFields );
|
||||
SELF_FIELDCOUNT( ( AREAP ) pArea, &uiFields );
|
||||
|
||||
//TraceLog( NULL, "Before extent\n" );
|
||||
SELF_SETFIELDEXTENT( ( AREAP ) pArea, uiFields );
|
||||
|
||||
pArea->maxFieldLen = 0;
|
||||
@@ -2734,8 +2822,6 @@ static ERRCODE adsOpen( ADSAREAP pArea, LPDBOPENINFO pOpenInfo )
|
||||
AdsGetFieldName( pArea->hTable, uiCount, szName, &pusBufLen );
|
||||
dbFieldInfo.atomName = szName;
|
||||
|
||||
//TraceLog( NULL, "Field: '%s'\n", szName );
|
||||
|
||||
* ( dbFieldInfo.atomName + pusBufLen ) = '\0';
|
||||
AdsGetFieldType( pArea->hTable, szName, &pusType );
|
||||
AdsGetFieldLength( pArea->hTable, szName, &u32Length );
|
||||
|
||||
@@ -246,6 +246,7 @@ struct hb_struBlock
|
||||
USHORT lineno;
|
||||
USHORT paramcnt;
|
||||
USHORT hclass;
|
||||
USHORT method;
|
||||
};
|
||||
|
||||
struct hb_struDate
|
||||
|
||||
@@ -203,6 +203,16 @@ typedef struct
|
||||
#define HASH_KEYMAX ( 1 << ( 16 - BUCKETBITS ) )
|
||||
#define hb_clsMthNum(p) ( ( ( ULONG ) (p)->uiHashKey + 1 ) << BUCKETBITS )
|
||||
|
||||
#if defined( HB_REAL_BLOCK_SCOPE )
|
||||
# undef HB_CLASSY_BLOCK_SCOPE
|
||||
#elif !defined( HB_CLASSY_BLOCK_SCOPE )
|
||||
# define HB_REAL_BLOCK_SCOPE
|
||||
#endif
|
||||
|
||||
#if defined( HB_REAL_BLOCK_SCOPE )
|
||||
# define hb_clsSenderOffset() hb_stackBaseProcOffset( 1 )
|
||||
#endif
|
||||
|
||||
static HARBOUR hb___msgGetData( void );
|
||||
static HARBOUR hb___msgSetData( void );
|
||||
static HARBOUR hb___msgGetClsData( void );
|
||||
@@ -298,10 +308,6 @@ static HB_SYMB s___msgWithObjectPop = { "___WITHOBJECT", {HB_FS_MESSAGE}, {hb__
|
||||
static PCLASS s_pClasses = NULL;
|
||||
static USHORT s_uiClasses = 0;
|
||||
|
||||
#ifdef HB_CLS_ENFORCERO
|
||||
static PMETHOD hb_objGetpMethod( PHB_ITEM, PHB_SYMB );
|
||||
#endif
|
||||
|
||||
/* ================================================ */
|
||||
|
||||
static USHORT hb_clsMsgBucket( PHB_DYNS pMsg, USHORT uiMask )
|
||||
@@ -406,27 +412,6 @@ static void hb_clsDictInit( PCLASS pClass, USHORT uiHashKey )
|
||||
memset( pClass->pMethods, 0, ulSize );
|
||||
}
|
||||
|
||||
static PMETHOD hb_clsFindMsg( PCLASS pClass, PHB_DYNS pMsg )
|
||||
{
|
||||
PMETHOD pMethod;
|
||||
USHORT uiBucket;
|
||||
|
||||
HB_TRACE(HB_TR_DEBUG, ("hb_clsFindMsg(%p,%p)", pClass, pMsg));
|
||||
|
||||
pMethod = pClass->pMethods + hb_clsMsgBucket( pMsg, pClass->uiHashKey );
|
||||
uiBucket = BUCKETSIZE;
|
||||
|
||||
do
|
||||
{
|
||||
if( pMethod->pMessage == pMsg )
|
||||
return pMethod;
|
||||
++pMethod;
|
||||
}
|
||||
while( --uiBucket );
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void hb_clsCopyClass( PCLASS pClsDst, PCLASS pClsSrc )
|
||||
{
|
||||
PMETHOD pMethod;
|
||||
@@ -479,6 +464,27 @@ static void hb_clsCopyClass( PCLASS pClsDst, PCLASS pClsSrc )
|
||||
while( --ulLimit );
|
||||
}
|
||||
|
||||
static PMETHOD hb_clsFindMsg( PCLASS pClass, PHB_DYNS pMsg )
|
||||
{
|
||||
PMETHOD pMethod;
|
||||
USHORT uiBucket;
|
||||
|
||||
HB_TRACE(HB_TR_DEBUG, ("hb_clsFindMsg(%p,%p)", pClass, pMsg));
|
||||
|
||||
pMethod = pClass->pMethods + hb_clsMsgBucket( pMsg, pClass->uiHashKey );
|
||||
uiBucket = BUCKETSIZE;
|
||||
|
||||
do
|
||||
{
|
||||
if( pMethod->pMessage == pMsg )
|
||||
return pMethod;
|
||||
++pMethod;
|
||||
}
|
||||
while( --uiBucket );
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static PMETHOD hb_clsAllocMsg( PCLASS pClass, PHB_DYNS pMsg )
|
||||
{
|
||||
HB_TRACE(HB_TR_DEBUG, ("hb_clsAllocMsg(%p,%p)", pClass, pMsg));
|
||||
@@ -889,6 +895,7 @@ HB_EXPORT char * hb_objGetRealClsName( PHB_ITEM pObject, char * szName )
|
||||
return hb_objGetClsName( pObject );
|
||||
}
|
||||
|
||||
#if !defined( HB_REAL_BLOCK_SCOPE )
|
||||
static LONG hb_clsSenderOffset( void )
|
||||
{
|
||||
LONG lOffset = hb_stackBaseProcOffset( 1 );
|
||||
@@ -912,8 +919,9 @@ static LONG hb_clsSenderOffset( void )
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined( HB_CASTED_PROTECT_SCOPE )
|
||||
#if 0
|
||||
static USHORT hb_clsSenderClasss( void )
|
||||
{
|
||||
LONG lOffset = hb_clsSenderOffset();
|
||||
@@ -948,7 +956,7 @@ static USHORT hb_clsSenderObjectClasss( void )
|
||||
{
|
||||
PHB_ITEM pSender = hb_stackItem( lOffset + 1 );
|
||||
|
||||
if( pSender->type == HB_IT_ARRAY )
|
||||
if( HB_IS_ARRAY( pSender ) )
|
||||
return pSender->item.asArray.value->uiClass;
|
||||
}
|
||||
return 0;
|
||||
@@ -1344,43 +1352,6 @@ HB_EXPORT void hb_objSendMsg( PHB_ITEM pObject, char *sMsg, ULONG ulArg, ... )
|
||||
hb_vmSend( (USHORT) ulArg );
|
||||
}
|
||||
|
||||
#ifndef HB_CLS_ENFORCERO
|
||||
/*
|
||||
* This function is only for backward binary compatibility
|
||||
* It will be removed in the future so please do not use it.
|
||||
* Use hb_objHasMessage() instead.
|
||||
*/
|
||||
#if defined(__cplusplus)
|
||||
extern "C" BOOL hb_objGetpMethod( PHB_ITEM pObject, PHB_SYMB pMessage );
|
||||
#endif
|
||||
BOOL hb_objGetpMethod( PHB_ITEM pObject, PHB_SYMB pMessage )
|
||||
{
|
||||
return hb_objGetMethod( pObject, pMessage, NULL ) != NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HB_CLS_ENFORCERO
|
||||
static PMETHOD hb_objGetpMethod( PHB_ITEM pObject, PHB_SYMB pMessage )
|
||||
{
|
||||
USHORT uiClass;
|
||||
PHB_DYNS pMsg = pMessage->pDynSym;
|
||||
|
||||
HB_TRACE(HB_TR_DEBUG, ("hb_objGetpMethod(%p, %p)", pObject, pMessage));
|
||||
|
||||
if( pObject->type == HB_IT_ARRAY )
|
||||
{
|
||||
USHORT uiClass = pObject->item.asArray.value->uiClass;
|
||||
|
||||
if( uiClass && uiClass <= s_uiClasses )
|
||||
{
|
||||
return hb_clsFindMsg( s_pClasses + ( uiClass - 1 ), pMsg );
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static PHB_SYMB hb_objFuncParam( int iParam )
|
||||
{
|
||||
PHB_ITEM pItem = hb_param( iParam, HB_IT_SYMBOL | HB_IT_STRING );
|
||||
@@ -1427,11 +1398,12 @@ static PHB_DYNS hb_objMsgParam( int iParam )
|
||||
}
|
||||
|
||||
static void hb_clsSetInlineClass( PCLASS pClass, USHORT uiIndex,
|
||||
USHORT uiClass )
|
||||
USHORT uiClass, USHORT uiMethod )
|
||||
{
|
||||
PHB_ITEM pBlock = hb_arrayGetItemPtr( pClass->pInlines, uiIndex );
|
||||
|
||||
pBlock->item.asBlock.hclass = uiClass;
|
||||
pBlock->item.asBlock.method = uiMethod;
|
||||
}
|
||||
|
||||
static USHORT hb_clsUpdateScope( USHORT uiScope, BOOL fAssign )
|
||||
@@ -1765,7 +1737,8 @@ HB_FUNC( __CLSADDMSG )
|
||||
pNewMeth->uiData = ( USHORT ) ( hb_arrayLen( pClass->pInlines ) + 1 );
|
||||
hb_arraySize( pClass->pInlines, pNewMeth->uiData );
|
||||
hb_arraySet( pClass->pInlines, pNewMeth->uiData, pBlock );
|
||||
hb_clsSetInlineClass( pClass, pNewMeth->uiData, uiClass );
|
||||
hb_clsSetInlineClass( pClass, pNewMeth->uiData, uiClass,
|
||||
( USHORT ) ( pNewMeth - pClass->pMethods ) );
|
||||
break;
|
||||
|
||||
case HB_OO_MSG_VIRTUAL:
|
||||
@@ -2174,7 +2147,8 @@ HB_FUNC( __CLSMODMSG )
|
||||
else
|
||||
{
|
||||
hb_arraySet( pClass->pInlines, pMethod->uiData, pBlock );
|
||||
hb_clsSetInlineClass( pClass, pMethod->uiData, uiClass );
|
||||
hb_clsSetInlineClass( pClass, pMethod->uiData, uiClass,
|
||||
( USHORT ) ( pMethod - pClass->pMethods ) );
|
||||
}
|
||||
}
|
||||
else /* Modify METHOD */
|
||||
|
||||
@@ -4155,6 +4155,8 @@ static HARBOUR hb_vmDoBlock( void )
|
||||
*/
|
||||
uiLine = hb_stackBaseItem()->item.asSymbol.lineno;
|
||||
hb_stackBaseItem()->item.asSymbol.lineno = pBlock->item.asBlock.lineno;
|
||||
hb_stackBaseItem()->item.asSymbol.stackstate->uiClass = pBlock->item.asBlock.hclass;
|
||||
hb_stackBaseItem()->item.asSymbol.stackstate->uiMethod = pBlock->item.asBlock.method;
|
||||
|
||||
hb_codeblockEvaluate( pBlock );
|
||||
|
||||
@@ -4704,6 +4706,7 @@ static void hb_vmPushBlock( const BYTE * pCode, PHB_SYMB pSymbols, USHORT usLen
|
||||
*/
|
||||
pItem->item.asBlock.lineno = hb_stackBaseItem()->item.asSymbol.lineno;
|
||||
pItem->item.asBlock.hclass = hb_stackBaseItem()->item.asSymbol.stackstate->uiClass;
|
||||
pItem->item.asBlock.method = hb_stackBaseItem()->item.asSymbol.stackstate->uiMethod;
|
||||
}
|
||||
|
||||
/* -2 -> HB_P_PUSHBLOCKSHORT
|
||||
@@ -4734,6 +4737,7 @@ static void hb_vmPushBlockShort( const BYTE * pCode, PHB_SYMB pSymbols, USHORT u
|
||||
*/
|
||||
pItem->item.asBlock.lineno = hb_stackBaseItem()->item.asSymbol.lineno;
|
||||
pItem->item.asBlock.hclass = hb_stackBaseItem()->item.asSymbol.stackstate->uiClass;
|
||||
pItem->item.asBlock.method = hb_stackBaseItem()->item.asSymbol.stackstate->uiMethod;
|
||||
}
|
||||
|
||||
/* +0 -> HB_P_MPUSHBLOCK
|
||||
@@ -4762,6 +4766,7 @@ static void hb_vmPushMacroBlock( BYTE * pCode, PHB_SYMB pSymbols )
|
||||
*/
|
||||
pItem->item.asBlock.lineno = hb_stackBaseItem()->item.asSymbol.lineno;
|
||||
pItem->item.asBlock.hclass = hb_stackBaseItem()->item.asSymbol.stackstate->uiClass;
|
||||
pItem->item.asBlock.method = hb_stackBaseItem()->item.asSymbol.stackstate->uiMethod;
|
||||
}
|
||||
|
||||
/* pushes current workarea number on the eval stack
|
||||
|
||||
@@ -150,58 +150,53 @@ HB_FUNC( PROCFILE )
|
||||
/* NOTE: szName size must be an at least:
|
||||
HB_SYMBOL_NAME_LEN + HB_SYMBOL_NAME_LEN + 5 [vszakats] */
|
||||
|
||||
char * hb_procname( int iLevel, char * szName, BOOL bSkipBlock )
|
||||
char * hb_procname( int iLevel, char * szName, BOOL fMethodName )
|
||||
{
|
||||
long lOffset = hb_stackBaseProcOffset( iLevel );
|
||||
long lPrevOffset = 0;
|
||||
|
||||
if( lOffset >= 0 )
|
||||
{
|
||||
PHB_ITEM pBase, pSelf;
|
||||
|
||||
if( bSkipBlock && lOffset > 0 &&
|
||||
hb_stackItem( lOffset )->item.asSymbol.value == &hb_symEval )
|
||||
{
|
||||
/* it's an inline method - back one more ... */
|
||||
lPrevOffset = lOffset;
|
||||
lOffset = hb_stackItem( lOffset )->item.asSymbol.stackstate->lBaseItem;
|
||||
}
|
||||
|
||||
pBase = hb_stackItem( lOffset );
|
||||
pSelf = hb_stackItem( lOffset + 1 );
|
||||
|
||||
if( pBase->item.asSymbol.stackstate->uiClass ) /* it is a method name */
|
||||
if( fMethodName && lOffset > 0 &&
|
||||
pBase->item.asSymbol.value == &hb_symEval &&
|
||||
pBase->item.asSymbol.stackstate->uiClass )
|
||||
{
|
||||
strcpy( szName, hb_clsName( pBase->item.asSymbol.stackstate->uiClass ) );
|
||||
long lPrevOffset = hb_stackItem( lOffset )->item.asSymbol.stackstate->lBaseItem;
|
||||
|
||||
if( lPrevOffset )
|
||||
strcat( szName, ":(b)" );
|
||||
if( hb_stackItem( lPrevOffset )->item.asSymbol.stackstate->uiClass ==
|
||||
pBase->item.asSymbol.stackstate->uiClass &&
|
||||
hb_stackItem( lPrevOffset )->item.asSymbol.stackstate->uiMethod ==
|
||||
pBase->item.asSymbol.stackstate->uiMethod )
|
||||
{
|
||||
pBase = hb_stackItem( lPrevOffset );
|
||||
pSelf = hb_stackItem( lPrevOffset + 1 );
|
||||
}
|
||||
}
|
||||
|
||||
szName[ 0 ] = '\0';
|
||||
if( pBase->item.asSymbol.value == &hb_symEval ||
|
||||
strcmp( pBase->item.asSymbol.value->szName, "EVAL" ) == 0 )
|
||||
{
|
||||
strcat( szName, "(b)" );
|
||||
|
||||
if( HB_IS_BLOCK( pSelf ) )
|
||||
strcat( szName, pSelf->item.asBlock.value->pDefSymb->szName );
|
||||
else
|
||||
strcat( szName, ":" );
|
||||
|
||||
strcat( szName, pBase->item.asSymbol.value->szName );
|
||||
strcat( szName, pBase->item.asSymbol.value->szName );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( lPrevOffset ) /* Back to standart code block */
|
||||
/* it is a method name? */
|
||||
if( pBase->item.asSymbol.stackstate->uiClass )
|
||||
{
|
||||
lOffset = lPrevOffset;
|
||||
pBase = hb_stackItem( lOffset );
|
||||
pSelf = hb_stackItem( lOffset + 1 );
|
||||
strcat( szName, hb_clsName( pBase->item.asSymbol.stackstate->uiClass ) );
|
||||
strcat( szName, ":" );
|
||||
}
|
||||
|
||||
if( pBase->item.asSymbol.value == &hb_symEval ||
|
||||
strcmp( pBase->item.asSymbol.value->szName, "EVAL" ) == 0 )
|
||||
{
|
||||
strcpy( szName, "(b)" );
|
||||
|
||||
if( HB_IS_BLOCK( pSelf ) )
|
||||
strcat( szName, pSelf->item.asBlock.value->pDefSymb->szName );
|
||||
else
|
||||
strcat( szName, pBase->item.asSymbol.value->szName );
|
||||
}
|
||||
else
|
||||
strcpy( szName, pBase->item.asSymbol.value->szName );
|
||||
strcat( szName, pBase->item.asSymbol.value->szName );
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -231,15 +226,10 @@ BOOL hb_procinfo( int iLevel, char * szName, USHORT * puiLine, char * szFile )
|
||||
|
||||
if( szName )
|
||||
{
|
||||
if( pBase->item.asSymbol.stackstate->uiClass ) /* it is a method name */
|
||||
szName[ 0 ] = '\0';
|
||||
if( pSym == &hb_symEval || strcmp( pSym->szName, "EVAL" ) == 0 )
|
||||
{
|
||||
strcpy( szName, hb_clsName( pBase->item.asSymbol.stackstate->uiClass ) );
|
||||
strcat( szName, ":" );
|
||||
strcat( szName, pSym->szName );
|
||||
}
|
||||
else if( pSym == &hb_symEval || strcmp( pSym->szName, "EVAL" ) == 0 )
|
||||
{
|
||||
strcpy( szName, "(b)" );
|
||||
strcat( szName, "(b)" );
|
||||
|
||||
if( HB_IS_BLOCK( pSelf ) )
|
||||
strcat( szName, pSelf->item.asBlock.value->pDefSymb->szName );
|
||||
@@ -247,7 +237,14 @@ BOOL hb_procinfo( int iLevel, char * szName, USHORT * puiLine, char * szFile )
|
||||
strcat( szName, pSym->szName );
|
||||
}
|
||||
else
|
||||
strcpy( szName, pSym->szName );
|
||||
{
|
||||
if( pBase->item.asSymbol.stackstate->uiClass ) /* it is a method name */
|
||||
{
|
||||
strcat( szName, hb_clsName( pBase->item.asSymbol.stackstate->uiClass ) );
|
||||
strcat( szName, ":" );
|
||||
}
|
||||
strcat( szName, pSym->szName );
|
||||
}
|
||||
}
|
||||
|
||||
if( puiLine )
|
||||
|
||||
1021
harbour/tests/clsscope.prg
Normal file
1021
harbour/tests/clsscope.prg
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user