2006-10-07 04:25 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl)

* harbour/include/hbclass.ch
    + added validation for class data names. As additional preprocessor
      rule to not use <!marker!>

  * harbour/include/hboo.ch
  * harbour/source/rtl/tclass.prg
  * harbour/source/vm/classes.c
    + added delegate messages

  * harbour/include/hbstack.h
  * harbour/source/vm/arrays.c
  * harbour/source/vm/estack.c
  * harbour/source/vm/hvm.c
  * harbour/source/vm/proc.c
    + added startup symbol to hb_stack. It gives very good stop
      condition for all procedures which trace stack calls and
      resolves the problem with hb_stack.pBase which was never
      pointing to valid function/procedure symbol when no symbol
      was put on HVM stack. Now after hb_stackInit() the first
      item is allocated for "hb_stackInit()" symbol so hb_stack.pBase
      is always a pointer to valid function/procedure symbol.
    * changed the guard condition for buggy code in hb_stackPop()
      and similar code from:
         hb_stack.pPos < hb_stack.pItems
      to:
         hb_stack.pPos <= hb_stack.pBase
      The old condition was generating usable error message only in the
      startup function. In deeply called functions it was only waste of
      CPU time on one of the most often call functions. Before it was
      activated internal stack structures were corrupted.
      If we were leaving for many years without really working stack
      underflow protection then maybe we should think about disabling
      it at when HB_STACK_MACROS are used and keep it only in real
      stack functions for HVM developers. Single protection in
      hb_stackOldFrame() I've just added is enough for basic C code
      validation.
      I created the second version of stack macros without it in
      hbstack.h but I would like to hear other developers opinion.
This commit is contained in:
Przemyslaw Czerpak
2006-10-07 02:35:52 +00:00
parent 57b1473404
commit 0fae2fdd2c
10 changed files with 243 additions and 93 deletions

View File

@@ -8,6 +8,46 @@
2002-12-01 13:30 UTC+0100 Foo Bar <foo.bar@foobar.org>
*/
2006-11-07 20:36 UTC+0200 JF Lefebvre (jflefebv at mafact com)
* harbour/include/hbclass.ch
* added one rule to support inline method with local var separated from <code> by a coma
2006-11-03 22:00 UTC+0100 Marek Paliwoda (mpaliwoda at interia pl)
* harbour/makefile.bc
* Updated comment section about environment variables used by makefile
* harbour/makefile.vc
* Updated comment section about environment variables used by makefile
* Cleaned compilation under Visual C++ 8.0 (VS2005 compiler), including
64 bit platforms. To properly compile under Visual C++ 8.0 you have
set a new environment variable HB_VISUALC_VER to 80 before running
make_vc.bat.
2006-10-07 04:25 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
* harbour/include/hbclass.ch
+ added validation for class data names. As additional preprocessor
rule to not use <!marker!>
* harbour/include/hboo.ch
* harbour/source/rtl/tclass.prg
* harbour/source/vm/classes.c
+ added delegate messages
* harbour/include/hbstack.h
* harbour/source/vm/arrays.c
* harbour/source/vm/estack.c
* harbour/source/vm/hvm.c
* harbour/source/vm/proc.c
+ added startup symbol to hb_stack. It gives very good stop
condition for all procedures which trace stack calls and
resolves the problem with hb_stack.pBase which was never
pointing to valid function/procedure symbol when no symbol
was put on HVM stack. Now after hb_stackInit() the first
item is allocated for "hb_stackInit()" symbol so hb_stack.pBase
is always a pointer to valid function/procedure symbol.
* changed the guard condition for buggy code in hb_stackPop()
and similar code from:
hb_stack.pPos < hb_stack.pItems
to:
hb_stack.pPos <= hb_stack.pBase
The old condition was generating usable error message only in the
startup function. In deeply called functions it was only waste of

View File

@@ -181,9 +181,10 @@
#ifdef HB_CLS_NO_OO_ERR
#xtranslate __HB_CLS_ERR([<msg,...>]) =>
#else
#xtranslate __HB_CLS_ERR([<msg,...>]) => #error [<msg>]
#xtranslate __HB_CLS_ERR([<msg,...>]) => ;#error [<msg>] ; #undef _DUMMY_DEF_
#endif
#xtranslate __HB_CLS_VARERR(<var>) => __HB_CLS_ERR( Invalid instance variable name: <var> )
DECLARE HBClass ;
New( cName AS String, OPTIONAL SuperParams ) AS CLASS HBClass ;
@@ -220,12 +221,15 @@ DECLARE HBClass ;
#xtranslate __HB_CLS_ASARGS( <FuncName>([<Args,...>]) ) => [<Args>]
#xtranslate __HB_CLS_ASARGSOPT( <FuncName> ) =>
#xtranslate __HB_CLS_ASARGSOPT( <FuncName>([<Args,...>]) ) => [, <Args>]
#xtranslate __HB_CLS_ISVAR( <var> ) =>
#xtranslate __HB_CLS_ISVAR( <var>([<params,...>]) ) => __HB_CLS_VARERR(<var>([<params>]))
#xcommand __HB_CLS_CHECKVAR( <param1> [,<paramN>] ) => __HB_CLS_ISVAR( <param1> ) [;__HB_CLS_ISVAR( <paramN> )]
/* #xtranslate __HB_CLS_SCOPE( <export>, <protect>, <hidde> ) => ;
iif( <export>, HB_OO_CLSTP_EXPORTED , ;
iif( <protect>, HB_OO_CLSTP_PROTECTED, ;
iif( <hidde>, HB_OO_CLSTP_HIDDEN, nScope ) ) ) */
#xtranslate __HB_CLS_SCOPE( <x,...> ) => );__HB_CLS_ERR( Can not use multiple scope qualifiers! );empty(nScope
#xtranslate __HB_CLS_SCOPE( <x,...> ) => __HB_CLS_ERR( Can not use multiple scope qualifiers! )
#xtranslate __HB_CLS_SCOPE( .T., .F., .F. ) => HB_OO_CLSTP_EXPORTED
#xtranslate __HB_CLS_SCOPE( .F., .T., .F. ) => HB_OO_CLSTP_PROTECTED
#xtranslate __HB_CLS_SCOPE( .F., .F., .T. ) => HB_OO_CLSTP_HIDDEN
@@ -442,25 +446,31 @@ DECLARE HBClass ;
/* This definitions are not Class(y) compatible - I'm leaving them as is now */
#xcommand VAR <DataNames,...> [ <tp: TYPE, AS> <type> ] [ <as: ASSIGN, INIT> <uValue> ] [<export: EXPORTED, VISIBLE>] [<protect: PROTECTED>] [<hidde: HIDDEN>] [<ro: READONLY, RO>] [<persistent: PERSISTENT, PROPERTY>] => ;
__HB_CLS_CHECKVAR(<DataNames>);;
_HB_MEMBER {[AS <type>] <DataNames>} ;;
s_oClass:AddMultiData( <(type)>, <uValue>, __HB_CLS_SCOPE( <.export.>, <.protect.>, <.hidde.> ) + iif( <.ro.>, HB_OO_CLSTP_READONLY, 0 ) + iif( <.persistent.>, HB_OO_CLSTP_PERSIST, 0 ), {<(DataNames)>}, __HB_CLS_NOINI )
#xcommand VAR <DataName> [ AS <type> ] IN <SuperClass> => ;
__HB_CLS_CHECKVAR(<DataName>);;
_HB_MEMBER {[AS <type>] <DataName>} ;;
s_oClass:AddInline( <(DataName)>, {|Self| Self:<SuperClass>:<DataName> }, HB_OO_CLSTP_EXPORTED + HB_OO_CLSTP_READONLY ) ;;
s_oClass:AddInline( "_" + <(DataName)>, {|Self, param| Self:<SuperClass>:<DataName> := param }, HB_OO_CLSTP_EXPORTED )
#xcommand VAR <DataName> [ AS <type> ] IS <SprDataName> IN <SuperClass> => ;
__HB_CLS_CHECKVAR(<DataName>);;
_HB_MEMBER {[AS <type>] <DataName>} ;;
s_oClass:AddInline( <(DataName)>, {|Self| Self:<SuperClass>:<SprDataName> }, HB_OO_CLSTP_EXPORTED + HB_OO_CLSTP_READONLY ) ;;
s_oClass:AddInline( "_" + <(DataName)>, {|Self, param| Self:<SuperClass>:<SprDataName> := param }, HB_OO_CLSTP_EXPORTED )
#xcommand VAR <DataName1> [ AS <type> ] IS <DataName2> => ;
__HB_CLS_CHECKVAR(<DataName1>);;
_HB_MEMBER {[AS <type>] <DataName1>} ;;
s_oClass:AddInline( <(DataName1)>, {|Self| Self:<DataName2> }, HB_OO_CLSTP_EXPORTED + HB_OO_CLSTP_READONLY ) ;;
s_oClass:AddInline( "_" + <(DataName1)>, {|Self, param| Self:<DataName2> := param }, HB_OO_CLSTP_EXPORTED )
#xcommand VAR <DataName1> IS <DataName2> TO <oObject> => ;
#xcommand VAR <DataName1> [ AS <type> ] IS <DataName2> TO <oObject> => ;
__HB_CLS_CHECKVAR(<DataName1>);;
_HB_MEMBER {[AS <type>] <DataName1>} ;;
s_oClass:AddInline( <(DataName1)>, {|Self| Self:<oObject>:<DataName2> }, HB_OO_CLSTP_EXPORTED + HB_OO_CLSTP_READONLY ) ;;
s_oClass:AddInline( "_" + <(DataName1)>, {|Self, param| Self:<oObject>:<DataName2> := param }, HB_OO_CLSTP_EXPORTED )
@@ -470,6 +480,7 @@ DECLARE HBClass ;
#ifdef HB_CLS_FWO
#xcommand DATA <DataNames,...> [ AS <type> ] [ INIT <uValue> ] [ <export: EXPORTED, VISIBLE>] [<protect: PROTECTED>] [<hidde: HIDDEN>] [<ro: READONLY, RO>] [<persistent: PERSISTENT, PROPERTY>] => ;
__HB_CLS_CHECKVAR(<DataNames>);;
_HB_MEMBER {[AS <type>] <DataNames>} ;;
s_oClass:AddMultiData( <(type)>, <uValue>, __HB_CLS_SCOPE( <.export.>, <.protect.>, <.hidde.> ) + iif( <.ro.>, HB_OO_CLSTP_READONLY, 0 ) + iif( <.persistent.>, HB_OO_CLSTP_PERSIST, 0 ), {<(DataNames)>}, __HB_CLS_NOINI )
@@ -489,14 +500,17 @@ DECLARE HBClass ;
#xtranslate , <!name!>{ [<p,...>] } => , <name>():New( <p> )
#xcommand EXPORT <DataNames,...> [ <tp: TYPE, AS> <type> ] [ <as: ASSIGN, INIT> <uValue> ] [<ro: READONLY, RO>] [<persistent: PERSISTENT, PROPERTY>] => ;
__HB_CLS_CHECKVAR(<DataNames>);;
_HB_MEMBER {[AS <type>] <DataNames>} ;;
s_oClass:AddMultiData( <(type)>, <uValue>, HB_OO_CLSTP_EXPORTED + iif( <.ro.>, HB_OO_CLSTP_READONLY, 0 ) + iif( <.persistent.>, HB_OO_CLSTP_PERSIST, 0 ), {<(DataNames)>}, __HB_CLS_NOINI )
#xcommand PROTECT <DataNames,...> [ <tp: TYPE, AS> <type> ] [ <as: ASSIGN, INIT> <uValue> ] [<ro: READONLY, RO>] [<persistent: PERSISTENT, PROPERTY>] => ;
__HB_CLS_CHECKVAR(<DataNames>);;
_HB_MEMBER {[AS <type>] <DataNames>} ;;
s_oClass:AddMultiData( <(type)>, <uValue>, HB_OO_CLSTP_PROTECTED + iif( <.ro.>, HB_OO_CLSTP_READONLY, 0 ) + iif( <.persistent.>, HB_OO_CLSTP_PERSIST, 0 ), {<(DataNames)>}, __HB_CLS_NOINI )
#xcommand HIDDE <DataNames,...> [ <tp: TYPE, AS> <type> ] [ <as: ASSIGN, INIT> <uValue> ] [<ro: READONLY, RO>] [<persistent: PERSISTENT, PROPERTY>] => ;
__HB_CLS_CHECKVAR(<DataNames>);;
_HB_MEMBER {[AS <type>] <DataNames>} ;;
s_oClass:AddMultiData( <(type)>, <uValue>, HB_OO_CLSTP_HIDDEN + iif( <.ro.>, HB_OO_CLSTP_READONLY, 0 ) + iif( <.persistent.>, HB_OO_CLSTP_PERSIST, 0 ), {<(DataNames)>}, __HB_CLS_NOINI )
@@ -511,6 +525,7 @@ DECLARE HBClass ;
s_oClass:AddClsMthds( __HB_CLS_ASSTRING(<MethodName>), @__HB_CLS_ASID( __HB_CLS_MTHNAME _CLASS_NAME_ <MethodName> )(), __HB_CLS_SCOPE( <.export.>, <.protect.>, <.hidde.> ) + iif( <.share.>, HB_OO_CLSTP_SHARED, 0 ) + iif( <.persistent.>, HB_OO_CLSTP_PERSIST, 0 ) )
#xcommand CLASSVAR <DataNames,...> [ <tp: TYPE, AS> <type> ] [ <as: ASSIGN, INIT> <uValue> ] [<export: EXPORTED, VISIBLE>] [<protect: PROTECTED>] [<hidde: HIDDEN>] [<ro: READONLY, RO>] [<share: SHARED>] [<persistent: PERSISTENT, PROPERTY>] => ;
__HB_CLS_CHECKVAR(<DataNames>);;
_HB_MEMBER {[AS <type>] <DataNames>} ;;
s_oClass:AddMultiClsData( <(type)>, <uValue>, __HB_CLS_SCOPE( <.export.>, <.protect.>, <.hidde.> ) + iif( <.ro.>, HB_OO_CLSTP_READONLY, 0 ) + iif( <.share.>, HB_OO_CLSTP_SHARED, 0 ) + iif( <.persistent.>, HB_OO_CLSTP_PERSIST, 0 ), {<(DataNames)>}, __HB_CLS_NOINI )

View File

@@ -105,6 +105,7 @@
#define HB_OO_MSG_DESTRUCTOR 13
#define HB_OO_MSG_INITIALIZED 14
#define HB_OO_MSG_PERFORM 15
#define HB_OO_MSG_DELEGATE 16
/* Data */
#define HB_OO_DATA_SYMBOL 1

View File

@@ -76,6 +76,7 @@ typedef struct
PHB_ITEM * pEvalBase; /* stack frame position for the evaluated codeblock */
LONG lStatics; /* statics base for the current function call */
LONG lWithObject; /* stack offset to base current WITH OBJECT item */
HB_STACK_STATE state; /* first (default) stack state frame */
char szDate[ 9 ]; /* last returned date from _pards() yyyymmdd format */
} HB_STACK;
@@ -121,8 +122,8 @@ extern void hb_stackIncrease( void ); /* increase the stack size */
#ifdef _HB_API_INTERNAL_
extern void hb_stackDecrease( ULONG ulItems );
extern HB_ITEM_PTR hb_stackNewFrame( HB_STACK_STATE * pStack, USHORT uiParams );
extern void hb_stackOldFrame( HB_STACK_STATE * pStack );
extern HB_ITEM_PTR hb_stackNewFrame( PHB_STACK_STATE pStack, USHORT uiParams );
extern void hb_stackOldFrame( PHB_STACK_STATE pStack );
extern void hb_stackClearMevarsBase( void );
#endif
@@ -149,45 +150,67 @@ extern void hb_stackClearMevarsBase( void );
hb_stackIncrease() : (void) 0 ), \
* ( hb_stack.pPos - 1 ) )
#ifdef HB_STACK_SAFEMACROS
#define hb_stackDecrease( n ) do { \
if( ( hb_stack.pPos -= (n) ) < hb_stack.pItems ) \
if( ( hb_stack.pPos -= (n) ) <= hb_stack.pBase ) \
hb_errInternal( HB_EI_STACKUFLOW, NULL, NULL, NULL ); \
} while ( 0 )
#define hb_stackDec( ) do { \
if( --hb_stack.pPos < hb_stack.pItems ) \
if( --hb_stack.pPos <= hb_stack.pBase ) \
hb_errInternal( HB_EI_STACKUFLOW, NULL, NULL, NULL ); \
} while ( 0 )
#define hb_stackPop( ) do { \
if( --hb_stack.pPos < hb_stack.pItems ) \
if( --hb_stack.pPos <= hb_stack.pBase ) \
hb_errInternal( HB_EI_STACKUFLOW, NULL, NULL, NULL ); \
if( HB_IS_COMPLEX( * hb_stack.pPos ) ) \
hb_itemClear( * hb_stack.pPos ); \
} while ( 0 )
#define hb_stackPush( ) do { \
if( ++hb_stack.pPos == hb_stack.pEnd ) \
hb_stackIncrease(); \
} while ( 0 )
#define hb_stackPopReturn( ) do { \
if( HB_IS_COMPLEX( &hb_stack.Return ) ) \
hb_itemClear( &hb_stack.Return ); \
if( --hb_stack.pPos < hb_stack.pItems ) \
if( --hb_stack.pPos <= hb_stack.pBase ) \
hb_errInternal( HB_EI_STACKUFLOW, NULL, NULL, NULL ); \
hb_itemRawMove( &hb_stack.Return, * hb_stack.pPos ); \
} while ( 0 )
#else
#define hb_stackDecrease( n ) do { hb_stack.pPos -= (n); } while ( 0 )
#define hb_stackDec( ) do { --hb_stack.pPos; } while ( 0 )
#define hb_stackPop( ) do { --hb_stack.pPos; \
if( HB_IS_COMPLEX( * hb_stack.pPos ) ) \
hb_itemClear( * hb_stack.pPos ); \
} while ( 0 )
#define hb_stackPopReturn( ) do { \
if( HB_IS_COMPLEX( &hb_stack.Return ) ) \
hb_itemClear( &hb_stack.Return ); \
--hb_stack.pPos; \
hb_itemRawMove( &hb_stack.Return, * hb_stack.pPos ); \
} while ( 0 )
#endif
#define hb_stackPush( ) do { \
if( ++hb_stack.pPos == hb_stack.pEnd ) \
hb_stackIncrease(); \
} while ( 0 )
#define hb_stackPushReturn( ) do { \
hb_itemRawMove( * hb_stack.pPos, &hb_stack.Return ); \
if( ++hb_stack.pPos == hb_stack.pEnd ) \
hb_stackIncrease(); \
} while ( 0 )
#define hb_stackLocalVariable( p ) ((((*hb_stack.pBase)->item.asSymbol.paramcnt > (*hb_stack.pBase)->item.asSymbol.paramdeclcnt) && \
(*(p)) > (*hb_stack.pBase)->item.asSymbol.paramdeclcnt ) ? \
(* ( hb_stack.pBase + ( int ) ((*(p))+=((*hb_stack.pBase)->item.asSymbol.paramcnt - (*hb_stack.pBase)->item.asSymbol.paramdeclcnt)) + 1 ) ) : \
(* ( hb_stack.pBase + ( int ) (*(p)) + 1 ) ) )
#define hb_stackLocalVariable( p ) ( ( ( ( *hb_stack.pBase )->item.asSymbol.paramcnt > \
( * hb_stack.pBase )->item.asSymbol.paramdeclcnt ) && \
( * (p) ) > ( * hb_stack.pBase )->item.asSymbol.paramdeclcnt ) ? \
( * ( hb_stack.pBase + ( int ) ( * (p) += \
( * hb_stack.pBase )->item.asSymbol.paramcnt - \
( * hb_stack.pBase )->item.asSymbol.paramdeclcnt ) + 1 ) ) : \
( * ( hb_stack.pBase + ( int ) ( * (p) ) + 1 ) ) )
#endif

View File

@@ -83,8 +83,8 @@ FUNCTION HBClass()
STATIC s_hClass /* NOTE: Automatically default to NIL */
IF s_hClass == NIL
s_hClass := __clsNew( "HBCLASS", 15)
/* s_hClass := __clsNew( "HBCLASS", 16) */
s_hClass := __clsNew( "HBCLASS", 16)
/* s_hClass := __clsNew( "HBCLASS", 17) */
__clsAddMsg( s_hClass, "New" , @New() , HB_OO_MSG_METHOD )
__clsAddMsg( s_hClass, "Create" , @Create() , HB_OO_MSG_METHOD )
@@ -96,6 +96,7 @@ FUNCTION HBClass()
__clsAddMsg( s_hClass, "AddMethod" , @AddMethod() , HB_OO_MSG_METHOD )
__clsAddMsg( s_hClass, "AddClsMethod" , @AddClsMethod() , HB_OO_MSG_METHOD )
__clsAddMsg( s_hClass, "AddVirtual" , @AddVirtual() , HB_OO_MSG_METHOD )
__clsAddMsg( s_hClass, "AddDelegate" , @AddDelegate() , HB_OO_MSG_METHOD )
__clsAddMsg( s_hClass, "AddFriendFunc" , @AddFriendFunc() , HB_OO_MSG_METHOD )
__clsAddMsg( s_hClass, "AddFriendClass" , @AddFriendClass() , HB_OO_MSG_METHOD )
__clsAddMsg( s_hClass, "Instance" , @Instance() , HB_OO_MSG_METHOD )
@@ -119,22 +120,25 @@ FUNCTION HBClass()
__clsAddMsg( s_hClass, "_aInlines" , 7, HB_OO_MSG_ASSIGN )
__clsAddMsg( s_hClass, "aVirtuals" , 8, HB_OO_MSG_ACCESS )
__clsAddMsg( s_hClass, "_aVirtuals" , 8, HB_OO_MSG_ASSIGN )
__clsAddMsg( s_hClass, "asSuper" , 9, HB_OO_MSG_ACCESS )
__clsAddMsg( s_hClass, "_asSuper" , 9, HB_OO_MSG_ASSIGN )
__clsAddMsg( s_hClass, "nOnError" , 10, HB_OO_MSG_ACCESS )
__clsAddMsg( s_hClass, "_nOnError" , 10, HB_OO_MSG_ASSIGN )
__clsAddMsg( s_hClass, "nDestructor" , 11, HB_OO_MSG_ACCESS )
__clsAddMsg( s_hClass, "_nDestructor" , 11, HB_OO_MSG_ASSIGN )
__clsAddMsg( s_hClass, "lModFriendly" , 12, HB_OO_MSG_ACCESS )
__clsAddMsg( s_hClass, "_lModFriendly" , 12, HB_OO_MSG_ASSIGN )
__clsAddMsg( s_hClass, "asFriendClass" , 13, HB_OO_MSG_ACCESS )
__clsAddMsg( s_hClass, "_asFriendClass" , 13, HB_OO_MSG_ASSIGN )
__clsAddMsg( s_hClass, "asFriendFunc" , 14, HB_OO_MSG_ACCESS )
__clsAddMsg( s_hClass, "_asFriendFunc" , 14, HB_OO_MSG_ASSIGN )
__clsAddMsg( s_hClass, "sClassFunc" , 15, HB_OO_MSG_ACCESS )
__clsAddMsg( s_hClass, "_sClassFunc" , 15, HB_OO_MSG_ASSIGN )
/* __clsAddMsg( s_hClass, "class" , 16, HB_OO_MSG_ACCESS )
__clsAddMsg( s_hClass, "_class" , 16, HB_OO_MSG_ASSIGN ) */
__clsAddMsg( s_hClass, "aDelegates" , 9, HB_OO_MSG_ACCESS )
__clsAddMsg( s_hClass, "_aDelegates" , 9, HB_OO_MSG_ASSIGN )
__clsAddMsg( s_hClass, "asSuper" , 10, HB_OO_MSG_ACCESS )
__clsAddMsg( s_hClass, "_asSuper" , 10, HB_OO_MSG_ASSIGN )
__clsAddMsg( s_hClass, "nOnError" , 11, HB_OO_MSG_ACCESS )
__clsAddMsg( s_hClass, "_nOnError" , 11, HB_OO_MSG_ASSIGN )
__clsAddMsg( s_hClass, "nDestructor" , 12, HB_OO_MSG_ACCESS )
__clsAddMsg( s_hClass, "_nDestructor" , 12, HB_OO_MSG_ASSIGN )
__clsAddMsg( s_hClass, "lModFriendly" , 13, HB_OO_MSG_ACCESS )
__clsAddMsg( s_hClass, "_lModFriendly" , 13, HB_OO_MSG_ASSIGN )
__clsAddMsg( s_hClass, "asFriendClass" , 14, HB_OO_MSG_ACCESS )
__clsAddMsg( s_hClass, "_asFriendClass" , 14, HB_OO_MSG_ASSIGN )
__clsAddMsg( s_hClass, "asFriendFunc" , 15, HB_OO_MSG_ACCESS )
__clsAddMsg( s_hClass, "_asFriendFunc" , 15, HB_OO_MSG_ASSIGN )
__clsAddMsg( s_hClass, "sClassFunc" , 16, HB_OO_MSG_ACCESS )
__clsAddMsg( s_hClass, "_sClassFunc" , 16, HB_OO_MSG_ASSIGN )
/* __clsAddMsg( s_hClass, "class" , 17, HB_OO_MSG_ACCESS )
__clsAddMsg( s_hClass, "_class" , 17, HB_OO_MSG_ASSIGN ) */
ENDIF
@@ -184,6 +188,7 @@ STATIC FUNCTION New( cClassName, xSuper, sClassFunc, lModuleFriendly )
::aClsMethods := {}
::aInlines := {}
::aVirtuals := {}
::aDelegates := {}
::asFriendClass := {}
::asFriendFunc := {}
@@ -404,6 +409,20 @@ STATIC PROCEDURE AddVirtual( cMethod )
RETURN
STATIC PROCEDURE AddDelegate( xMethod, nAccScope, nAsgScope, cType, cDelegMsg, cDelegClass )
LOCAL i
IF VALTYPE( xMethod ) == "C"
AAdd( QSelf():aDelegates, { xMethod, nAccScope, nAsgScope, cType, cDelegMsg, cDelegClass } )
ELSEIF VALTYPE( xMethod ) == "A"
FOR i := 1 TO LEN( xMethod )
AAdd( QSelf():aDelegates, { xMethod[ i ], nAccScope, nAsgScope, cType, cDelegMsg, cDelegClass } )
NEXT
ENDIF
RETURN
//----------------------------------------------------------------------------//
STATIC PROCEDURE AddFriendClass( ... )

View File

@@ -991,7 +991,7 @@ PHB_ITEM hb_arrayFromParams( int iLevel )
HB_TRACE(HB_TR_DEBUG, ("hb_arrayFromParams(%d)", iLevel));
lBaseOffset = hb_stackBaseProcOffset( iLevel );
if( lBaseOffset >= 0 )
if( lBaseOffset > 0 )
uiPCount = hb_stackItem( lBaseOffset )->item.asSymbol.paramcnt;
else
uiPCount = 0;

View File

@@ -166,7 +166,7 @@ typedef struct
PHB_SYMB pFuncSym; /* Function symbol */
USHORT uiSprClass; /* Originalclass'handel (super or current class'handel if not herited). */ /*Added by RAC&JF*/
USHORT uiScope; /* Scoping value */
USHORT uiData; /* Item position for instance data, class or shared data (Harbour like, begin from 1) */
USHORT uiData; /* Item position for instance data, class data and shared data (Harbour like, begin from 1) or delegated message index object */
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;
@@ -246,6 +246,7 @@ static HARBOUR hb___msgVirtual( void );
static HARBOUR hb___msgSuper( void );
static HARBOUR hb___msgRealClass( void );
static HARBOUR hb___msgPerform( void );
static HARBOUR hb___msgDelegate( void );
static HARBOUR hb___msgNoMethod( void );
static HARBOUR hb___msgScopeErr( void );
static HARBOUR hb___msgTypeErr( void );
@@ -308,6 +309,7 @@ static HB_SYMB s___msgVirtual = { "__msgVirtual", {HB_FS_MESSAGE}, {hb___m
static HB_SYMB s___msgSuper = { "__msgSuper", {HB_FS_MESSAGE}, {hb___msgSuper}, NULL };
static HB_SYMB s___msgRealClass = { "__msgRealClass", {HB_FS_MESSAGE}, {hb___msgRealClass}, NULL };
static HB_SYMB s___msgPerform = { "__msgPerform", {HB_FS_MESSAGE}, {hb___msgPerform}, NULL };
static HB_SYMB s___msgDelegate = { "__msgDelegate", {HB_FS_MESSAGE}, {hb___msgDelegate}, 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 };
@@ -1211,7 +1213,7 @@ char * hb_clsRealMethodName( void )
LONG lOffset = hb_stackBaseProcOffset( 1 );
char * szName = NULL;
if( lOffset >=0 )
if( lOffset > 0 )
{
PHB_STACK_STATE pStack = hb_stackItem( lOffset )->item.asSymbol.stackstate;
@@ -1236,7 +1238,7 @@ static LONG hb_clsSenderOffset( void )
{
LONG lOffset = hb_stackBaseProcOffset( 1 );
if( lOffset >=0 )
if( lOffset > 0 )
{
/* Is it inline method? */
if( lOffset > 0 && HB_IS_BLOCK( hb_stackItem( lOffset + 1 ) ) &&
@@ -1262,7 +1264,7 @@ static USHORT hb_clsSenderClasss( void )
{
LONG lOffset = hb_clsSenderOffset();
if( lOffset >=0 )
if( lOffset > 0 )
return hb_stackItem( lOffset )->item.asSymbol.stackstate->uiClass;
else
return 0;
@@ -1273,7 +1275,7 @@ static USHORT hb_clsSenderMethodClasss( void )
{
LONG lOffset = hb_clsSenderOffset();
if( lOffset >=0 )
if( lOffset > 0 )
{
PHB_STACK_STATE pStack = hb_stackItem( lOffset )->item.asSymbol.stackstate;
@@ -1289,7 +1291,7 @@ static PHB_SYMB hb_clsSenderSymbol( void )
PHB_SYMB pSym = NULL;
LONG lOffset = hb_clsSenderOffset();
if( lOffset >=0 )
if( lOffset > 0 )
{
pSym = hb_stackItem( lOffset )->item.asSymbol.value;
@@ -1309,7 +1311,7 @@ static USHORT hb_clsSenderObjectClasss( void )
{
LONG lOffset = hb_clsSenderOffset();
if( lOffset >=0 )
if( lOffset > 0 )
{
PHB_ITEM pSender = hb_stackItem( lOffset + 1 );
@@ -1815,9 +1817,8 @@ HB_EXPORT void hb_objSendMsg( PHB_ITEM pObject, char *sMsg, ULONG ulArg, ... )
hb_vmSend( (USHORT) ulArg );
}
static PHB_DYNS hb_objMsgParam( int iParam )
static PHB_DYNS hb_objGetMsgSym( PHB_ITEM pMessage )
{
PHB_ITEM pMessage = hb_param( iParam, HB_IT_STRING | HB_IT_SYMBOL );
PHB_DYNS pDynSym = NULL;
if( pMessage )
@@ -1826,7 +1827,7 @@ static PHB_DYNS hb_objMsgParam( int iParam )
if( HB_IS_STRING( pMessage ) )
szMsg = pMessage->item.asString.value;
else
else if( HB_IS_SYMBOL( pMessage ) )
{
pDynSym = pMessage->item.asSymbol.value->pDynSym;
if( !pDynSym )
@@ -1969,6 +1970,7 @@ static HB_TYPE hb_clsGetItemType( PHB_ITEM pItem )
* HB_OO_MSG_REALCLASS : caller method real class casting
* HB_OO_MSG_PERFORM : perform method
* HB_OO_MSG_VIRTUAL : virtual method
* HB_OO_MSG_DELEGATE : delegate method
*
* <uiScope> * HB_OO_CLSTP_EXPORTED 1 : default for data and method
* HB_OO_CLSTP_PROTECTED 2 : method or data protected
@@ -1994,6 +1996,7 @@ static HB_TYPE hb_clsGetItemType( PHB_ITEM pItem )
* HB_OO_MSG_CLSASSIGN : Index class data array
* HB_OO_MSG_CLSACCESS : /
* HB_OO_MSG_SUPER : Handle of super class
* HB_OO_MSG_DELEGATE : delegated message symbol
*
* <pInit> HB_OO_MSG_ACCESS : Optional initializer for (Class)DATA
* HB_OO_MSG_CLSACCESS : /
@@ -2127,6 +2130,18 @@ static BOOL hb_clsAddMsg( USHORT uiClass, char * szMessage,
fOK = uiIndex != 0;
break;
case HB_OO_MSG_DELEGATE:
{
PHB_DYNS pDelegMsg = hb_objGetMsgSym( pFunction );
if( pDelegMsg )
{
pNewMeth = hb_clsFindMsg( pClass, pDelegMsg );
if( pNewMeth )
uiIndex = ( USHORT ) ( pNewMeth - pClass->pMethods );
}
fOK = uiIndex != 0;
break;
}
case HB_OO_MSG_REALCLASS:
case HB_OO_MSG_VIRTUAL:
case HB_OO_MSG_PERFORM:
@@ -2300,6 +2315,12 @@ static BOOL hb_clsAddMsg( USHORT uiClass, char * szMessage,
pNewMeth->uiScope = uiScope;
break;
case HB_OO_MSG_DELEGATE:
pNewMeth->pFuncSym = &s___msgDelegate;
pNewMeth->uiScope = uiScope;
pNewMeth->uiData = uiIndex;
break;
case HB_OO_MSG_ONERROR:
pNewMeth->pFuncSym = pFuncSym;
@@ -2342,11 +2363,13 @@ static BOOL hb_clsAddMsg( USHORT uiClass, char * szMessage,
* HB_OO_MSG_CLSASSIGN : > Index class data array
* HB_OO_MSG_CLSACCESS : /
* HB_OO_MSG_SUPER : Handle of super class
* HB_OO_MSG_DELEGATE : delegated message symbol
*
* <nType> see HB_OO_MSG_* above and:
* HB_OO_MSG_REALCLASS : caller method real class casting
* HB_OO_MSG_PERFORM : perform message
* HB_OO_MSG_VIRTUAL : virtual message
* HB_OO_MSG_DELEGATE : delegate method
*
* <xInit> HB_OO_MSG_ACCESS : \
* HB_OO_MSG_CLSACCESS : > Optional initializer for DATA
@@ -2886,7 +2909,7 @@ HB_FUNC( __OBJGETCLSNAME )
*/
HB_FUNC( __OBJHASMSG )
{
PHB_DYNS pMessage = hb_objMsgParam( 2 );
PHB_DYNS pMessage = hb_objGetMsgSym( hb_param( 2, HB_IT_ANY ) );
if( pMessage )
hb_retl( hb_objHasMessage( hb_param( 1, HB_IT_ANY ), pMessage ) );
@@ -2901,7 +2924,7 @@ HB_FUNC( __OBJHASMSG )
*/
HB_FUNC( __OBJSENDMSG )
{
PHB_DYNS pMessage = hb_objMsgParam( 2 );
PHB_DYNS pMessage = hb_objGetMsgSym( hb_param( 2, HB_IT_ANY ) );
if( pMessage )
{
@@ -3211,7 +3234,7 @@ HB_FUNC( __SENDER )
{
LONG lOffset = hb_stackBaseProcOffset( 2 );
if( lOffset >= 0 )
if( lOffset > 0 )
{
PHB_ITEM pSelf = hb_stackItem( lOffset + 1 );
@@ -3435,6 +3458,29 @@ static HARBOUR hb___msgPerform( void )
}
}
static HARBOUR hb___msgDelegate( void )
{
PCLASS pClass = &s_pClasses[
hb_stackBaseItem()->item.asSymbol.stackstate->uiClass ];
PMETHOD pMethod = pClass->pMethods +
hb_stackBaseItem()->item.asSymbol.stackstate->uiMethod;
PHB_SYMB pExecSym = pClass->pMethods[ pMethod->uiData ].pFuncSym;
if( pExecSym && pExecSym->value.pFunPtr )
{
if( pExecSym->scope.value & HB_FS_PCODEFUNC )
/* Running pCode dynamic function from .HRB */
hb_vmExecute( pExecSym->value.pCodeFunc->pCode,
pExecSym->value.pCodeFunc->pSymbols );
else
pExecSym->value.pFunPtr();
}
else
{
hb___msgNoMethod();
}
}
/*
* __msgNoMethod()
*

View File

@@ -73,6 +73,8 @@
HB_STACK hb_stack;
HB_SYMB s_initSymbol = { "hb_stackInit", {HB_FS_STATIC}, {NULL}, NULL };
/* ------------------------------- */
#undef hb_stackPop
@@ -80,7 +82,7 @@ void hb_stackPop( void )
{
HB_TRACE(HB_TR_DEBUG, ("hb_stackPop()"));
if( --hb_stack.pPos < hb_stack.pItems )
if( --hb_stack.pPos <= hb_stack.pBase )
hb_errInternal( HB_EI_STACKUFLOW, NULL, NULL, NULL );
if( HB_IS_COMPLEX( * hb_stack.pPos ) )
@@ -95,7 +97,7 @@ void hb_stackPopReturn( void )
if( HB_IS_COMPLEX( &hb_stack.Return ) )
hb_itemClear( &hb_stack.Return );
if( --hb_stack.pPos < hb_stack.pItems )
if( --hb_stack.pPos <= hb_stack.pBase )
hb_errInternal( HB_EI_STACKUFLOW, NULL, NULL, NULL );
hb_itemRawMove( &hb_stack.Return, * hb_stack.pPos );
@@ -106,7 +108,7 @@ void hb_stackDec( void )
{
HB_TRACE(HB_TR_DEBUG, ("hb_stackDec()"));
if( --hb_stack.pPos < hb_stack.pItems )
if( --hb_stack.pPos <= hb_stack.pBase )
hb_errInternal( HB_EI_STACKUFLOW, NULL, NULL, NULL );
}
@@ -115,7 +117,7 @@ void hb_stackDecrease( ULONG ulItems )
{
HB_TRACE(HB_TR_DEBUG, ("hb_stackDec()"));
if( ( hb_stack.pPos -= ulItems ) < hb_stack.pItems )
if( ( hb_stack.pPos -= ulItems ) <= hb_stack.pBase )
hb_errInternal( HB_EI_STACKUFLOW, NULL, NULL, NULL );
}
@@ -213,6 +215,10 @@ void hb_stackInit( void )
hb_stack.pItems[ i ] = ( PHB_ITEM ) hb_xgrab( sizeof( HB_ITEM ) );
hb_stack.pItems[ i ]->type = HB_IT_NIL;
}
hb_stack.pPos++;
hb_itemPutSymbol( * hb_stack.pItems, &s_initSymbol );
( * hb_stack.pItems )->item.asSymbol.stackstate = &hb_stack.state;
}
void hb_stackRemove( LONG lUntilPos )
@@ -227,7 +233,7 @@ void hb_stackRemove( LONG lUntilPos )
}
}
HB_ITEM_PTR hb_stackNewFrame( HB_STACK_STATE * pStack, USHORT uiParams )
HB_ITEM_PTR hb_stackNewFrame( PHB_STACK_STATE pStack, USHORT uiParams )
{
HB_ITEM_PTR * pBase, pItem;
@@ -257,14 +263,18 @@ HB_ITEM_PTR hb_stackNewFrame( HB_STACK_STATE * pStack, USHORT uiParams )
return pItem;
}
void hb_stackOldFrame( HB_STACK_STATE * pStack )
void hb_stackOldFrame( PHB_STACK_STATE pStack )
{
while( hb_stack.pPos > hb_stack.pBase )
if( hb_stack.pPos <= hb_stack.pBase )
hb_errInternal( HB_EI_STACKUFLOW, NULL, NULL, NULL );
do
{
--hb_stack.pPos;
if( HB_IS_COMPLEX( * hb_stack.pPos ) )
hb_itemClear( * hb_stack.pPos );
}
while( hb_stack.pPos > hb_stack.pBase );
hb_stack.pBase = hb_stack.pItems + pStack->lBaseItem;
hb_stack.lStatics = pStack->lStatics;
@@ -283,7 +293,7 @@ HB_ITEM_PTR hb_stackItem( LONG iItemPos )
#undef hb_stackItemFromTop
HB_ITEM_PTR hb_stackItemFromTop( int nFromTop )
{
if( nFromTop > 0 )
if( nFromTop >= 0 )
hb_errInternal( HB_EI_STACKUFLOW, NULL, NULL, NULL );
return * ( hb_stack.pPos + nFromTop );
@@ -405,24 +415,23 @@ PHB_ITEM ** hb_stackItemBasePtr( void )
void hb_stackClearMevarsBase( void )
{
PHB_ITEM pBase;
HB_TRACE(HB_TR_DEBUG, ("hb_stackClearMevarsBase()"));
if( hb_stack.pBase > hb_stack.pPos )
{
PHB_ITEM pBase = * hb_stack.pBase;
pBase = * hb_stack.pBase;
while( pBase->item.asSymbol.stackstate->ulPrivateBase != 0 )
{
pBase->item.asSymbol.stackstate->ulPrivateBase = 0;
pBase = * ( hb_stack.pItems + pBase->item.asSymbol.stackstate->lBaseItem );
}
while( pBase->item.asSymbol.stackstate->ulPrivateBase != 0 )
{
pBase->item.asSymbol.stackstate->ulPrivateBase = 0;
pBase = * ( hb_stack.pItems + pBase->item.asSymbol.stackstate->lBaseItem );
}
}
int hb_stackCallDepth( void )
{
LONG lOffset = hb_stack.pBase - hb_stack.pItems;
int iLevel = 1;
int iLevel = 0;
while( lOffset > 0 )
{
@@ -452,7 +461,7 @@ void hb_stackBaseProcInfo( char * szProcName, USHORT * puiProcLine )
* This function is called by FM module and has to be ready for execution
* before stack initialization, [druzus];
*/
if( hb_stack.pPos > hb_stack.pBase && HB_IS_SYMBOL( * hb_stack.pBase ) )
if( hb_stack.pPos > hb_stack.pBase )
{
strcpy( szProcName, ( * hb_stack.pBase )->item.asSymbol.value->szName );
* puiProcLine = ( * hb_stack.pBase )->item.asSymbol.stackstate->uiLineNo;
@@ -547,12 +556,10 @@ void hb_stackDispCall( void )
HB_TRACE(HB_TR_DEBUG, ("hb_stackDispCall()"));
while( pBase != hb_stack.pItems )
while( pBase > hb_stack.pItems )
{
char buffer[ HB_SYMBOL_NAME_LEN + HB_SYMBOL_NAME_LEN + 32 ];
pBase = hb_stack.pItems + ( *pBase )->item.asSymbol.stackstate->lBaseItem;
if( HB_IS_OBJECT( *( pBase + 1 ) ) )
sprintf( buffer, HB_I_("Called from %s:%s(%i)"), hb_objGetClsName( *(pBase + 1) ),
( *pBase )->item.asSymbol.value->szName,
@@ -564,6 +571,8 @@ void hb_stackDispCall( void )
hb_conOutErr( buffer, 0 );
hb_conOutErr( hb_conNewLine(), 0 );
pBase = hb_stack.pItems + ( *pBase )->item.asSymbol.stackstate->lBaseItem;
}
}
@@ -588,7 +597,7 @@ void hb_vmIsLocalRef( void )
if( HB_IS_GCITEM( *pItem ) )
hb_gcItemRef( *pItem );
}
while( --pItem >= hb_stack.pItems );
while( --pItem > hb_stack.pItems );
}
}
@@ -606,7 +615,7 @@ LONG WINAPI hb_UnhandledExceptionFilter( struct _EXCEPTION_POINTERS * ExceptionI
msg[ 0 ] = '\0';
do
while( pBase > hb_stack.pItems )
{
char buffer[ HB_SYMBOL_NAME_LEN + HB_SYMBOL_NAME_LEN + 32 ];
@@ -623,7 +632,6 @@ LONG WINAPI hb_UnhandledExceptionFilter( struct _EXCEPTION_POINTERS * ExceptionI
pBase = hb_stack.pItems + ( *pBase )->item.asSymbol.stackstate->lBaseItem;
}
while( pBase != hb_stack.pItems );
MessageBox( NULL, msg, HB_I_("Harbour Exception"), MB_ICONSTOP );
@@ -636,13 +644,11 @@ LONG WINAPI hb_UnhandledExceptionFilter( struct _EXCEPTION_POINTERS * ExceptionI
#if defined(HB_OS_OS2)
ULONG _System OS2TermHandler(PEXCEPTIONREPORTRECORD p1,
PEXCEPTIONREGISTRATIONRECORD p2,
PCONTEXTRECORD p3,
PVOID pv) {
PHB_ITEM *pBase = hb_stack.pBase;
ULONG _System OS2TermHandler( PEXCEPTIONREPORTRECORD p1,
PEXCEPTIONREGISTRATIONRECORD p2,
PCONTEXTRECORD p3,
PVOID pv )
{
HB_SYMBOL_UNUSED(p1);
HB_SYMBOL_UNUSED(p2);
HB_SYMBOL_UNUSED(p3);
@@ -650,11 +656,13 @@ ULONG _System OS2TermHandler(PEXCEPTIONREPORTRECORD p1,
/* Don't print stack trace if inside unwind, normal process termination or process killed or
during debugging */
if (p1->ExceptionNum != XCPT_UNWIND && p1->ExceptionNum < XCPT_BREAKPOINT) {
if( p1->ExceptionNum != XCPT_UNWIND && p1->ExceptionNum < XCPT_BREAKPOINT )
{
PHB_ITEM *pBase = hb_stack.pBase;
fprintf(stderr, HB_I_("\nException %lx at address %p \n"), p1->ExceptionNum, p1->ExceptionAddress);
do
while( pBase > hb_stack.pItems )
{
if( HB_IS_OBJECT( *( pBase + 1 ) ) )
fprintf( stderr, HB_I_("Called from %s:%s(%i)\n"), hb_objGetClsName( *(pBase + 1) ),
@@ -667,7 +675,6 @@ ULONG _System OS2TermHandler(PEXCEPTIONREPORTRECORD p1,
pBase = hb_stack.pItems + ( *pBase )->item.asSymbol.stackstate->lBaseItem;
}
while( pBase != hb_stack.pItems );
}
return XCPT_CONTINUE_SEARCH; /* Exception not resolved... */

View File

@@ -545,7 +545,7 @@ HB_EXPORT int hb_vmQuit( void )
/* release all known items stored in subsystems */
hb_itemClear( hb_stackReturnItem() );
hb_stackRemove( 0 ); /* clear stack items */
hb_stackRemove( 1 ); /* clear stack items, leave only initial symbol item */
hb_memvarsClear(); /* clear all PUBLIC (and PRIVATE if any) variables */
/* intentionally here to allow executing object destructors for all
@@ -4174,9 +4174,9 @@ HB_EXPORT void hb_vmDo( USHORT uiParams )
if( s_bDebugging )
hb_vmDebuggerEndProc();
hb_stackOldFrame( &sStackState );
s_bDebugging = bDebugPrevState;
hb_stackOldFrame( &sStackState );
}
HB_EXPORT void hb_vmSend( USHORT uiParams )
@@ -4234,10 +4234,9 @@ HB_EXPORT void hb_vmSend( USHORT uiParams )
if( s_bDebugging )
hb_vmDebuggerEndProc();
s_bDebugging = bDebugPrevState;
hb_stackOldFrame( &sStackState );
s_bDebugging = bDebugPrevState;
}
static void hb_vmPushObjectVarRef( void )

View File

@@ -95,7 +95,7 @@ HB_FUNC( PROCLINE )
{
long lOffset = hb_stackBaseProcOffset( hb_parni( 1 ) + 1 );
if( lOffset >= 0 )
if( lOffset > 0 )
hb_retni( hb_stackItem( lOffset )->item.asSymbol.stackstate->uiLineNo );
else
hb_retni( 0 );
@@ -118,7 +118,7 @@ HB_FUNC( PROCFILE )
{
long lOffset = hb_stackBaseProcOffset( hb_parni( 1 ) + 1 );
if( lOffset >= 0 )
if( lOffset > 0 )
{
pSym = hb_stackItem( lOffset )->item.asSymbol.value;
@@ -145,7 +145,7 @@ char * hb_procname( int iLevel, char * szName, BOOL fMethodName )
long lOffset = hb_stackBaseProcOffset( iLevel );
szName[ 0 ] = '\0';
if( lOffset >= 0 )
if( lOffset > 0 )
{
PHB_ITEM pBase, pSelf;
@@ -202,7 +202,7 @@ BOOL hb_procinfo( int iLevel, char * szName, USHORT * puiLine, char * szFile )
{
long lOffset = hb_stackBaseProcOffset( iLevel );
if( lOffset >= 0 )
if( lOffset > 0 )
{
PHB_ITEM pBase, pSelf;
PHB_SYMB pSym;