diff --git a/harbour/ChangeLog b/harbour/ChangeLog index b1f1bfb63f..1f35091b41 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -8,6 +8,23 @@ 2009-12-31 13:59 UTC+0100 Foo Bar (foo.bar foobar.org) */ +2009-03-05 12:04 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl) + * harbour/source/vm/memvars.c + ! added protection against pushing new private variable on HVM stack + if such private variable is already created by the same function. + Clipper also has such protection. This code illustrates it: + proc main() + memvar var1, var2, var3 + private var1 := "a", var2 := "b", var3 := "c" + ? var1, var2, var3 + private var1 := "A", var2, var3 := "C" + ? var1, var2, var3 + private var1 := NIL, var2, var3 + ? var1, var2, var3 + return + compare Clipper and current Harbour results with old Harbour ones or + with xHarbour results. + 2009-03-05 11:36 UTC+0100 Viktor Szakats (harbour.01 syenar hu) * utils/hbmk2/hbmk2.prg + Added -prgflag:, -cflag:, -ldflag: options. diff --git a/harbour/source/vm/memvars.c b/harbour/source/vm/memvars.c index 8469a0f312..d2fadf4107 100644 --- a/harbour/source/vm/memvars.c +++ b/harbour/source/vm/memvars.c @@ -227,33 +227,54 @@ static void hb_memvarAddPrivate( PHB_DYNS pDynSym, PHB_ITEM pValue ) pPrivateStack = hb_stackGetPrivateStack(); - /* Allocate the value from the end of table + pMemvar = hb_dynsymGetMemvar( pDynSym ); + /* If the variable with the same name exists already + * and it's PRIVATE variable declared in this function then + * do not push new memvar on PRIVATEs stack */ - if( pPrivateStack->count == pPrivateStack->size ) + if( pMemvar ) { - /* No more free values in the table - expand the table - */ - if( pPrivateStack->size == 0 ) + ULONG ulCount = pPrivateStack->count; + while( ulCount > pPrivateStack->base ) { - pPrivateStack->stack = ( PHB_PRIVATE_ITEM ) - hb_xgrab( sizeof( HB_PRIVATE_ITEM ) * TABLE_INITHB_VALUE ); - pPrivateStack->size = TABLE_INITHB_VALUE; - pPrivateStack->count = pPrivateStack->base = 0; - } - else - { - pPrivateStack->size += TABLE_EXPANDHB_VALUE; - pPrivateStack->stack = ( PHB_PRIVATE_ITEM ) - hb_xrealloc( pPrivateStack->stack, - sizeof( HB_PRIVATE_ITEM ) * pPrivateStack->size ); + if( pDynSym == pPrivateStack->stack[ ulCount - 1 ].pDynSym ) + break; + --ulCount; } + if( ulCount <= pPrivateStack->base ) + pMemvar = NULL; } - pPrivateStack->stack[ pPrivateStack->count ].pDynSym = pDynSym; - pPrivateStack->stack[ pPrivateStack->count++ ].pPrevMemvar = hb_dynsymGetMemvar( pDynSym ); + if( ! pMemvar ) + { + /* Allocate the value from the end of table + */ + if( pPrivateStack->count == pPrivateStack->size ) + { + /* No more free values in the table - expand the table + */ + if( pPrivateStack->size == 0 ) + { + pPrivateStack->stack = ( PHB_PRIVATE_ITEM ) + hb_xgrab( sizeof( HB_PRIVATE_ITEM ) * TABLE_INITHB_VALUE ); + pPrivateStack->size = TABLE_INITHB_VALUE; + pPrivateStack->count = pPrivateStack->base = 0; + } + else + { + pPrivateStack->size += TABLE_EXPANDHB_VALUE; + pPrivateStack->stack = ( PHB_PRIVATE_ITEM ) + hb_xrealloc( pPrivateStack->stack, + sizeof( HB_PRIVATE_ITEM ) * pPrivateStack->size ); + } + } - pMemvar = hb_memvarValueNew(); - hb_dynsymSetMemvar( pDynSym, pMemvar ); + pPrivateStack->stack[ pPrivateStack->count ].pDynSym = pDynSym; + pPrivateStack->stack[ pPrivateStack->count++ ].pPrevMemvar = hb_dynsymGetMemvar( pDynSym ); + + pMemvar = hb_memvarValueNew(); + hb_dynsymSetMemvar( pDynSym, pMemvar ); + } if( pValue ) { @@ -313,6 +334,16 @@ void hb_memvarUpdatePrivatesBase( void ) hb_stackGetPrivateStack()->base = hb_stackGetPrivateStack()->count; } +/* + * Reset PRIVATE base offset to the level of previous function + */ +static void hb_memvarResetPrivatesBase( void ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_memvarResetPrivatesBase()")); + + hb_stackGetPrivateStack()->base = hb_stackBaseItem()->item.asSymbol.stackstate->ulPrivateBase; +} + /* * This functions copies passed item value into the memvar pointed * by symbol @@ -1041,6 +1072,7 @@ HB_FUNC( __MVPRIVATE ) { int i; + hb_memvarResetPrivatesBase(); for( i = 1; i <= iCount; i++ ) { PHB_ITEM pMemvar = hb_param( i, HB_IT_ANY );