diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 9b7ce68847..ec3c7cb472 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -1,3 +1,39 @@ +19990828-14:00 GMT+1 Victor Szel + + * source/rtl/filesys.c + source/hbpp/stdalone/hbpp.c + source/compiler/harbour.y + include/hbsetup.h + include/hbpp.h + ! hb_fsFNameSplit() fixed handling of colon in filenames. + (reported by Bruno Cantero) + * source/compiler/harbour.y + ! Fixed the name format of the generated symbol registration function, + since it was causing a compiler error where the .prg name begun with + a number ( for example: 1.prg ). The new format is: hb_vm_SymbolInit_*() + * include/ctoharb.h + source/rtl/errorapi.c + source/vm/hvm.c + + hb_errLaunch() and hb_errLaunchSubst() finished + (the latter not yet tested). + Thanks to Ryszard Glab. + * include/ctoharb.h + source/vm/hvm.c + source/vm/initsymb.c + * hb_vmRTSymbolsInit() -> hb_vmSymbolInit_RT + * include/hbsetup.h + include/hbpp.h + + Changed OPT_DELIMITER to OS_OPT_DELIMITER_LIST and moved to hbsetup.h + So now it's multiplatform. + * source/rtl/mouse/mousedos.c + + hb_mouse_IsButtonPressed() added by Luiz Rafael Culik. + (small fixes applied, code not tested) + * include/hbdefs.h + ! LOBYTE(),HIBYTE(),LOWORD() put in #ifndef guards. + (reported by Jon Berg) + * tests/working/fileio.prg + + Some tests added. + 19990828-08:40 GMT+1 Antonio Linares * source/vm/hvm.c * Fixed hb_vmDebuggerEndProc() @@ -36,7 +72,7 @@ * source/debug/tbrwtext.prg * small fixes. -19990826-06:50 GMT+1 Victor Szel +19990827-06:50 GMT+1 Victor Szel * source/rtl/inkey.c include/inkey.h @@ -50,7 +86,7 @@ * hb_inkeyPoll() now calls hb_inkeyPut() to insert the new code. ! INKEY() fixed parameter count checking bug introduced a few hours ago. -19990826-06:00 GMT+1 Victor Szel +19990827-06:00 GMT+1 Victor Szel * include/mouseapi.h source/rtl/mouseapi.c @@ -67,7 +103,7 @@ Non-GNU make file users should add the new files source/rtl/mouseapi.c and source/rtl/mouse/mousedos.c file to their make system. -19990826-05:00 GMT+1 Victor Szel +19990827-05:00 GMT+1 Victor Szel * include/Makefile include/mouseapi.h diff --git a/harbour/include/ctoharb.h b/harbour/include/ctoharb.h index 2aed1ed89d..f60d124b95 100644 --- a/harbour/include/ctoharb.h +++ b/harbour/include/ctoharb.h @@ -34,7 +34,13 @@ extern void hb_vmExecute( BYTE * pCode, PHB_SYMB pSymbols ); /* invokes the extern void hb_vmProcessSymbols( PHB_SYMB pSymbols, WORD wSymbols ); /* statics symbols initialization */ extern void hb_vmRequestQuit( void ); extern void hb_vmRequestBreak( PHB_ITEM pItem ); -extern void hb_vmRTSymbolsInit( void ); /* initialization of runtime support symbols */ +extern WORD hb_vmRequestQuery( void ); +extern void hb_vmQuit( void ); /* Immediately quits the virtual machine */ +extern void hb_vmSymbolInit_RT( void ); /* initialization of runtime support symbols */ + +/* Return values of hb_vmRequestQuery() */ +#define HB_QUIT_REQUESTED 1 /* immediately quit the application */ +#define HB_BREAK_REQUESTED 2 /* break to nearest RECOVER/END sequence */ /* PCode functions */ extern void hb_vmAnd( void ); /* performs the logical AND on the latest two values, removes them and leaves result on the stack */ diff --git a/harbour/include/hbdefs.h b/harbour/include/hbdefs.h index db9fe8d666..5aedc1fde8 100644 --- a/harbour/include/hbdefs.h +++ b/harbour/include/hbdefs.h @@ -65,9 +65,15 @@ typedef unsigned long DWORD; #define FALSE 0 #define TRUE 1 +#ifndef LOBYTE #define LOBYTE( w ) ( ( BYTE )( w ) ) +#endif +#ifndef HIBYTE #define HIBYTE( w ) ( ( BYTE )( ( ( WORD )( w ) >> 8 ) & 0xFF ) ) +#endif +#ifndef LOWORD #define LOWORD( l ) ( ( WORD )( l ) ) +#endif #endif /* HB_DONT_DEFINE_BASIC_TYPES */ #endif /* __IBMCPP__ */ diff --git a/harbour/include/hbpp.h b/harbour/include/hbpp.h index d75c761a7a..ea678eb812 100644 --- a/harbour/include/hbpp.h +++ b/harbour/include/hbpp.h @@ -38,13 +38,8 @@ typedef struct _COMMANDS #define STR_SIZE 8192 #define BUFF_SIZE 2048 -#define SKIPTABSPACES(sptr) while ( *sptr == ' ' || *sptr == '\t' ) (sptr)++ - -/* TODO: #define this for various platforms */ -#define PATH_DELIMITER "/\\" -#define IS_PATH_SEP( c ) (strchr(PATH_DELIMITER, (c))!=NULL) -#define OPT_DELIMITER "/-" -#define IS_OPT_SEP( c ) (strchr(OPT_DELIMITER, (c))!=NULL) +#define SKIPTABSPACES( sptr ) while ( *sptr == ' ' || *sptr == '\t' ) ( sptr )++ +#define IS_OPT_SEP( c ) ( strchr( OS_OPT_DELIMITER_LIST, ( c ) ) != NULL ) /* HBPP.C exported functions */ diff --git a/harbour/include/hbsetup.h b/harbour/include/hbsetup.h index eede684bcc..cc1bdce988 100644 --- a/harbour/include/hbsetup.h +++ b/harbour/include/hbsetup.h @@ -46,8 +46,8 @@ * in run-time support modules and in user defined modules. * If strict ANSI C compability is required then all symbol tables * have to be joined manually by calling special function named - * __InitSymbols - * (for example for myfirst.prg it will be: 'MYFIRST__InitSymbols' + * hb_vm_SymbolInit_ + * (for example for myfirst.prg it will be: 'hb_vm_SymbolInit_MYFIRST' * The generation of this function is performed by the macro called * HB_CALL_ON_STARTUP that is defined in 'init.h' * @@ -74,9 +74,9 @@ * By default we are using automatic lookup (symbol not defined) */ #if defined(__WATCOMC__) || defined(__GNUC__) - #if !defined(__DJGPP__) && !defined(HARBOUR_GCC_OS2) - #define HARBOUR_START_PROCEDURE "MAIN" - #endif + #if !defined(__DJGPP__) && !defined(HARBOUR_GCC_OS2) + #define HARBOUR_START_PROCEDURE "MAIN" + #endif #endif /* *********************************************************************** @@ -115,7 +115,7 @@ /* Indicate that one of the GTAPIs is defined */ #if defined(HARBOUR_USE_DOS_GTAPI) || defined(HARBOUR_USE_OS2_GTAPI) || defined(HARBOUR_USE_WIN_GTAPI) - #define HARBOUR_USE_GTAPI + #define HARBOUR_USE_GTAPI #endif /* *********************************************************************** @@ -137,22 +137,28 @@ * Operating system specific definitions */ #ifdef __GNUC__ - /* The GNU C compiler is used */ - #if defined(__DJGPP__) || defined(HARBOUR_GCC_OS2) || defined(_Windows) || defined(_WIN32) - /* The DJGPP port of GNU C is used - for DOS platform */ - #define OS_PATH_LIST_SEPARATOR ';' - #define OS_PATH_DELIMITER '\\' - #define OS_DOS_COMPATIBLE - #else - #define OS_PATH_LIST_SEPARATOR ':' - #define OS_PATH_DELIMITER '/' - #define OS_UNIX_COMPATIBLE - #endif + /* The GNU C compiler is used */ + #if defined(__DJGPP__) || defined(HARBOUR_GCC_OS2) || defined(_Windows) || defined(_WIN32) + /* The DJGPP port of GNU C is used - for DOS platform */ + #define OS_DOS_COMPATIBLE + #define OS_PATH_LIST_SEPARATOR ';' + #define OS_PATH_DELIMITER '\\' + #define OS_PATH_DELIMITER_LIST "\\/:" + #define OS_OPT_DELIMITER_LIST "/-" + #else + #define OS_UNIX_COMPATIBLE + #define OS_PATH_LIST_SEPARATOR ':' + #define OS_PATH_DELIMITER '/' + #define OS_PATH_DELIMITER_LIST "/" + #define OS_OPT_DELIMITER_LIST "-" + #endif #else - /* we are assuming here the DOS compatible OS */ - #define OS_PATH_LIST_SEPARATOR ';' - #define OS_PATH_DELIMITER '\\' - #define OS_DOS_COMPATIBLE + /* we are assuming here the DOS compatible OS */ + #define OS_DOS_COMPATIBLE + #define OS_PATH_LIST_SEPARATOR ';' + #define OS_PATH_DELIMITER '\\' + #define OS_PATH_DELIMITER_LIST "\\/:" + #define OS_OPT_DELIMITER_LIST "/-" #endif /* *********************************************************************** @@ -160,27 +166,27 @@ */ #ifndef DOS -#if defined(_QC) || defined(__DOS__) || defined(MSDOS) || defined(__MSDOS__) -#define DOS -#endif + #if defined(_QC) || defined(__DOS__) || defined(MSDOS) || defined(__MSDOS__) + #define DOS + #endif #endif #ifndef OS2 -#if defined(__OS2__) || defined(OS_2) || defined(HARBOUR_GCC_OS2) -#define OS2 -#endif + #if defined(__OS2__) || defined(OS_2) || defined(HARBOUR_GCC_OS2) + #define OS2 + #endif #endif #ifndef EMX -#if defined(__EMX__) -#define EMX -#endif + #if defined(__EMX__) + #define EMX + #endif #endif #ifndef WINNT -#if defined(__NT__) -#define WINNT -#endif + #if defined(__NT__) + #define WINNT + #endif #endif #endif /* HB_SETUP_H_ */ diff --git a/harbour/source/compiler/harbour.y b/harbour/source/compiler/harbour.y index 6e19a52d61..5a67f76c83 100644 --- a/harbour/source/compiler/harbour.y +++ b/harbour/source/compiler/harbour.y @@ -2336,7 +2336,7 @@ void GenCCode( char *szFileName, char *szName ) /* generates the C languag /* Generate the wrapper that will initialize local symbol table */ yy_strupr( _pFileName->szName ); - fprintf( yyc, "\n\nHB_INIT_SYMBOLS_BEGIN( %s__InitSymbols )\n", _pFileName->szName ); + fprintf( yyc, "\n\nHB_INIT_SYMBOLS_BEGIN( hb_vm_SymbolInit_%s )\n", _pFileName->szName ); if( ! _bStartProc ) pSym = pSym->pNext; /* starting procedure is always the first symbol */ @@ -2390,8 +2390,8 @@ void GenCCode( char *szFileName, char *szName ) /* generates the C languag pSym = pSym->pNext; } - fprintf( yyc, "\nHB_INIT_SYMBOLS_END( %s__InitSymbols )\n", _pFileName->szName ); - fprintf( yyc, "#if ! defined(__GNUC__)\n#pragma startup %s__InitSymbols\n#endif\n\n\n", _pFileName->szName ); + fprintf( yyc, "\nHB_INIT_SYMBOLS_END( hb_vm_SymbolInit_%s )\n", _pFileName->szName ); + fprintf( yyc, "#if ! defined(__GNUC__)\n#pragma startup hb_vm_SymbolInit_%s\n#endif\n\n\n", _pFileName->szName ); /* Generate functions data */ @@ -3633,10 +3633,10 @@ void Inc( void ) if( pStackValType ) { - if( pStackValType->cType == ' ' ) - GenWarning( _szCWarnings, 'W', WARN_NUMERIC_SUSPECT, NULL, NULL ); - else if( pStackValType->cType != 'N' ) - GenWarning( _szCWarnings, 'W', WARN_NUMERIC_TYPE, sType, NULL ); + if( pStackValType->cType == ' ' ) + GenWarning( _szCWarnings, 'W', WARN_NUMERIC_SUSPECT, NULL, NULL ); + else if( pStackValType->cType != 'N' ) + GenWarning( _szCWarnings, 'W', WARN_NUMERIC_TYPE, sType, NULL ); } } } @@ -4382,10 +4382,10 @@ void Dec( void ) if( pStackValType ) { - if( pStackValType->cType == ' ' ) - GenWarning( _szCWarnings, 'W', WARN_NUMERIC_SUSPECT, NULL, NULL ); - else if( pStackValType->cType != 'N' ) - GenWarning( _szCWarnings, 'W', WARN_NUMERIC_TYPE, sType, NULL ); + if( pStackValType->cType == ' ' ) + GenWarning( _szCWarnings, 'W', WARN_NUMERIC_SUSPECT, NULL, NULL ); + else if( pStackValType->cType != 'N' ) + GenWarning( _szCWarnings, 'W', WARN_NUMERIC_TYPE, sType, NULL ); } } } @@ -5284,116 +5284,135 @@ static void LoopEnd( void ) hb_xfree( (void *) pLoop ); } +#define IS_PATH_SEP( c ) ( strchr( OS_PATH_DELIMITER_LIST, ( c ) ) != NULL ) + /* Split given filename into path, name and extension */ -PHB_FNAME hb_fsFNameSplit( char *szFilename ) +PHB_FNAME hb_fsFNameSplit( char * szFilename ) { - PHB_FNAME pName = (PHB_FNAME) hb_xgrab( sizeof(HB_FNAME) ); - int iLen = strlen(szFilename); - int iSlashPos; - int iDotPos; - int iPos; + PHB_FNAME pName = ( PHB_FNAME ) hb_xgrab( sizeof( HB_FNAME ) ); - pName->szPath = pName->szName = pName->szExtension = NULL; + int iLen = strlen( szFilename ); + int iSlashPos; + int iDotPos; + int iPos; - iSlashPos = iLen-1; - iPos = 0; + pName->szPath = + pName->szName = + pName->szExtension = NULL; - while( iSlashPos >= 0 && !IS_PATH_SEP(szFilename[ iSlashPos ]) ) - --iSlashPos; + iSlashPos = iLen - 1; + iPos = 0; - if( iSlashPos == 0 ) - { - /* root path -> \filename */ - pName->szBuffer[ 0 ] = OS_PATH_DELIMITER; - pName->szBuffer[ 1 ] = '\x0'; - pName->szPath = pName->szBuffer; - iPos = 2; /* first free position after the slash */ - } - else if( iSlashPos > 0 ) - { - /* path with separator -> path\filename */ - memcpy( pName->szBuffer, szFilename, iSlashPos ); - pName->szBuffer[ iSlashPos ] = '\x0'; - pName->szPath = pName->szBuffer; - iPos = iSlashPos + 1; /* first free position after the slash */ - } + while( iSlashPos >= 0 && !IS_PATH_SEP( szFilename[ iSlashPos ] ) ) + --iSlashPos; - iDotPos = iLen-1; - while( iDotPos > iSlashPos && szFilename[ iDotPos ] != '.' ) - --iDotPos; - if( (iDotPos-iSlashPos) > 1 ) - { - /* the dot was found - * and there is at least one character between a slash and a dot - */ - if( iDotPos == iLen-1 ) - { - /* the dot is the last character -use it as extension name */ - pName->szExtension = pName->szBuffer+iPos; - pName->szBuffer[ iPos++ ] = '.'; - pName->szBuffer[ iPos++ ] = '\x0'; - } - else - { - pName->szExtension = pName->szBuffer+iPos; - /* copy rest of the string with terminating ZERO character */ - memcpy( pName->szExtension, szFilename+iDotPos+1, iLen-iDotPos ); - iPos += iLen-iDotPos; - } - } - else - /* there is no dot in the filename or it is '.filename' */ - iDotPos = iLen; + if( iSlashPos == 0 ) + { + /* root path -> \filename */ + pName->szBuffer[ 0 ] = OS_PATH_DELIMITER; + pName->szBuffer[ 1 ] = '\0'; + pName->szPath = pName->szBuffer; + iPos = 2; /* first free position after the slash */ + } + else if( iSlashPos > 0 ) + { + /* If we are after a drive letter let's keep the following backslash */ + if( IS_PATH_SEP( ':' ) && + ( szFilename[ iSlashPos ] == ':' || szFilename[ iSlashPos - 1 ] == ':' ) ) + { + /* path with separator -> d:\path\filename or d:path\filename */ + memcpy( pName->szBuffer, szFilename, iSlashPos + 1 ); + pName->szBuffer[ iSlashPos + 1 ] = '\0'; + iPos = iSlashPos + 2; /* first free position after the slash */ + } + else + { + /* path with separator -> path\filename */ + memcpy( pName->szBuffer, szFilename, iSlashPos ); + pName->szBuffer[ iSlashPos ] = '\0'; + iPos = iSlashPos + 1; /* first free position after the slash */ + } - pName->szName = pName->szBuffer + iPos; - memcpy( pName->szName, szFilename + iSlashPos + 1, iDotPos - iSlashPos - 1 ); - pName->szName[ iDotPos - iSlashPos - 1 ] = '\x0'; + pName->szPath = pName->szBuffer; + } - return pName; + iDotPos = iLen - 1; + while( iDotPos > iSlashPos && szFilename[ iDotPos ] != '.' ) + --iDotPos; + + if( ( iDotPos - iSlashPos ) > 1 ) + { + /* the dot was found + * and there is at least one character between a slash and a dot + */ + if( iDotPos == iLen - 1 ) + { + /* the dot is the last character - use it as extension name */ + pName->szExtension = pName->szBuffer + iPos; + pName->szBuffer[ iPos++ ] = '.'; + pName->szBuffer[ iPos++ ] = '\0'; + } + else + { + pName->szExtension = pName->szBuffer + iPos; + /* copy rest of the string with terminating ZERO character */ + memcpy( pName->szExtension, szFilename + iDotPos + 1, iLen - iDotPos ); + iPos += iLen - iDotPos; + } + } + else + /* there is no dot in the filename or it is '.filename' */ + iDotPos = iLen; + + pName->szName = pName->szBuffer + iPos; + memcpy( pName->szName, szFilename + iSlashPos + 1, iDotPos - iSlashPos - 1 ); + pName->szName[ iDotPos - iSlashPos - 1 ] = '\0'; + + return pName; } /* This function joins path, name and extension into a string with a filename */ -char * hb_fsFNameMerge( char *szFileName, PHB_FNAME pFileName ) +char * hb_fsFNameMerge( char * szFileName, PHB_FNAME pFileName ) { - if( pFileName->szPath && pFileName->szPath[ 0 ] ) - { - /* we have not empty path specified */ - int iLen = strlen(pFileName->szPath); + if( pFileName->szPath && pFileName->szPath[ 0 ] ) + { + /* we have not empty path specified */ + int iLen = strlen( pFileName->szPath ); - strcpy( szFileName, pFileName->szPath ); + strcpy( szFileName, pFileName->szPath ); - /* if the path is a root directory then we don't need to add path separator */ - if( !(IS_PATH_SEP(pFileName->szPath[ 0 ]) && pFileName->szPath[ 0 ] == '\x0') ) - { - /* add the path separator only in cases: - * when a name doesn't start with it - * when the path doesn't end with it - */ - if( !( IS_PATH_SEP(pFileName->szName[ 0 ]) || IS_PATH_SEP(pFileName->szPath[ iLen-1 ]) ) ) + /* if the path is a root directory then we don't need to add path separator */ + if( !( IS_PATH_SEP( pFileName->szPath[ 0 ] ) && pFileName->szPath[ 0 ] == '\0' ) ) { - szFileName[ iLen++ ] = OS_PATH_DELIMITER; - szFileName[ iLen ] = '\x0'; + /* add the path separator only in cases: + * when a name doesn't start with it + * when the path doesn't end with it + */ + if( !( IS_PATH_SEP( pFileName->szName[ 0 ] ) || IS_PATH_SEP( pFileName->szPath[ iLen-1 ] ) ) ) + { + szFileName[ iLen++ ] = OS_PATH_DELIMITER; + szFileName[ iLen ] = '\0'; + } } - } - strcpy( szFileName+iLen, pFileName->szName ); - } - else - strcpy( szFileName, pFileName->szName ); + strcpy( szFileName + iLen, pFileName->szName ); + } + else + strcpy( szFileName, pFileName->szName ); - if( pFileName->szExtension ) - { - int iLen = strlen(szFileName); + if( pFileName->szExtension ) + { + int iLen = strlen( szFileName ); - if( !(pFileName->szExtension[ 0 ] == '.' || szFileName[ iLen-1 ] == '.') ) - { - /* add extension separator only when extansion doesn't contain it */ - szFileName[ iLen++ ] = '.'; - szFileName[ iLen ] = '\x0'; - } - strcpy( szFileName+iLen, pFileName->szExtension ); - } + if( !( pFileName->szExtension[ 0 ] == '.' || szFileName[ iLen-1 ] == '.') ) + { + /* add extension separator only when extansion doesn't contain it */ + szFileName[ iLen++ ] = '.'; + szFileName[ iLen ] = '\0'; + } + strcpy( szFileName + iLen, pFileName->szExtension ); + } - return szFileName; + return szFileName; } void * hb_xgrab( ULONG ulSize ) /* allocates fixed memory, exits on failure */ diff --git a/harbour/source/hbpp/stdalone/hbpp.c b/harbour/source/hbpp/stdalone/hbpp.c index cfd4cf5956..1998706d0d 100644 --- a/harbour/source/hbpp/stdalone/hbpp.c +++ b/harbour/source/hbpp/stdalone/hbpp.c @@ -427,116 +427,135 @@ void GenWarning( char* _szWarnings[], char cPrefix, int iWarning, char * szWarni } } +#define IS_PATH_SEP( c ) ( strchr( OS_PATH_DELIMITER_LIST, ( c ) ) != NULL ) + /* Split given filename into path, name and extension */ -PHB_FNAME hb_fsFNameSplit( char *szFilename ) +PHB_FNAME hb_fsFNameSplit( char * szFilename ) { - PHB_FNAME pName = (PHB_FNAME) hb_xgrab( sizeof(HB_FNAME) ); - int iLen = strlen(szFilename); - int iSlashPos; - int iDotPos; - int iPos; + PHB_FNAME pName = ( PHB_FNAME ) hb_xgrab( sizeof( HB_FNAME ) ); - pName->szPath = pName->szName = pName->szExtension = NULL; + int iLen = strlen( szFilename ); + int iSlashPos; + int iDotPos; + int iPos; - iSlashPos = iLen-1; - iPos = 0; + pName->szPath = + pName->szName = + pName->szExtension = NULL; - while( iSlashPos >= 0 && !IS_PATH_SEP(szFilename[ iSlashPos ]) ) - --iSlashPos; + iSlashPos = iLen - 1; + iPos = 0; - if( iSlashPos == 0 ) - { - /* root path -> \filename */ - pName->szBuffer[ 0 ] = OS_PATH_DELIMITER; - pName->szBuffer[ 1 ] = '\x0'; - pName->szPath = pName->szBuffer; - iPos = 2; /* first free position after the slash */ - } - else if( iSlashPos > 0 ) - { - /* path with separator -> path\filename */ - memcpy( pName->szBuffer, szFilename, iSlashPos ); - pName->szBuffer[ iSlashPos ] = '\x0'; - pName->szPath = pName->szBuffer; - iPos = iSlashPos + 1; /* first free position after the slash */ - } + while( iSlashPos >= 0 && !IS_PATH_SEP( szFilename[ iSlashPos ] ) ) + --iSlashPos; - iDotPos = iLen-1; - while( iDotPos > iSlashPos && szFilename[ iDotPos ] != '.' ) - --iDotPos; - if( (iDotPos-iSlashPos) > 1 ) - { - /* the dot was found - * and there is at least one character between a slash and a dot - */ - if( iDotPos == iLen-1 ) - { - /* the dot is the last character -use it as extension name */ - pName->szExtension = pName->szBuffer+iPos; - pName->szBuffer[ iPos++ ] = '.'; - pName->szBuffer[ iPos++ ] = '\x0'; - } - else - { - pName->szExtension = pName->szBuffer+iPos; - /* copy rest of the string with terminating ZERO character */ - memcpy( pName->szExtension, szFilename+iDotPos+1, iLen-iDotPos ); - iPos += iLen-iDotPos; - } - } - else - /* there is no dot in the filename or it is '.filename' */ - iDotPos = iLen; + if( iSlashPos == 0 ) + { + /* root path -> \filename */ + pName->szBuffer[ 0 ] = OS_PATH_DELIMITER; + pName->szBuffer[ 1 ] = '\0'; + pName->szPath = pName->szBuffer; + iPos = 2; /* first free position after the slash */ + } + else if( iSlashPos > 0 ) + { + /* If we are after a drive letter let's keep the following backslash */ + if( IS_PATH_SEP( ':' ) && + ( szFilename[ iSlashPos ] == ':' || szFilename[ iSlashPos - 1 ] == ':' ) ) + { + /* path with separator -> d:\path\filename or d:path\filename */ + memcpy( pName->szBuffer, szFilename, iSlashPos + 1 ); + pName->szBuffer[ iSlashPos + 1 ] = '\0'; + iPos = iSlashPos + 2; /* first free position after the slash */ + } + else + { + /* path with separator -> path\filename */ + memcpy( pName->szBuffer, szFilename, iSlashPos ); + pName->szBuffer[ iSlashPos ] = '\0'; + iPos = iSlashPos + 1; /* first free position after the slash */ + } - pName->szName = pName->szBuffer + iPos; - memcpy( pName->szName, szFilename + iSlashPos + 1, iDotPos - iSlashPos - 1 ); - pName->szName[ iDotPos - iSlashPos - 1 ] = '\x0'; + pName->szPath = pName->szBuffer; + } - return pName; + iDotPos = iLen - 1; + while( iDotPos > iSlashPos && szFilename[ iDotPos ] != '.' ) + --iDotPos; + + if( ( iDotPos - iSlashPos ) > 1 ) + { + /* the dot was found + * and there is at least one character between a slash and a dot + */ + if( iDotPos == iLen - 1 ) + { + /* the dot is the last character - use it as extension name */ + pName->szExtension = pName->szBuffer + iPos; + pName->szBuffer[ iPos++ ] = '.'; + pName->szBuffer[ iPos++ ] = '\0'; + } + else + { + pName->szExtension = pName->szBuffer + iPos; + /* copy rest of the string with terminating ZERO character */ + memcpy( pName->szExtension, szFilename + iDotPos + 1, iLen - iDotPos ); + iPos += iLen - iDotPos; + } + } + else + /* there is no dot in the filename or it is '.filename' */ + iDotPos = iLen; + + pName->szName = pName->szBuffer + iPos; + memcpy( pName->szName, szFilename + iSlashPos + 1, iDotPos - iSlashPos - 1 ); + pName->szName[ iDotPos - iSlashPos - 1 ] = '\0'; + + return pName; } /* This function joins path, name and extension into a string with a filename */ -char * hb_fsFNameMerge( char *szFileName, PHB_FNAME pFileName ) +char * hb_fsFNameMerge( char * szFileName, PHB_FNAME pFileName ) { - if( pFileName->szPath && pFileName->szPath[ 0 ] ) - { - /* we have not empty path specified */ - int iLen = strlen(pFileName->szPath); + if( pFileName->szPath && pFileName->szPath[ 0 ] ) + { + /* we have not empty path specified */ + int iLen = strlen( pFileName->szPath ); - strcpy( szFileName, pFileName->szPath ); + strcpy( szFileName, pFileName->szPath ); - /* if the path is a root directory then we don't need to add path separator */ - if( !(IS_PATH_SEP(pFileName->szPath[ 0 ]) && pFileName->szPath[ 0 ] == '\x0') ) - { - /* add the path separator only in cases: - * when a name doesn't start with it - * when the path doesn't end with it - */ - if( !( IS_PATH_SEP(pFileName->szName[ 0 ]) || IS_PATH_SEP(pFileName->szPath[ iLen-1 ]) ) ) + /* if the path is a root directory then we don't need to add path separator */ + if( !( IS_PATH_SEP( pFileName->szPath[ 0 ] ) && pFileName->szPath[ 0 ] == '\0' ) ) { - szFileName[ iLen++ ] = OS_PATH_DELIMITER; - szFileName[ iLen ] = '\x0'; + /* add the path separator only in cases: + * when a name doesn't start with it + * when the path doesn't end with it + */ + if( !( IS_PATH_SEP( pFileName->szName[ 0 ] ) || IS_PATH_SEP( pFileName->szPath[ iLen-1 ] ) ) ) + { + szFileName[ iLen++ ] = OS_PATH_DELIMITER; + szFileName[ iLen ] = '\0'; + } } - } - strcpy( szFileName+iLen, pFileName->szName ); - } - else - strcpy( szFileName, pFileName->szName ); + strcpy( szFileName + iLen, pFileName->szName ); + } + else + strcpy( szFileName, pFileName->szName ); - if( pFileName->szExtension ) - { - int iLen = strlen(szFileName); + if( pFileName->szExtension ) + { + int iLen = strlen( szFileName ); - if( !(pFileName->szExtension[ 0 ] == '.' || szFileName[ iLen-1 ] == '.') ) - { - /* add extension separator only when extansion doesn't contain it */ - szFileName[ iLen++ ] = '.'; - szFileName[ iLen ] = '\x0'; - } - strcpy( szFileName+iLen, pFileName->szExtension ); - } + if( !( pFileName->szExtension[ 0 ] == '.' || szFileName[ iLen-1 ] == '.') ) + { + /* add extension separator only when extansion doesn't contain it */ + szFileName[ iLen++ ] = '.'; + szFileName[ iLen ] = '\0'; + } + strcpy( szFileName + iLen, pFileName->szExtension ); + } - return szFileName; + return szFileName; } void * hb_xgrab( ULONG ulSize ) /* allocates fixed memory, exits on failure */ diff --git a/harbour/source/rtl/errorapi.c b/harbour/source/rtl/errorapi.c index 29da3919ba..741c834b15 100644 --- a/harbour/source/rtl/errorapi.c +++ b/harbour/source/rtl/errorapi.c @@ -66,7 +66,7 @@ WORD hb_errLaunch( PHB_ITEM pError ) if( ! IS_BLOCK( &errorBlock ) ) hb_errInternal( 9999, "No ERRORBLOCK() for error", NULL, NULL ); - /* Launch the error handler: "lResult := EVAL( bErrorBlock, oError )" */ + /* Launch the error handler: "lResult := EVAL( ErrorBlock(), oError )" */ pBlock = hb_itemNew( NULL ); pObject = hb_itemNew( NULL ); @@ -82,22 +82,16 @@ WORD hb_errLaunch( PHB_ITEM pError ) /* Check results */ - /* TODO: Determine if there was a BREAK in the error handler. */ - if( FALSE ) + if( hb_vmRequestQuery() == HB_QUIT_REQUESTED ) { hb_itemRelease( pResult ); - - /* TODO: Detect sequence level properly */ - if( FALSE ) - { - /* TODO: Initiate a jump to the closest RECOVER statement */ - wRetVal = E_BREAK; - } - else - { - /* TODO: QUIT correctly, without any message */ - exit( 1 ); - } + hb_errRelease( pError ); + hb_vmQuit(); + } + else if( hb_vmRequestQuery() == HB_BREAK_REQUESTED ) + { + hb_itemRelease( pResult ); + wRetVal = E_BREAK; } else { @@ -107,20 +101,15 @@ WORD hb_errLaunch( PHB_ITEM pError ) /* If the error block didn't return a logical value, */ /* or the canSubstitute flag has been set, consider it as a failure */ - if( ! IS_LOGICAL( pResult ) || - ( uiFlags & EF_CANSUBSTITUTE ) ) - { + if( ! IS_LOGICAL( pResult ) || ( uiFlags & EF_CANSUBSTITUTE ) ) bFailure = TRUE; - } else { wRetVal = hb_itemGetL( pResult ) ? E_RETRY : E_DEFAULT; if( ( wRetVal == E_DEFAULT && !( uiFlags & EF_CANDEFAULT ) ) || ( wRetVal == E_RETRY && !( uiFlags & EF_CANRETRY ) ) ) - { bFailure = TRUE; - } } hb_itemRelease( pResult ); @@ -143,7 +132,7 @@ WORD hb_errLaunch( PHB_ITEM pError ) Since it this case the error handler will return the value to be substituted */ /* NOTE: The item pointer returned should be hb_itemRelease()-d by the - caller. */ + caller if it was not NULL. */ PHB_ITEM hb_errLaunchSubst( PHB_ITEM pError ) { @@ -160,7 +149,7 @@ PHB_ITEM hb_errLaunchSubst( PHB_ITEM pError ) if( ! IS_BLOCK( &errorBlock ) ) hb_errInternal( 9999, "No ERRORBLOCK() for error", NULL, NULL ); - /* Launch the error handler: "xResult := EVAL( bErrorBlock, oError )" */ + /* Launch the error handler: "xResult := EVAL( ErrorBlock(), oError )" */ pBlock = hb_itemNew( NULL ); pObject = hb_itemNew( NULL ); @@ -176,23 +165,16 @@ PHB_ITEM hb_errLaunchSubst( PHB_ITEM pError ) /* Check results */ - /* TODO: Determine if there was a BREAK in the error handler. */ - if( FALSE ) + if( hb_vmRequestQuery() == HB_QUIT_REQUESTED ) { - /* TODO: Detect sequence level properly */ - if( FALSE ) - { - /* TODO: Initiate a jump to the closest RECOVER statement */ - /* QUESTION: Will Clipper return to the caller in this case ? */ - } - else - { - hb_itemRelease( pResult ); - pResult = NULL; - - /* TODO: QUIT correctly, without any message */ - exit( 1 ); - } + hb_itemRelease( pResult ); + hb_errRelease( pError ); + hb_vmQuit(); + } + else if( hb_vmRequestQuery() == HB_BREAK_REQUESTED ) + { + hb_itemRelease( pResult ); + pResult = NULL; } else { @@ -200,9 +182,7 @@ PHB_ITEM hb_errLaunchSubst( PHB_ITEM pError ) consider it as a failure. */ if( ! ( hb_errGetFlags( pError ) & EF_CANSUBSTITUTE ) ) - { hb_errInternal( 9999, "Error recovery failure", NULL, NULL ); - } } } else diff --git a/harbour/source/rtl/filesys.c b/harbour/source/rtl/filesys.c index 76bc1db03b..eb7375ec7b 100644 --- a/harbour/source/rtl/filesys.c +++ b/harbour/source/rtl/filesys.c @@ -484,7 +484,7 @@ BOOL hb_fsLock ( FHANDLE hFileHandle, ULONG ulStart, int iResult = 0; #if defined(_MSC_VER) - ULONG ulPos; + ULONG ulOldPos; #endif #if defined(HAVE_POSIX_IO) && !defined(__GNUC__) && !defined(__IBMCPP__) @@ -505,7 +505,7 @@ BOOL hb_fsLock ( FHANDLE hFileHandle, ULONG ulStart, #if defined(_MSC_VER) - ulPos = hb_fsSeek( hFileHandle, ulStart, FS_SET ); + ulOldPos = hb_fsSeek( hFileHandle, ulStart, FS_SET ); switch( uiMode ) { @@ -517,7 +517,7 @@ BOOL hb_fsLock ( FHANDLE hFileHandle, ULONG ulStart, iResult = locking( hFileHandle, _LK_UNLCK, ulLength ); } - hb_fsSeek( hFileHandle, ulPos, FS_SET ); + hb_fsSeek( hFileHandle, ulOldPos, FS_SET ); #else @@ -725,6 +725,7 @@ USHORT hb_fsIsDrv ( BYTE nDrive ) } /* TODO: Implement hb_fsExtOpen */ + FHANDLE hb_fsExtOpen( BYTE * pFilename, BYTE * pDefExt, USHORT uiFlags, BYTE * pPaths, PHB_ITEM pError ) { @@ -741,15 +742,11 @@ FHANDLE hb_fsExtOpen( BYTE * pFilename, BYTE * pDefExt, HARBOUR HB_FOPEN( void ) { if( ISCHAR( 1 ) ) - { hb_retni( hb_fsOpen( ( BYTE * ) hb_parc( 1 ), ISNUM( 2 ) ? hb_parni( 2 ) : FO_READ ) ); - } else - { /* NOTE: Undocumented but existing Clipper Run-time error */ hb_errRT_BASE( EG_ARG, 2021, NULL, "FOPEN" ); - } } HARBOUR HB_FCREATE( void ) @@ -1024,10 +1021,10 @@ HARBOUR HB_W2BIN( void ) HB_I2BIN(); } -#define IS_PATH_SEP( c ) ( c == OS_PATH_DELIMITER ) +#define IS_PATH_SEP( c ) ( strchr( OS_PATH_DELIMITER_LIST, ( c ) ) != NULL ) /* Split given filename into path, name and extension */ -PHB_FNAME hb_fsFNameSplit( char *szFilename ) +PHB_FNAME hb_fsFNameSplit( char * szFilename ) { PHB_FNAME pName = ( PHB_FNAME ) hb_xgrab( sizeof( HB_FNAME ) ); @@ -1052,15 +1049,28 @@ PHB_FNAME hb_fsFNameSplit( char *szFilename ) pName->szBuffer[ 0 ] = OS_PATH_DELIMITER; pName->szBuffer[ 1 ] = '\0'; pName->szPath = pName->szBuffer; - iPos = 2; /* first free position after the slash */ + iPos = 2; /* first free position after the slash */ } else if( iSlashPos > 0 ) { - /* path with separator -> path\filename */ - memcpy( pName->szBuffer, szFilename, iSlashPos ); - pName->szBuffer[ iSlashPos ] = '\0'; + /* If we are after a drive letter let's keep the following backslash */ + if( IS_PATH_SEP( ':' ) && + ( szFilename[ iSlashPos ] == ':' || szFilename[ iSlashPos - 1 ] == ':' ) ) + { + /* path with separator -> d:\path\filename or d:path\filename */ + memcpy( pName->szBuffer, szFilename, iSlashPos + 1 ); + pName->szBuffer[ iSlashPos + 1 ] = '\0'; + iPos = iSlashPos + 2; /* first free position after the slash */ + } + else + { + /* path with separator -> path\filename */ + memcpy( pName->szBuffer, szFilename, iSlashPos ); + pName->szBuffer[ iSlashPos ] = '\0'; + iPos = iSlashPos + 1; /* first free position after the slash */ + } + pName->szPath = pName->szBuffer; - iPos = iSlashPos + 1; /* first free position after the slash */ } iDotPos = iLen - 1; @@ -1074,7 +1084,7 @@ PHB_FNAME hb_fsFNameSplit( char *szFilename ) */ if( iDotPos == iLen - 1 ) { - /* the dot is the last character -use it as extension name */ + /* the dot is the last character - use it as extension name */ pName->szExtension = pName->szBuffer + iPos; pName->szBuffer[ iPos++ ] = '.'; pName->szBuffer[ iPos++ ] = '\0'; @@ -1099,7 +1109,7 @@ PHB_FNAME hb_fsFNameSplit( char *szFilename ) } /* This function joins path, name and extension into a string with a filename */ -char * hb_fsFNameMerge( char *szFileName, PHB_FNAME pFileName ) +char * hb_fsFNameMerge( char * szFileName, PHB_FNAME pFileName ) { if( pFileName->szPath && pFileName->szPath[ 0 ] ) { @@ -1142,26 +1152,3 @@ char * hb_fsFNameMerge( char *szFileName, PHB_FNAME pFileName ) return szFileName; } -/* TOFIX: -If you call pFileName = hb_fsFNameSplit( "C:FILE.EXT" ) the result is: - pFileName->szPath => (null) must be 'C:' - pFileName->szName => 'C:FILE' must be 'FILE' - pFileName->szExtension => '.EXT' Ok! - -If you call pFileName = hb_fsFNameSplit( "C:\FILE.EXT" ) the result is: - pFileName->szPath => 'C:' must be 'C:\' - pFileName->szName => 'FILE' Ok! - pFileName->szExtension => '.EXT' Ok! - -If you call pFileName = hb_fsFNameSplit( "\FILE.EXT" ) the result is: - pFileName->szPath => '\' Ok! - pFileName->szName => 'FILE' Ok! - pFileName->szExtension => '.EXT' Ok! - -If you call pFileName = hb_fsFNameSplit( "C:\DIR\FILE.EXT" ) the result -is: - pFileName->szPath => 'C:\DIR' Ok! - pFileName->szName => 'FILE' Ok! - pFileName->szExtension => '.EXT' Ok! - -*/ diff --git a/harbour/source/rtl/mouse/mousedos.c b/harbour/source/rtl/mouse/mousedos.c index 0216beb0b9..0157915d02 100644 --- a/harbour/source/rtl/mouse/mousedos.c +++ b/harbour/source/rtl/mouse/mousedos.c @@ -42,7 +42,6 @@ #pragma inline #include - #include #endif #include "mouseapi.h" @@ -200,7 +199,26 @@ BOOL hb_mouse_IsButtonPressed( int iButton ) { /* TODO: */ - HB_SYMBOL_UNUSED( iButton ); + if( s_bPresent ) + { +#ifdef BORLANDC + int iReturn = 0; + + asm + { + mov ax, 5 + int MOUSE_INTERRUPT + mov iReturn, bx + } + + /* Convert the button number (1 -> x) to a bitmask and check */ + /* TODO: Test if this works */ + + return ( ( 2 ** ( iButton - 1 ) ) && iReturn ); +#else + return FALSE; +#endif + } return FALSE; } diff --git a/harbour/source/vm/hvm.c b/harbour/source/vm/hvm.c index 2ea9bb7d85..25741b3061 100644 --- a/harbour/source/vm/hvm.c +++ b/harbour/source/vm/hvm.c @@ -109,8 +109,6 @@ static LONG RecoverBase = 0; /* Request for some action - stop processing of opcodes */ static WORD wActionRequest = 0; -#define HB_QUIT_REQUESTED 1 /* immediately quit the application */ -#define HB_BREAK_REQUESTED 2 /* break to nearest RECOVER/END sequence */ /* uncomment it to trace the virtual machine activity */ /* #define bHB_DEBUG */ @@ -145,7 +143,7 @@ int main( int argc, char * argv[] ) #ifdef HARBOUR_OBJ_GENERATION hb_vmProcessObjSymbols(); /* initialize Harbour generated OBJs symbols */ #endif - hb_vmRTSymbolsInit(); /* initialize symbol table with runtime support functions */ + hb_vmSymbolInit_RT(); /* initialize symbol table with runtime support functions */ /* Call functions that initializes static variables * Static variables have to be initialized before any INIT functions @@ -171,9 +169,21 @@ int main( int argc, char * argv[] ) hb_vmPushString( argv[ i ], strlen( argv[ i ] ) ); hb_vmDo( argc - 1 ); /* invoke it with number of supplied parameters */ + hb_vmQuit(); + + /* This point is never reached */ + + return 0; +} + +void hb_vmQuit( void ) +{ wActionRequest = 0; /* EXIT procedures should be processed */ hb_vmDoExitFunctions(); /* process defined EXIT functions */ + while( stack.pPos > stack.pItems ) + hb_stackPop(); + hb_itemClear( &stack.Return ); hb_arrayRelease( &aStatics ); hb_itemClear( &errorBlock ); @@ -189,7 +199,7 @@ int main( int argc, char * argv[] ) HB_DEBUG( "Done!\n" ); - return byErrorLevel; + exit( byErrorLevel ); } void hb_vmExecute( BYTE * pCode, PHB_SYMB pSymbols ) @@ -903,9 +913,9 @@ void hb_vmArrayPut( void ) static void hb_vmDebuggerEndProc( void ) { - HB_ITEM it; + HB_ITEM item; - hb_itemCopy( &it, &stack.Return ); /* saves the previous returned value */ + hb_itemCopy( &item, &stack.Return ); /* saves the previous returned value */ bDebugShowLines = FALSE; hb_vmPushSymbol( hb_dynsymFind( "__DBGENTRY" )->pSymbol ); @@ -913,8 +923,8 @@ static void hb_vmDebuggerEndProc( void ) hb_vmDo( 0 ); bDebugShowLines = TRUE; - hb_itemCopy( &stack.Return, &it ); /* restores the previous returned value */ - hb_itemClear( &it ); + hb_itemCopy( &stack.Return, &item ); /* restores the previous returned value */ + hb_itemClear( &item ); } static void hb_vmDebuggerShowLine( WORD wLine ) /* makes the debugger shows a specific source code line */ @@ -1534,8 +1544,6 @@ void hb_vmNotEqual( void ) else if( pItem1->type != pItem2->type ) hb_errRT_BASE( EG_ARG, 1072, NULL, "<>" ); - - else hb_vmPushLogical( TRUE ); } @@ -2734,6 +2742,9 @@ HARBOUR HB_ERRORLEVEL(void) { BYTE byPrevValue = byErrorLevel; + /* NOTE: This should be ISNUM( 1 ), but it's sort of a Clipper bug that it + accepts other types also and consider them zero. */ + if( hb_pcount() > 0 ) /* Only replace the error level if a parameter was passed */ byErrorLevel = hb_parni( 1 ); @@ -2778,6 +2789,11 @@ void hb_vmRequestBreak( PHB_ITEM pItem ) wActionRequest = HB_QUIT_REQUESTED; } +WORD hb_vmRequestQuery( void ) +{ + return wActionRequest; +} + /* NOTE: This function should normally have a parameter count check. But since in Harbour we cannot distinguish between BREAK() function and the BREAK statement, because both generate a BREAK() function diff --git a/harbour/source/vm/initsymb.c b/harbour/source/vm/initsymb.c index dfb1e4ee80..08fe13b807 100644 --- a/harbour/source/vm/initsymb.c +++ b/harbour/source/vm/initsymb.c @@ -127,8 +127,8 @@ static HB_SYMB symbols[] = { /* NOTE: The system symbol table with runtime functions HAVE TO be called last */ -void hb_vmRTSymbolsInit( void ) +void hb_vmSymbolInit_RT( void ) { - hb_vmProcessSymbols( symbols, sizeof(symbols) / sizeof( HB_SYMB ) ); + hb_vmProcessSymbols( symbols, sizeof( symbols ) / sizeof( HB_SYMB ) ); } diff --git a/harbour/tests/working/fileio.prg b/harbour/tests/working/fileio.prg index 2d635c8cfb..492d332b51 100644 --- a/harbour/tests/working/fileio.prg +++ b/harbour/tests/working/fileio.prg @@ -74,6 +74,10 @@ FUNCTION Main() OutSpec("FClose()" , FClose() ) OutSpec("FClose( fhnd )" , FClose( fhnd ) ) OutSpec("FClose( fhnd )" , FClose( fhnd ) ) + OutSpec("FErase( 'NOT_HERE.$$$' )" , FErase( 'NOT_HERE.$$$' ) ) + OutSpec("FErase( 1 )" , FErase( 1 ) ) + OutSpec("FErase( 'NOT_HERE.$$$' )" , FErase( 'NOT_HERE.$$$' ) ) + OutSpec("FRename( 'NOT_HERE.$$$', 'A' )" , FRename( 'NOT_HERE.$$$', 'A' ) ) OutSpec("File( cFileName )" , File( cFileName ) )