From c4ac523a2f6c8b6cdb4bec678841f6821383f54d Mon Sep 17 00:00:00 2001 From: Ryszard Glab Date: Sun, 1 Aug 1999 05:53:29 +0000 Subject: [PATCH] ChangeLog 19990801-07:45 --- harbour/ChangeLog | 66 ++++++++++++++ harbour/config/dos/watcom.cf | 5 ++ harbour/include/extend.h | 1 + harbour/include/rddapi.h | 1 + harbour/include/run_exp.h | 6 +- harbour/source/hbpp/table.c | 2 +- harbour/source/rdd/dbcmd.c | 2 +- harbour/source/rtl/dir.c | 52 +---------- harbour/source/rtl/inkey.c | 5 +- harbour/source/rtl/itemapi.c | 3 +- harbour/source/rtl/memvars.c | 149 ++++++++++++++++++++---------- harbour/source/rtl/strings.c | 58 ++++++++++++ harbour/source/runner/Makefile | 3 + harbour/source/runner/runner.c | 12 ++- harbour/source/vm/hvm.c | 159 +++++++++++++++++++-------------- 15 files changed, 350 insertions(+), 174 deletions(-) diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 7d814dae6a..24a0fdc52f 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -1,3 +1,69 @@ +19990801-07:45 GMT+2 Ryszard Glab + + *source/rtl/inkey.c + * added #include for Watcom section + + *source/vm/hvm.c + * the symbols are not scaned if there is no INIT/EXIT + procedure in the module (this is checked at the time of + symbol registration) + * _INITSTATICS function is called directly (by pointer) + instead of Do() function - it gives faster startup code + * removed calls for hb_ItemClear for uninitialized data + during startup code - these data have to be initialized + by assigning the IT_NIL value + - removed unnecessary calls for hb_itemClear in Push* + functions (the number of calls decreased almost 3 times) + * StackPop() clears now the last item on the stack + (it clreared the first free previously) + + added StackDec() that decrements the stack pointer but + doesn't clear the item (hb_itemClear() must be called + when this item is no longer needed) + * storing/restoring of private variables stack position moved + to VirtualMachine function + + *source/rtl/itemapi.c + + added checking for proper type before calling hb_itemClear + + *include/rddapi.h + * added forward declaration for _RDDFUNC struct + + *config/dos/watcom.cf + * changed to support new RDD directory structure + + *source/rdd/dbcmd.c + * removed #ifdef _MSC_VER that was placed before some + type casting - this type casting should be included for + all compilers + + *source/runner/runner.c + * corrected to properly call static variable initialization + function before other INIT functions + + *include/run_exp.h + + added symols: __MVPUBLIC, __MVPRIVATE + + *source/runner/Makefile + + added required libraries + + *include/extend.h + * added declaration for hb_strMatchRegExp() function + + *source/rtl/strings.c + * moved hb_strMatchDOS() function from rtl/dir.c + * added hb_strMatchRegExp() function (it calls hb_strMatchDOS + at this moment) + + *source/rtl/dir.c + * moved hb_strMatchDOS() function to rtl/strings.c + + *source/hbpp/table.c + * corrected entry for RELEASE command + + *source/rtl/memvars.c + * corrected __MVXRELEASE function used in RELEASE statement + + added __MVRELEASE function used in RELEASE ALL LIKE/EXCEPT + 19990801-00:15 EDT Paul Tucker * source/rtl/gtapi.c * hb_gtScroll() - call gtScroll if WIN_GTAPI diff --git a/harbour/config/dos/watcom.cf b/harbour/config/dos/watcom.cf index be3674a55d..3fd0bc4a38 100644 --- a/harbour/config/dos/watcom.cf +++ b/harbour/config/dos/watcom.cf @@ -36,6 +36,7 @@ define link_exe_file $(COMSPEC) /E:2048 /Cecho $(LDFLAGS) NAME $@ > __link__.tmp $(foreach file, $^, $(link_file)) $(foreach lib, $(LINKLIBS), $(link_lib)) +$(foreach lib, $(RDDLIBS), $(link_lib)) -$(LD) @__link__.tmp endef @@ -46,6 +47,10 @@ LINKLIBS := $(foreach lib, $(LIBS), $(subst /,\,$(TOP)$(ROOT)source/$(lib)/$(ARC else LINKLIBS := $(foreach lib, $(LIBS), $(subst /,\,$(HB_LIB_COMPILE)/$(lib))) endif +# If LIBS specifies the rdd library, add all DB drivers. +ifeq ($(findstring rdd,$(LIBS)),rdd) +RDDLIBS := $(foreach drv, $(HB_DB_DRIVERS), $(subst /,\,$(TOP)$(ROOT)source/rdd/$(drv)/$(ARCH)/$(drv))) +endif LD_RULE = $(link_exe_file) #Note: The empty line below HAVE TO exist! diff --git a/harbour/include/extend.h b/harbour/include/extend.h index 2cf549ce67..f838f6d197 100644 --- a/harbour/include/extend.h +++ b/harbour/include/extend.h @@ -300,6 +300,7 @@ PHB_ITEM hb_itemUnRef( PHB_ITEM pItem ); /* de-references passed variable */ char * hb_str( PHB_ITEM pNumber, PHB_ITEM pWidth, PHB_ITEM pDec ); /* convert number to string */ int hb_stricmp( const char *s1, const char *s2 ); BOOL hb_strempty( char * szText, ULONG ulLen ); +BOOL hb_strMatchRegExp( char * szString, char * szMask ); ULONG hb_strAt( char *, long, char *, long ); char * hb_strUpper( char * szText, long lLen ); char * hb_strLower( char * szText, long lLen ); diff --git a/harbour/include/rddapi.h b/harbour/include/rddapi.h index dce88f5468..4f5bcac7de 100644 --- a/harbour/include/rddapi.h +++ b/harbour/include/rddapi.h @@ -467,6 +467,7 @@ typedef FIELD * LPFIELD; * * Information to administrate the workarea */ +struct _RDDFUNCS; /* forward declaration */ typedef struct _AREA { diff --git a/harbour/include/run_exp.h b/harbour/include/run_exp.h index c7a102a417..75ff801f35 100644 --- a/harbour/include/run_exp.h +++ b/harbour/include/run_exp.h @@ -67,6 +67,8 @@ HARBOUR HB_TANH(); HARBOUR HB_TFILEREAD(); HARBOUR HB_TOCHAR(); HARBOUR HB_VALTYPE(); +HARBOUR HB___MVPUBLIC(); +HARBOUR HB___MVPRIVATE(); /* Same story. @@ -130,7 +132,9 @@ HB_INIT_SYMBOLS_BEGIN( RUNNER ) { "TANH", FS_PUBLIC, HB_TANH , 0 }, { "TFILEREAD", FS_PUBLIC, HB_TFILEREAD , 0 }, { "TOCHAR", FS_PUBLIC, HB_TOCHAR , 0 }, -{ "VALTYPE", FS_PUBLIC, HB_VALTYPE , 0 } +{ "VALTYPE", FS_PUBLIC, HB_VALTYPE , 0 }, +{ "__MVPUBLIC", FS_PUBLIC, HB___MVPUBLIC , 0 }, +{ "__MVPRIVATE", FS_PUBLIC, HB___MVPRIVATE , 0 } HB_INIT_SYMBOLS_END( RUNNER ); #if ! defined(__GNUC__) #pragma startup RUNNER diff --git a/harbour/source/hbpp/table.c b/harbour/source/hbpp/table.c index 7ea6f33b48..d07c917201 100644 --- a/harbour/source/hbpp/table.c +++ b/harbour/source/hbpp/table.c @@ -213,7 +213,7 @@ COMMANDS aCommands[] = {0,"SET","KEY \1A00 [TO]","SetKey( \1A00, NIL )"}, {0,"SET","FUNCTION \1A00 [TO] [\1B00]","__SetFunction( \1A00, \1B00 )"}, {0,"CLEAR","MEMORY","__MVClear()"}, - {0,"RELEASE","\1A10s","__MVXRelease( \1A20 )"}, + {0,"RELEASE"," \1A00","__MVXRelease( \1A30 )"}, {0,"RELEASE","ALL","__MVRelease('*', .t.)"}, {0,"RELEASE","ALL LIKE \1A00","__MVRelease( \1A10, .t. )"}, {0,"RELEASE","ALL EXCEPT \1A00","__MVRelease( \1A10, .f. )"}, diff --git a/harbour/source/rdd/dbcmd.c b/harbour/source/rdd/dbcmd.c index 6d7e04a5ce..941f2fbff6 100644 --- a/harbour/source/rdd/dbcmd.c +++ b/harbour/source/rdd/dbcmd.c @@ -328,7 +328,7 @@ ERRCODE hb_rddInherit( PRDDFUNCS pTable, PRDDFUNCS pSubTable, PRDDFUNCS pSuperTa { szDrvName = ( PBYTE ) hb_strUpper( ( char * ) szDrvName, strlen( ( const char * ) szDrvName ) ); if( !( pRddNode = hb_FindRddNode( (char *)szDrvName ) ) ) - return FAILURE; + return FAILURE; memcpy( pTable, &pRddNode->pTable, sizeof( RDDFUNCS ) ); } diff --git a/harbour/source/rtl/dir.c b/harbour/source/rtl/dir.c index 0893ae8d87..59bd4f631c 100644 --- a/harbour/source/rtl/dir.c +++ b/harbour/source/rtl/dir.c @@ -15,13 +15,6 @@ * */ -/* Harbour Project source code - http://www.Harbour-Project.org/ - The following function is Copyright 1999 Victor Szel : - hb_strMatchDOS(). - See doc/hdr_tpl.txt, Version 1.2 or later, for licensing terms. -*/ - #if defined(__IBMCPP__) #define INCL_DOSFILEMGR #define INCL_DOSERRORS @@ -146,8 +139,6 @@ HB_INIT_SYMBOLS_END( Dir__InitSymbols ); #pragma startup Dir__InitSymbols #endif -static BOOL hb_strMatchDOS (char *pszString, char *pszMask); - HARBOUR HB_DIRECTORY( void ) { @@ -320,7 +311,7 @@ HARBOUR HB_DIRECTORY( void ) printf("\n fname fext %s %s ",fname,fext); while(0==getchar()); */ - if (hb_strMatchDOS( fname,pfname) && hb_strMatchDOS( fext,pfext)) + if (hb_strMatchRegExp( fname,pfname) && hb_strMatchRegExp( fext,pfext)) { attrib = 0; aatrib[0] = '\0'; @@ -498,44 +489,3 @@ HARBOUR HB_DIRECTORY( void ) #endif #endif /* HAVE_POSIX_IO */ } - -static BOOL hb_strMatchDOS (char *pszString, char *pszMask) -{ - while (*pszMask && *pszString) - { - if (*pszMask == '*') - { - while (*pszMask == '*') - pszMask++; - if (!(*pszMask)) - return (TRUE); - else - if (*pszMask == '?') - pszString++; - else - { - while (toupper(*pszString) != toupper(*pszMask)) - { - if (!(*(++pszString))) - return (FALSE); - } - while (toupper(*pszString) == toupper(*pszMask)) - { - if (!(*(++pszString))) - break; - } - pszMask++; - } - } - else - if (toupper(*pszMask) != toupper(*pszString) && *pszMask != '?') - return (FALSE); - else - { - pszMask++; - pszString++; - } - } - return !((!(*pszString) && *pszMask && *pszMask != '*') || - (!(*pszMask) && *pszString)); -} diff --git a/harbour/source/rtl/inkey.c b/harbour/source/rtl/inkey.c index aa7e8f6c45..7a0e433fdf 100644 --- a/harbour/source/rtl/inkey.c +++ b/harbour/source/rtl/inkey.c @@ -53,6 +53,7 @@ #endif #ifdef __WATCOMC__ + #include #include #if defined(__386__) && !defined(__WINDOWS_386__) #define INT_86 int386 @@ -194,7 +195,7 @@ void hb_inkeyPoll( void ) /* Poll the console keyboard to stuff the Harbour int ch = 0; #if defined(__CYGWIN__) #elif defined(OS_DOS_COMPATIBLE) || defined(HARBOUR_GCC_OS2) || defined(__IBMCPP__) || defined(_Windows) - /* The reason for including _Windows here is that kbhit() and getch() appear + /* The reason for including _Windows here is that kbhit() and getch() appear to work properly in console mode. For true Windows mode, changes are needed. */ #if defined(HARBOUR_GCC_OS2) /* Read from the keyboard with no echo, no wait, and no SIGSEV on Ctrl-C */ @@ -501,7 +502,7 @@ HARBOUR HB_INKEY( void ) { /* Release the CPU between checks */ hb_releaseCPU(); - + /* Check for timeout */ if( !forever && clock() >= end_clock ) wait = FALSE; } diff --git a/harbour/source/rtl/itemapi.c b/harbour/source/rtl/itemapi.c index 2a49511667..cfdd07c368 100644 --- a/harbour/source/rtl/itemapi.c +++ b/harbour/source/rtl/itemapi.c @@ -429,7 +429,8 @@ void hb_itemClear( PHB_ITEM pItem ) void hb_itemCopy( PHB_ITEM pDest, PHB_ITEM pSource ) { - hb_itemClear( pDest ); + if( pDest->type ) + hb_itemClear( pDest ); if( pDest == pSource ) { diff --git a/harbour/source/rtl/memvars.c b/harbour/source/rtl/memvars.c index 6b1f26c083..04de373a45 100644 --- a/harbour/source/rtl/memvars.c +++ b/harbour/source/rtl/memvars.c @@ -41,10 +41,10 @@ #define VS_PRIVATE 64 #define VS_PUBLIC 128 -static PDYNSYM *_privateStack = NULL; +static PDYNSYM *_privateStack = NULL; static ULONG _privateStackSize = 0; static ULONG _privateStackCnt = 0; -static int _privateReleaseIgnore = FALSE; +static ULONG _privateStackBase = 0; static ULONG _globalTableSize = 0; static ULONG _globalFirstFree = 0; @@ -74,7 +74,7 @@ void hb_MemvarsInit( void ) _privateStack = (PDYNSYM *) hb_xgrab( sizeof(PDYNSYM) * TABLE_INITHB_VALUE ); _privateStackSize = TABLE_INITHB_VALUE; - _privateStackCnt = 0; + _privateStackCnt = _privateStackBase = 0; } @@ -192,9 +192,6 @@ HB_HANDLE hb_MemvarValueNew( HB_ITEM_PTR pSource, int iTrueMemvar ) return hValue; } -/* memcpy( &pValue->item, pSource, sizeof(HB_ITEM) );*/ - - /* * This function pushes passed dynamic symbol that belongs to PRIVATE variable * into the stack. The value will be popped from it if the variable falls @@ -222,7 +219,9 @@ static void hb_MemvarAddPrivate( PDYNSYM pDynSym ) */ ULONG hb_MemvarGetPrivatesBase( void ) { - return _privateStackCnt; + ULONG ulBase = _privateStackBase; + _privateStackBase =_privateStackCnt; + return ulBase; } /* @@ -233,24 +232,20 @@ void hb_MemvarSetPrivatesBase( ULONG ulBase ) { HB_HANDLE hVar, hOldValue; - /* Ignore it if it is requested after __PRIVATE function call - */ - if( !_privateReleaseIgnore ) - while( _privateStackCnt > ulBase ) - { - --_privateStackCnt; - hVar =_privateStack[ _privateStackCnt ]->hMemvar; - hOldValue =_globalTable[ hVar ].hPrevMemvar; - hb_MemvarValueDecRef( hVar ); - /* - * Restore previous value for variables that were overridden - */ - _privateStack[ _privateStackCnt ]->hMemvar =hOldValue; - } - _privateReleaseIgnore =FALSE; + while( _privateStackCnt > _privateStackBase ) + { + --_privateStackCnt; + hVar =_privateStack[ _privateStackCnt ]->hMemvar; + hOldValue =_globalTable[ hVar ].hPrevMemvar; + hb_MemvarValueDecRef( hVar ); + /* + * Restore previous value for variables that were overridden + */ + _privateStack[ _privateStackCnt ]->hMemvar =hOldValue; + } + _privateStackBase =ulBase; } - /* * This function increases the number of references to passed global value * @@ -484,34 +479,41 @@ static void hb_MemvarCreateFromDynSymbol( PDYNSYM pDynVar, BYTE bScope, PHB_ITEM pDynVar->hMemvar = hb_MemvarValueNew( pValue, TRUE ); _globalTable[ pDynVar->hMemvar ].hPrevMemvar =hCurrentValue; + /* Add this variable to the PRIVATE variables stack */ hb_MemvarAddPrivate( pDynVar ); } } -/* This function releases +/* This function releases all memory occupied by a memvar variable + * It also restores the value that was hidden if there is another + * PRIVATE variable with the same name. */ void hb_MemvarRelease( HB_ITEM_PTR pMemvar ) { - HB_HANDLE hVar, hOldValue; + ULONG ulBase = _privateStackCnt; PDYNSYM pDynVar; if( IS_STRING(pMemvar) ) { - pDynVar =hb_GetDynSym( pMemvar->item.asString.value ); - - if( pDynVar ) + /* Find the variable with a requested name that is currently visible + * Start from the top of the stack. + */ + while( ulBase > 0 ) { - hVar =pDynVar->hMemvar; - if( hVar ) + --ulBase; + pDynVar =_privateStack[ ulBase ]; + /* reset current value to NIL - the overriden variables will be + * visible after exit from current procedure + */ + if( pDynVar->hMemvar ) { - hOldValue =_globalTable[ hVar ].hPrevMemvar; - hb_MemvarValueDecRef( hVar ); - /* - * Restore previous value for variables that were overridden - */ - pDynVar->hMemvar =hOldValue; + if( hb_stricmp( pDynVar->pSymbol->szName, pMemvar->item.asString.value ) == 0 ) + { + hb_itemClear( &_globalTable[ pDynVar->hMemvar ].item ); + ulBase =0; + } } } } @@ -520,12 +522,42 @@ void hb_MemvarRelease( HB_ITEM_PTR pMemvar ) } -/**************************************************************************** +/* This function releases all memory occupied by a memvar variable and + * assigns NIL value - it releases variables created in current + * procedure only. + * The scope of released variables are specified using passed name's mask */ +void hb_MemvarReleaseWithMask( char *szMask, BOOL bInclude ) +{ + ULONG ulBase = _privateStackCnt; + PDYNSYM pDynVar; + + while( ulBase > _privateStackBase ) + { + --ulBase; + pDynVar =_privateStack[ ulBase ]; + /* reset current value to NIL - the overriden variables will be + * visible after exit from current procedure + */ + if( pDynVar->hMemvar ) + { + if( bInclude ) + { + if( (szMask[ 0 ] == '*') || hb_strMatchRegExp( pDynVar->pSymbol->szName, szMask ) ) + hb_itemClear( &_globalTable[ pDynVar->hMemvar ].item ); + } + else if( ! hb_strMatchRegExp( pDynVar->pSymbol->szName, szMask ) ) + hb_itemClear( &_globalTable[ pDynVar->hMemvar ].item ); + } + } +} + + +/* ************************************************************************** */ /* $DOC$ * $FUNCNAME$ - * __MVXPUBLIC() + * __MVPUBLIC() * $CATEGORY$ * Variable management * $ONELINER$ @@ -594,7 +626,7 @@ HARBOUR HB___MVPUBLIC( void ) /* $DOC$ * $FUNCNAME$ - * __MVXPRIVATE() + * __MVPRIVATE() * $CATEGORY$ * Variable management * $ONELINER$ @@ -634,11 +666,6 @@ HARBOUR HB___MVPRIVATE( void ) if( iCount ) { - /* We will create PRIVATE variables here then do not release them - * on exit from this function - */ - _privateReleaseIgnore =TRUE; - for( i=1; i<=iCount; i++ ) { pMemvar =hb_param( i, IT_ANY ); @@ -683,6 +710,12 @@ HARBOUR HB___MVPRIVATE( void ) * $DESCRIPTION$ * This function releases values stored in memory variable. It shouldn't * be called directly, rather it should be placed into RELEASE command. + * If the released variable is a PRIVATE variable then previously hidden + * variable with the same name becomes visible (after exit from the + * procedure where released variable was created). + * + * It releases variable even if this variable was created in different + * procedure * $EXAMPLES$ * * $TESTS$ @@ -735,20 +768,22 @@ HARBOUR HB___MVXRELEASE( void ) * $CATEGORY$ * Variable management * $ONELINER$ - * This function releases value stored in PRIVATE or PUBLIC variable + * This function releases PRIVATE variables created in current procedure * $SYNTAX$ * __MVRELEASE( , ) * $ARGUMENTS$ * = string that contains the wildcard mask for variables' names * that will be released. Supported wildcards: '*' and '?' * = logical value that specifies if variables - * mathing passed skeleton should be either included in deletion (if .T.) - * or excluded from deletion (if .F.) + * that match passed skeleton should be either included in deletion + * (if .T.) or excluded from deletion (if .F.) * $RETURNS$ * Nothing * $DESCRIPTION$ * This function releases values stored in memory variables. It shouldn't * be called directly, it should be placed into RELEASE ALL command. + * If released variable is a PRIVATE variable then the NIL is assigned. + * PUBLIC variables are not changed. * $EXAMPLES$ * * $TESTS$ @@ -763,4 +798,24 @@ HARBOUR HB___MVXRELEASE( void ) */ HARBOUR HB___MVRELEASE( void ) { + int iCount = hb_pcount(); + PHB_ITEM pMask; + + if( iCount ) + { + pMask =hb_param( 1, IT_STRING ); + if( pMask ) + { + BOOL bIncludeVar; + + if( iCount > 1 ) + bIncludeVar =hb_parl( 2 ); + else + bIncludeVar =TRUE; + + if( pMask->item.asString.value[ 0 ] == '*' ) + bIncludeVar =TRUE; /* delete all memvar variables */ + hb_MemvarReleaseWithMask( pMask->item.asString.value, bIncludeVar ); + } + } } diff --git a/harbour/source/rtl/strings.c b/harbour/source/rtl/strings.c index c421ddad78..f20e2ba830 100644 --- a/harbour/source/rtl/strings.c +++ b/harbour/source/rtl/strings.c @@ -147,6 +147,64 @@ int hb_stricmp( const char *s1, const char *s2 ) return rc; } + +/* Harbour Project source code + http://www.Harbour-Project.org/ + The following function is Copyright 1999 Victor Szel : + hb_strMatchDOS(). + See doc/hdr_tpl.txt, Version 1.2 or later, for licensing terms. +*/ + +static BOOL hb_strMatchDOS (char *pszString, char *pszMask) +{ + while (*pszMask && *pszString) + { + if (*pszMask == '*') + { + while (*pszMask == '*') + pszMask++; + if (!(*pszMask)) + return (TRUE); + else + if (*pszMask == '?') + pszString++; + else + { + while (toupper(*pszString) != toupper(*pszMask)) + { + if (!(*(++pszString))) + return (FALSE); + } + while (toupper(*pszString) == toupper(*pszMask)) + { + if (!(*(++pszString))) + break; + } + pszMask++; + } + } + else + if (toupper(*pszMask) != toupper(*pszString) && *pszMask != '?') + return (FALSE); + else + { + pszMask++; + pszString++; + } + } + return !((!(*pszString) && *pszMask && *pszMask != '*') || + (!(*pszMask) && *pszString)); +} + +/* TODO: Replace it with a code that supports real regular expressions + * + */ +BOOL hb_strMatchRegExp( char *szString, char *szMask ) +{ + return hb_strMatchDOS( szString, szMask ); +} + + /* determines if first char of string is letter */ /* TEST: QOUT( "isalpha( 'hello' ) = ", isalpha( 'hello' ) ) */ /* TEST: QOUT( "isalpha( '12345' ) = ", isalpha( '12345' ) ) */ diff --git a/harbour/source/runner/Makefile b/harbour/source/runner/Makefile index 5feb224a62..8e41e71de3 100644 --- a/harbour/source/runner/Makefile +++ b/harbour/source/runner/Makefile @@ -9,5 +9,8 @@ C_SOURCES=\ C_MAIN=runner.c LIBS=\ + vm \ + rtl \ + tools \ include $(TOP)$(ROOT)config/bin.cf diff --git a/harbour/source/runner/runner.c b/harbour/source/runner/runner.c index e185f931b0..9e0973f0a4 100644 --- a/harbour/source/runner/runner.c +++ b/harbour/source/runner/runner.c @@ -217,9 +217,19 @@ HARBOUR HB_HB_RUN( void ) ProcessSymbols( pSymRead, ulSymbols ); + /* Initialize static variables first + */ for( ul = 0; ul < ulSymbols; ul++ ) /* Check INIT functions */ { - if( pSymRead[ ul ].cScope & FS_INIT ) + if( (pSymRead[ ul ].cScope & (FS_INIT|FS_EXIT)) == (FS_INIT|FS_EXIT) ) + { + if( pSymRead[ ul ].pFunPtr ) + pSymRead[ ul ].pFunPtr(); + } + } + for( ul = 0; ul < ulSymbols; ul++ ) /* Check INIT functions */ + { + if( (pSymRead[ ul ].cScope & (FS_INIT|FS_EXIT)) == FS_INIT ) { PushSymbol( pSymRead + ul ); PushNil(); diff --git a/harbour/source/vm/hvm.c b/harbour/source/vm/hvm.c index b6d1e169d9..57ca3a2883 100644 --- a/harbour/source/vm/hvm.c +++ b/harbour/source/vm/hvm.c @@ -83,7 +83,6 @@ void Inc( void ); /* increment the latest numeric value on the stack void Instring( void ); /* check whether string 1 is contained in string 2 */ void Less( void ); /* checks if the latest - 1 value is less than the latest, removes both and leaves result */ void LessEqual( void ); /* checks if the latest - 1 value is less than or equal the latest, removes both and leaves result */ -void Line( WORD wLine ); /* keeps track of the currently processed PRG line */ void Message( PSYMBOL pSymMsg ); /* sends a message to an object */ void Minus( void ); /* substracts the latest two values on the stack, removes them and leaves the result */ void Modulus( void ); /* calculates the modulus of latest two values on the stack, removes them and leaves the result */ @@ -130,6 +129,7 @@ typedef struct _SYMBOLS PSYMBOL pModuleSymbols; /* pointer to a one module own symbol table */ WORD wModuleSymbols; /* number of symbols on that table */ struct _SYMBOLS * pNext;/* pointer to the next SYMBOLS structure */ + SYMBOLSCOPE hScope; /* scope collected from all symbols in module used to speed initialization code */ } SYMBOLS, * PSYMBOLS; /* structure to keep track of all modules symbol tables */ void ProcessSymbols( PSYMBOL pSymbols, WORD wSymbols ); /* statics symbols initialization */ @@ -142,6 +142,7 @@ void ReleaseLocalSymbols( void ); /* releases the memory of the local symbols l void hb_ReleaseDynamicSymbols( void ); /* releases the memory of the dynamic symbol table */ /* stack management functions */ +void StackDec( void ); /* pops an item from the stack without clearing it's contents */ void StackPop( void ); /* pops an item from the stack */ void StackFree( void ); /* releases all memory used by the stack */ void StackPush( void ); /* pushes an item on to the stack */ @@ -209,9 +210,10 @@ BYTE bErrorLevel = 0; /* application exit errorlevel */ HB_DEBUG( "main\n" ); - hb_itemClear( &aStatics ); - hb_itemClear( &errorBlock ); - hb_itemClear( &stack.Return ); + /* initialize internal data structures */ + aStatics.type = IT_NIL; + errorBlock.type = IT_NIL; + stack.Return.type = IT_NIL; StackInit(); hb_NewDynSym( &symEval ); /* initialize dynamic symbol for evaluating codeblocks */ @@ -284,6 +286,7 @@ void VirtualMachine( PBYTE pCode, PSYMBOL pSymbols ) { BYTE bCode; WORD w = 0, wParams, wSize; + ULONG ulPrivateBase = hb_MemvarGetPrivatesBase(); HB_DEBUG( "VirtualMachine\n" ); @@ -430,7 +433,7 @@ void VirtualMachine( PBYTE pCode, PSYMBOL pSymbols ) break; case HB_P_LINE: - Line( pCode[ w + 1 ] + ( pCode[ w + 2 ] * 256 ) ); + stack.pBase->item.asSymbol.lineno = pCode[ w + 1 ] + ( pCode[ w + 2 ] * 256 ); w += 3; break; @@ -630,6 +633,7 @@ void VirtualMachine( PBYTE pCode, PSYMBOL pSymbols ) break; } } + hb_MemvarSetPrivatesBase( ulPrivateBase ); HB_DEBUG( "EndProc\n" ); } @@ -730,7 +734,6 @@ void Do( WORD wParams ) PHB_ITEM pSelf = stack.pPos - wParams - 1; /* NIL, OBJECT or BLOCK */ HARBOURFUNC pFunc; int iStatics = stack.iStatics; /* Return iStatics position */ - ULONG ulPrivateBase = hb_MemvarGetPrivatesBase(); if( ! IS_SYMBOL( pItem ) ) { @@ -784,7 +787,6 @@ void Do( WORD wParams ) stack.pBase = stack.pItems + wStackBase; stack.iStatics = iStatics; - hb_MemvarSetPrivatesBase( ulPrivateBase ); } HARBOUR DoBlock( void ) @@ -857,8 +859,9 @@ HARBOUR HB_EVAL( void ) void EndBlock( void ) { - StackPop(); - hb_itemCopy( &stack.Return, stack.pPos ); + StackDec(); /* make the last item visible */ + hb_itemCopy( &stack.Return, stack.pPos ); /* copy it */ + hb_itemClear( stack.pPos ); /* and now clear it */ HB_DEBUG( "EndBlock\n" ); } @@ -1230,12 +1233,6 @@ void Message( PSYMBOL pSymMsg ) /* sends a message to an object */ HB_DEBUG2( "Message: %s\n", pSymMsg->szName ); } -void Line( WORD wLine ) -{ - stack.pBase->item.asSymbol.lineno = wLine; - HB_DEBUG( "line\n" ); -} - void Negate( void ) { if( IS_INTEGER( stack.pPos - 1 ) ) @@ -1267,8 +1264,8 @@ void NotEqual( void ) if( IS_NIL( pItem1 ) && IS_NIL( pItem2 ) ) { - StackPop(); - StackPop(); + StackDec(); + StackDec(); PushLogical( 0 ); } @@ -1398,8 +1395,8 @@ void Or( void ) if( IS_LOGICAL( pItem1 ) && IS_LOGICAL( pItem2 ) ) { iResult = pItem1->item.asLogical.value || pItem2->item.asLogical.value; - StackPop(); - StackPop(); + StackDec(); stack.pPos->type =IT_NIL; + StackDec(); PushLogical( iResult ); } else @@ -1466,10 +1463,13 @@ void Plus( void ) long PopDate( void ) { - StackPop(); + StackDec(); if( IS_DATE( stack.pPos ) ) + { + stack.pPos->type =IT_NIL; return stack.pPos->item.asDate.value; + } else { printf( "incorrect item value trying to Pop a date value\n" ); @@ -1483,8 +1483,7 @@ double PopDouble( WORD *pwDec ) { double d; - StackPop(); - + StackDec(); switch( stack.pPos->type & ~IT_BYREF ) { case IT_INTEGER: @@ -1507,6 +1506,7 @@ double PopDouble( WORD *pwDec ) exit( 1 ); d = 0; } + stack.pPos->type =IT_NIL; HB_DEBUG( "PopDouble\n" ); return d; } @@ -1515,7 +1515,7 @@ void PopLocal( SHORT iLocal ) { PHB_ITEM pLocal; - StackPop(); + StackDec(); if( iLocal >= 0 ) { @@ -1538,10 +1538,13 @@ void PopLocal( SHORT iLocal ) int PopLogical( void ) { - StackPop(); + StackDec(); if( IS_LOGICAL( stack.pPos ) ) + { + stack.pPos->type =IT_NIL; return stack.pPos->item.asLogical.value; + } else { hb_errorRT_BASE(EG_ARG, 1066, NULL, hb_errorNatDescription(EG_CONDITION)); @@ -1551,7 +1554,7 @@ int PopLogical( void ) void PopMemvar( PSYMBOL pSym ) { - StackPop(); + StackDec(); hb_MemvarSetValue( pSym, stack.pPos ); hb_itemClear( stack.pPos ); HB_DEBUG( "PopMemvar\n" ); @@ -1562,7 +1565,7 @@ double PopNumber( void ) PHB_ITEM pItem = stack.pPos - 1; double dNumber; - StackPop(); + StackDec(); switch( pItem->type & ~IT_BYREF ) { @@ -1583,6 +1586,7 @@ double PopNumber( void ) exit( 1 ); break; } + stack.pPos->type =IT_NIL; return dNumber; } @@ -1596,7 +1600,7 @@ void PopStatic( WORD wStatic ) { PHB_ITEM pStatic; - StackPop(); + StackDec(); pStatic = aStatics.item.asArray.value->pItems + stack.iStatics + wStatic - 1; if( IS_BYREF( pStatic ) ) @@ -1619,7 +1623,6 @@ void Power( void ) void PushLogical( int iTrueFalse ) { - hb_itemClear( stack.pPos ); stack.pPos->type = IT_LOGICAL; stack.pPos->item.asLogical.value = iTrueFalse; StackPush(); @@ -1651,7 +1654,6 @@ void PushLocal( SHORT iLocal ) void PushLocalByRef( SHORT iLocal ) { - hb_itemClear( stack.pPos ); stack.pPos->type = IT_BYREF; /* we store its stack offset instead of a pointer to support a dynamic stack */ stack.pPos->item.asRefer.value = iLocal; @@ -1664,7 +1666,6 @@ void PushLocalByRef( SHORT iLocal ) void PushMemvar( PSYMBOL pSym ) { - hb_itemClear( stack.pPos ); hb_MemvarGetValue( stack.pPos, pSym ); StackPush(); HB_DEBUG( "PushMemvar\n" ); @@ -1672,7 +1673,6 @@ void PushMemvar( PSYMBOL pSym ) void PushMemvarByRef( PSYMBOL pSym ) { - hb_itemClear( stack.pPos ); hb_MemvarGetRefer( stack.pPos, pSym ); StackPush(); HB_DEBUG( "PushMemvar\n" ); @@ -1680,7 +1680,7 @@ void PushMemvarByRef( PSYMBOL pSym ) void PushNil( void ) { - hb_itemClear( stack.pPos ); + stack.pPos->type =IT_NIL; StackPush(); HB_DEBUG( "PushNil\n" ); } @@ -1715,7 +1715,6 @@ void PushStatic( WORD wStatic ) void PushStaticByRef( WORD wStatic ) { - hb_itemClear( stack.pPos ); stack.pPos->type = IT_BYREF; /* we store the offset instead of a pointer to support a dynamic stack */ stack.pPos->item.asRefer.value = wStatic -1; @@ -1733,7 +1732,6 @@ void PushString( char * szText, ULONG length ) memcpy (szTemp, szText, length); szTemp[ length ] = 0; - hb_itemClear( stack.pPos ); stack.pPos->type = IT_STRING; stack.pPos->item.asString.length = length; stack.pPos->item.asString.value = szTemp; @@ -1743,7 +1741,6 @@ void PushString( char * szText, ULONG length ) void PushSymbol( PSYMBOL pSym ) { - hb_itemClear( stack.pPos ); stack.pPos->type = IT_SYMBOL; stack.pPos->item.asSymbol.value = pSym; stack.pPos->item.asSymbol.stackbase = stack.pPos - stack.pItems; @@ -1768,7 +1765,6 @@ void PushBlock( BYTE * pCode, PSYMBOL pSymbols ) { WORD wLocals; - hb_itemClear( stack.pPos ); stack.pPos->type = IT_BLOCK; wLocals =pCode[ 5 ] + ( pCode[ 6 ] * 256 ); @@ -1793,7 +1789,6 @@ void PushBlock( BYTE * pCode, PSYMBOL pSymbols ) void PushDate( LONG lDate ) { - hb_itemClear( stack.pPos ); stack.pPos->type = IT_DATE; stack.pPos->item.asDate.value = lDate; StackPush(); @@ -1802,7 +1797,6 @@ void PushDate( LONG lDate ) void PushDouble( double dNumber, WORD wDec ) { - hb_itemClear( stack.pPos ); stack.pPos->type = IT_DOUBLE; stack.pPos->item.asDouble.value = dNumber; if( dNumber >= 10000000000.0 ) stack.pPos->item.asDouble.length = 20; @@ -1814,7 +1808,6 @@ void PushDouble( double dNumber, WORD wDec ) void PushInteger( int iNumber ) { - hb_itemClear( stack.pPos ); stack.pPos->type = IT_INTEGER; stack.pPos->item.asInteger.value = iNumber; stack.pPos->item.asInteger.length = 10; @@ -1825,7 +1818,6 @@ void PushInteger( int iNumber ) void PushLong( long lNumber ) { - hb_itemClear( stack.pPos ); stack.pPos->type = IT_LONG; stack.pPos->item.asLong.value = lNumber; stack.pPos->item.asLong.length = 10; @@ -1836,15 +1828,25 @@ void PushLong( long lNumber ) void RetValue( void ) { - StackPop(); - hb_itemCopy( &stack.Return, stack.pPos ); + StackDec(); /* make the last item visible */ + hb_itemCopy( &stack.Return, stack.pPos ); /* copy it */ + hb_itemClear( stack.pPos ); /* now clear it */ HB_DEBUG( "RetValue\n" ); } void StackPop( void ) { - hb_itemClear( stack.pPos ); + if( --stack.pPos < stack.pItems ) + { + printf( "runtime error: stack underflow\n" ); + exit( 1 ); + } + if( stack.pPos->type ) + hb_itemClear( stack.pPos ); +} +void StackDec( void ) +{ if( --stack.pPos < stack.pItems ) { printf( "runtime error: stack underflow\n" ); @@ -1988,6 +1990,8 @@ void ProcessSymbols( PSYMBOL pModuleSymbols, WORD wModuleSymbols ) /* module sym { PSYMBOLS pNewSymbols, pLastSymbols; WORD w; + SYMBOLSCOPE hSymScope; + #ifdef HARBOUR_OBJ_GENERATION static int iObjChecked = 0; @@ -2002,6 +2006,7 @@ void ProcessSymbols( PSYMBOL pModuleSymbols, WORD wModuleSymbols ) /* module sym pNewSymbols->pModuleSymbols = pModuleSymbols; pNewSymbols->wModuleSymbols = wModuleSymbols; pNewSymbols->pNext = 0; + pNewSymbols->hScope =0; if( ! pSymbols ) pSymbols = pNewSymbols; @@ -2015,11 +2020,12 @@ void ProcessSymbols( PSYMBOL pModuleSymbols, WORD wModuleSymbols ) /* module sym for( w = 0; w < wModuleSymbols; w++ ) /* register each public symbol on the dynamic symbol table */ { - if( ( ! pSymStart ) && ( ( pModuleSymbols + w )->cScope == FS_PUBLIC ) ) + hSymScope =( pModuleSymbols + w )->cScope; + pNewSymbols->hScope |=hSymScope; + if( ( ! pSymStart ) && ( hSymScope == FS_PUBLIC ) ) pSymStart = pModuleSymbols + w; /* first public defined symbol to start execution */ - if( ( ( pModuleSymbols + w )->cScope == FS_PUBLIC ) || - ( ( pModuleSymbols + w )->cScope & ( FS_MESSAGE | FS_MEMVAR ) ) ) + if( (hSymScope == FS_PUBLIC) || (hSymScope & ( FS_MESSAGE | FS_MEMVAR )) ) hb_NewDynSym( pModuleSymbols + w ); } } @@ -2067,14 +2073,23 @@ void DoInitStatics( void ) SYMBOLSCOPE scope; do { - for( w = 0; w < pLastSymbols->wModuleSymbols; w++ ) + if( (pLastSymbols->hScope & (FS_INIT | FS_EXIT)) == (FS_INIT | FS_EXIT) ) { - scope =( pLastSymbols->pModuleSymbols + w )->cScope & (FS_EXIT | FS_INIT); - if( scope == (FS_INIT | FS_EXIT) ) + for( w = 0; w < pLastSymbols->wModuleSymbols; w++ ) { - PushSymbol( pLastSymbols->pModuleSymbols + w ); - PushNil(); - Do( 0 ); + scope =( pLastSymbols->pModuleSymbols + w )->cScope & (FS_EXIT | FS_INIT); + if( scope == (FS_INIT | FS_EXIT) ) + { + /* _INITSTATICS procedure cannot call any function and it + * cannot use any local variable then it is safe to call + * this procedure directly + * PushSymbol( pLastSymbols->pModuleSymbols + w ); + * PushNil(); + * Do( 0 ); + */ + if( ( pLastSymbols->pModuleSymbols + w )->pFunPtr ) + ( pLastSymbols->pModuleSymbols + w )->pFunPtr(); + } } } pLastSymbols = pLastSymbols->pNext; @@ -2088,14 +2103,17 @@ void DoExitFunctions( void ) SYMBOLSCOPE scope; do { - for( w = 0; w < pLastSymbols->wModuleSymbols; w++ ) - { - scope =( pLastSymbols->pModuleSymbols + w )->cScope & (FS_EXIT | FS_INIT); - if( scope == FS_EXIT ) + if( pLastSymbols->hScope & FS_EXIT ) + { /* only if module contains some EXIT functions */ + for( w = 0; w < pLastSymbols->wModuleSymbols; w++ ) { - PushSymbol( pLastSymbols->pModuleSymbols + w ); - PushNil(); - Do( 0 ); + scope =( pLastSymbols->pModuleSymbols + w )->cScope & (FS_EXIT | FS_INIT); + if( scope == FS_EXIT ) + { + PushSymbol( pLastSymbols->pModuleSymbols + w ); + PushNil(); + Do( 0 ); + } } } pLastSymbols = pLastSymbols->pNext; @@ -2109,20 +2127,23 @@ void DoInitFunctions( int argc, char * argv[] ) SYMBOLSCOPE scope; do { - for( w = 0; w < pLastSymbols->wModuleSymbols; w++ ) - { - scope =( pLastSymbols->pModuleSymbols + w )->cScope & (FS_EXIT | FS_INIT); - if( scope == FS_INIT ) + if( pLastSymbols->hScope & FS_INIT ) + { /* only if module contains some INIT functions */ + for( w = 0; w < pLastSymbols->wModuleSymbols; w++ ) { - int i; + scope =( pLastSymbols->pModuleSymbols + w )->cScope & (FS_EXIT | FS_INIT); + if( scope == FS_INIT ) + { + int i; - PushSymbol( pLastSymbols->pModuleSymbols + w ); - PushNil(); + PushSymbol( pLastSymbols->pModuleSymbols + w ); + PushNil(); - for( i = 1; i < argc; i++ ) /* places application parameters on the stack */ - PushString( argv[ i ], strlen( argv[ i ] ) ); + for( i = 1; i < argc; i++ ) /* places application parameters on the stack */ + PushString( argv[ i ], strlen( argv[ i ] ) ); - Do( argc - 1 ); + Do( argc - 1 ); + } } } pLastSymbols = pLastSymbols->pNext;