diff --git a/harbour/ChangeLog b/harbour/ChangeLog index a7fadde5fb..be946508c2 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -8,6 +8,84 @@ 2002-12-01 13:30 UTC+0100 Foo Bar */ +2005-11-01 23:28 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) + * harbour/make_gnu.sh + + harbour/make_xmingw.sh + * harbour/bin/hb-mkslib.sh + * harbour/bin/postinst.sh + * harbour/config/w32/mingw32.cf + * added support for cross compilation (Windows binaries at Linux) with + MinGW - borrowed from xHarbour Phil Krylov solution + + * harbour/contrib/btree/hb_btree.c + * casting + + * harbour/contrib/libct/files.c + ! fixed iAttr initialization in SETFATTR() + + * harbour/contrib/ole/ole2.c + ! fixed names of included files + + * harbour/contrib/rdd_ads/ace.h + * cover #pragma warning( error : 4706 ) by !defined( __GNUC__ ) + + * harbour/include/hbapi.h + * harbour/include/hbdefs.h + + harbour/source/common/hbarch.c + * harbour/source/common/Makefile + * added functions for machine independent double and long long conversions + (my code borrowed from xHarbour) + + * harbour/include/hbapifs.h + * synced file IO with xHarbour - it fixes some problems, adds some + missing functionality and long (64bit) file support for Windows. + For Linux I added it some time ago. + + * harbour/include/hbcomp.h + * changed 'char cScope' to 'HB_SYMBOLSCOPE cScope' + + * harbour/source/common/hbfsapi.c + ! fixed some possible buffer overflow + + * harbour/source/common/hbstr.c + * synced with xHarbour + + * harbour/source/common/hbver.c + + added hb_iswinnt() (borrowed from xHarbour) + + * harbour/source/compiler/cmdcheck.c + + added -undef: compiler switch (borrowed from xHarbour) + + * harbour/source/compiler/gencobj.c + * cleanup + + * harbour/source/pp/ppcore.c + ! fixed path delimiters in included file names + + * harbour/source/rtl/Makefile + + harbour/source/rtl/fserror.c + + added C -> OS file error trnalsations - not perfect but better then + the used hacks (borrowed from xHarbour) + + * harbour/source/rtl/file.c + * use hb_fileNameConv() instead of hb_filecase() - hb_fileNameConv() + is the only one function to make file name conversions dependent on + some SETs. + + * harbour/source/rtl/filesys.c + * synced file IO with xHarbour - it fixes some problems, adds some + missing functionality and long (64bit) file support for Windows. + For Linux I added it some time ago. + + * harbour/source/rtl/fstemp.c + * synced with xHarbour + + * harbour/source/rtl/strings.c + * use ULONG instead of size_t in hb_strnicmp declaration - we have to + decide what we should use. Using size_t or its Harbour version f.e. + HB_SIZE_T seems to be reasonable but it has to be global - redefining + single functions does not make sense and will create troubles only. + 2005-10-31 14:38 UTC+0100 Antonio Linares * makefile.nt * makefile64.nt diff --git a/harbour/bin/hb-mkslib.sh b/harbour/bin/hb-mkslib.sh index f0e94a9db4..df44d9305e 100644 --- a/harbour/bin/hb-mkslib.sh +++ b/harbour/bin/hb-mkslib.sh @@ -12,12 +12,25 @@ # See doc/license.txt for licensing terms. # --------------------------------------------------------------- -if [ `uname` = "Darwin" ]; then - SLIB_EXT=".dylib" +if [ -n "${HB_ARCHITECTURE}" ] +then + hb_arch="${HB_ARCHITECTURE}" else - SLIB_EXT=".so" + hb_arch=`uname -s | tr -d "[-]" | tr '[A-Z]' '[a-z]' 2>/dev/null` fi +case "$hb_arch" in + *windows*|*mingw32*) hb_arch="w32" ;; + *dos) hb_arch="dos" ;; + *bsd) hb_arch="bsd" ;; +esac + +case "$hb_arch" in + darwin) SLIB_EXT=".dylib" ;; + w32) SLIB_EXT=".dll" ;; + *) SLIB_EXT=".so" ;; +esac + NAME="${1%${SLIB_EXT}}" LIB_NAME="${NAME##*/}" DSTDIR="${NAME%${LIB_NAME}}" @@ -65,7 +78,7 @@ for f in $* do case "${f}" in *.o) - if [ ! -r "${dir}/${f}" ] + if [ ! -r "${dir}/${f}" ] then echo "cannot read file: ${f}" exit 1 @@ -82,7 +95,7 @@ do d="${f##*/}" mkdir $d cd $d - ar -x "${dir}/${f}" || exit 1 + ${CCPREFIX}ar -x "${dir}/${f}" || exit 1 cd .. ;; *) @@ -93,22 +106,29 @@ done OBJLST=`find . -name \*.o` cd "${OTMPDIR}" -if [ `uname` = "Darwin" ]; then +if [ "${SLIB_EXT}" = ".dylib" ]; then FULLNAME="${BASE}.${VERSION}${SLIB_EXT}" ld -r -o "${FULLNAME}.o" $OBJLST && \ - gcc -dynamiclib -install_name "${BASE}.${MAJOR}${SLIB_EXT}" \ + ${CCPREFIX}gcc -dynamiclib -install_name "${BASE}.${MAJOR}${SLIB_EXT}" \ -compatibility_version ${MAJOR}.${MINOR} -current_version ${VERSION} \ - -flat_namespace -undefined warning -multiply_defined suppress \ + -flat_namespace -undefined warning -multiply_defined suppress -single_module \ -o "${FULLNAME}" "${FULLNAME}.o" ${linker_options} && \ cd "${dir}" && \ mv -f "${OTMPDIR}/${FULLNAME}" "${DSTDIR}${FULLNAME}" && \ ln -sf "${FULLNAME}" "${DSTDIR}${BASE}.${MAJOR}${SLIB_EXT}" && \ ln -sf "${FULLNAME}" "${DSTDIR}${BASE}${SLIB_EXT}" +elif [ "${SLIB_EXT}" = ".dll" ]; then + FULLNAME="${LIB_NAME}${SLIB_EXT}" + SYSLIBS="-luser32 -lwinspool -lgdi32 -lcomctl32 -lcomdlg32 -lole32" + SYSLIBS="${SYSLIBS} -loleaut32 -luuid -lmpr -lwsock32 -lws2_32 -lmapi32" + ${CCPREFIX}gcc -shared -o "${FULLNAME}" $OBJLST ${linker_options} ${SYSLIBS} ${HB_DLLIBS} && \ + cd "${dir}" && \ + mv -f "${OTMPDIR}/${FULLNAME}" "${DSTDIR}${FULLNAME}" else #FULLNAME="${BASE}-${VERSION}${SLIB_EXT}" #FULLNAME="${BASE}{SLIB_EXT}.${VERSION}" FULLNAME="${LIB_NAME}${SLIB_EXT}" - gcc -shared -o "${FULLNAME}" $OBJLST ${linker_options} && \ + ${CCPREFIX}gcc -shared -o "${FULLNAME}" $OBJLST ${linker_options} && \ cd "${dir}" && \ mv -f "${OTMPDIR}/${FULLNAME}" "${DSTDIR}${FULLNAME}" fi diff --git a/harbour/bin/postinst.sh b/harbour/bin/postinst.sh index 6da678b21c..7225861e81 100644 --- a/harbour/bin/postinst.sh +++ b/harbour/bin/postinst.sh @@ -35,16 +35,17 @@ else fi . ${hb_root}/bin/hb-func.sh -if [ "$HB_COMPILER" = "gcc" ] || [ "$HB_COMPILER" = "mingw32" ] || [ "$HB_COMPILER" = "djgpp" ] +if [ "$HB_COMPILER" = "gcc" ] || [ "$HB_COMPILER" = "gpp" ] || \ + [ "$HB_COMPILER" = "mingw32" ] || [ "$HB_COMPILER" = "djgpp" ] then RANLIB="" MAKE=make - AR="ar -cr" - if [ "${HB_ARCHITECTURE}" = "bsd" ]; then + AR="${CCPREFIX}ar -cr" + if [ "${HB_ARCHITECTURE}" = "bsd" ] || [ `uname` = "FreeBSD" ]; then MAKE=gmake elif [ "${HB_ARCHITECTURE}" = "darwin" ]; then # We must build an archive index on Darwin - AR="ar -crs" + AR="${CCPREFIX}ar -crs" fi if [ "${HB_ARCHITECTURE}" = "sunos" ]; then install -m 755 -f "${HB_BIN_INSTALL}" "${hb_root}/bin/hb-mkslib.sh" @@ -53,8 +54,10 @@ then install -c -m 755 "${hb_root}/bin/hb-mkslib.sh" "${HB_BIN_INSTALL}/hb-mkslib" fi mk_hbtools "${HB_BIN_INSTALL}" "$@" - [ "$HB_COMPILER" = "gcc" ] && mk_hblibso "${hb_root}" - + if [ "$HB_COMPILER" = "gcc" ] || [ "$HB_COMPILER" = "gpp" ] || \ + [ "$HB_COMPILER" = "mingw32" ]; then + mk_hblibso "${hb_root}" + fi # build fm lib with memory statistic (cd ${hb_root}/source/vm C_USR=${C_USR//-DHB_FM_STATISTICS_OFF/} diff --git a/harbour/config/w32/mingw32.cf b/harbour/config/w32/mingw32.cf index e81a4158c5..3c862af924 100644 --- a/harbour/config/w32/mingw32.cf +++ b/harbour/config/w32/mingw32.cf @@ -118,7 +118,7 @@ ifeq ($(SHLVL),) # COMMAND.COM - length of command line is limited AR_RULE = $(create_library) LD_RULE = $(link_exe_file) else -AR_RULE = $(AR) $(ARFLAGS) r $@ $^ && $(RANLIB) $@ || $(RM) $@ +AR_RULE = $(AR) $(ARFLAGS) cr $@ $^ && $(RANLIB) $@ || $(RM) $@ endif include $(TOP)$(ROOT)config/rules.cf diff --git a/harbour/contrib/btree/hb_btree.c b/harbour/contrib/btree/hb_btree.c index 6b902a2060..ddf97fc0c0 100644 --- a/harbour/contrib/btree/hb_btree.c +++ b/harbour/contrib/btree/hb_btree.c @@ -301,6 +301,8 @@ typedef struct hb_KeyData_Tag BYTE szKey[ 1 ]; } hb_KeyData_T; +typedef int ( * BTreeCmpFunc )( const char * l, const char * r, size_t n ); + struct hb_BTree { BYTE * szFileName; @@ -319,7 +321,7 @@ struct hb_BTree void * BufferEnd; BOOL IsDirtyFlagAssignment; /* replaces const TRUE, and !GETFLAG( pBTree, IsInMemory ) */ - int ( *pStrCompare )( const char * l, const char * r, size_t n ); + BTreeCmpFunc pStrCompare; }; @@ -1636,11 +1638,11 @@ struct hb_BTree * hb_BTreeNew( BYTE * FileName, USHORT usPageSize, USHORT usKeyS if ( GETFLAG( pBTree, IsCaseLess ) ) { - pBTree->pStrCompare = hb_strnicmp; + pBTree->pStrCompare = ( BTreeCmpFunc ) hb_strnicmp; } else { - pBTree->pStrCompare = strncmp; + pBTree->pStrCompare = ( BTreeCmpFunc ) strncmp; } if ( GETFLAG( pBTree, IsInMemory ) == FALSE ) @@ -1722,11 +1724,11 @@ struct hb_BTree *hb_BTreeOpen( BYTE *FileName, ULONG ulFlags, USHORT usBuffers ) if ( GETFLAG( pBTree, IsCaseLess ) ) { - pBTree->pStrCompare = hb_strnicmp; + pBTree->pStrCompare = ( BTreeCmpFunc ) hb_strnicmp; } else { - pBTree->pStrCompare = strncmp; + pBTree->pStrCompare = ( BTreeCmpFunc ) strncmp; } return pBTree; diff --git a/harbour/contrib/libct/files.c b/harbour/contrib/libct/files.c index 63cb2491ca..c499b8e36f 100644 --- a/harbour/contrib/libct/files.c +++ b/harbour/contrib/libct/files.c @@ -284,45 +284,41 @@ HB_FUNC(SETFATTR) #endif #elif defined(HB_OS_WIN_32) - { +{ DWORD dwFlags=FILE_ATTRIBUTE_ARCHIVE; DWORD dwLastError=ERROR_SUCCESS; - int iAttr; LPCTSTR cFile=hb_parc(1); + int iAttr=hb_parni(2); BOOL lSuccess; - if (ISNUM(2)) - iAttr=hb_parni(2); - if( iAttr & FA_RDONLY ) - dwFlags |= FILE_ATTRIBUTE_READONLY; - if( iAttr & FA_HIDDEN ) - dwFlags |= FILE_ATTRIBUTE_HIDDEN; - - if( iAttr & FA_SYSTEM ) - dwFlags |= FILE_ATTRIBUTE_SYSTEM; - if( iAttr & FA_NORMAL ) - dwFlags |= FILE_ATTRIBUTE_NORMAL; - lSuccess=SetFileAttributes(cFile,dwFlags); - if (lSuccess) - hb_retni(dwLastError); - else + if( iAttr & FA_RDONLY ) + dwFlags |= FILE_ATTRIBUTE_READONLY; + if( iAttr & FA_HIDDEN ) + dwFlags |= FILE_ATTRIBUTE_HIDDEN; + if( iAttr & FA_SYSTEM ) + dwFlags |= FILE_ATTRIBUTE_SYSTEM; + if( iAttr & FA_NORMAL ) + dwFlags |= FILE_ATTRIBUTE_NORMAL; + lSuccess=SetFileAttributes(cFile,dwFlags); + if (lSuccess) + hb_retni(dwLastError); + else + { + dwLastError=GetLastError(); + switch (dwLastError) { - dwLastError=GetLastError(); - switch (dwLastError) - { - case ERROR_FILE_NOT_FOUND : - hb_retni(-2); - break; - case ERROR_PATH_NOT_FOUND : - hb_retni(-3); - break; - case ERROR_ACCESS_DENIED: - hb_retni(-5); - break; - } + case ERROR_FILE_NOT_FOUND : + hb_retni(-2); + break; + case ERROR_PATH_NOT_FOUND : + hb_retni(-3); + break; + case ERROR_ACCESS_DENIED: + hb_retni(-5); + break; } } - +} #else { hb_retnl(-1); diff --git a/harbour/contrib/ole/ole2.c b/harbour/contrib/ole/ole2.c index 9d39ae78b7..e887ac8d4a 100644 --- a/harbour/contrib/ole/ole2.c +++ b/harbour/contrib/ole/ole2.c @@ -75,11 +75,11 @@ #define HB_OS_WIN_32_USED -#include -#include +#include +#include -#include -#include +#include "hbvm.h" +#include "hbdate.h" static far VARIANTARG RetVal; static EXCEPINFO excep; @@ -133,9 +133,8 @@ static LPSTR WideToAnsi( LPSTR cWide ) static void GetParams(DISPPARAMS * dParams) { VARIANTARG * pArgs = NULL; - PHB_ITEM uParam, Self; + PHB_ITEM uParam; int n, nArgs, nArg; - double date; LPSTR cString; nArgs = hb_pcount() - 2; diff --git a/harbour/contrib/rdd_ads/ace.h b/harbour/contrib/rdd_ads/ace.h index 60580b320d..e345db9e6f 100644 --- a/harbour/contrib/rdd_ads/ace.h +++ b/harbour/contrib/rdd_ads/ace.h @@ -45,8 +45,9 @@ #if defined( WIN32 ) && !defined( ADS_LINUX ) /* 16-bit compiler doesn't seem to like this */ /* MingWin reports "warning: ignoring pragma: )" */ - #pragma warning( error : 4706 ) - + #if !defined( __GNUC__ ) + #pragma warning( error : 4706 ) + #endif #define ADS_PATH_DELIMITER '\\' #endif diff --git a/harbour/include/hbapi.h b/harbour/include/hbapi.h index 1524c8235b..9400b3f8f5 100644 --- a/harbour/include/hbapi.h +++ b/harbour/include/hbapi.h @@ -484,36 +484,53 @@ extern LONGLONG hb_arrayGetNLL( PHB_ITEM pArray, ULONG ulIndex ); /* retrieves ( c ) == HB_CHAR_LF || \ ( c ) == HB_CHAR_CR ) -extern int hb_stricmp( const char * s1, const char * s2 ); /* compare two strings without regards to case */ -extern int hb_strnicmp( const char * s1, const char * s2, size_t ulLen ); /* compare two string without regards to case, limited by length */ -extern char * hb_strupr( char * pszText ); /* convert a string in-place to upper-case */ -extern char * hb_strdup( const char * pszText ); /* returns a pointer to a newly allocated copy of the source string */ -extern BOOL hb_strMatchRegExp( const char * szString, const char * szMask ); /* compare two strings using a regular expression pattern */ -extern BOOL hb_strEmpty( const char * szText, ULONG ulLen ); /* returns whether a string contains only white space */ -extern void hb_strDescend( char * szStringTo, const char * szStringFrom, ULONG ulLen ); /* copy a string to a buffer, inverting each character */ -extern BOOL hb_strMatchWild(const char *szString, const char *szPattern ); /* compare two strings using pattern with wildcard (?*) */ -extern ULONG hb_strAt( const char * szSub, ULONG ulSubLen, const char * szText, ULONG ulLen ); /* returns an index to a sub-string within another string */ -extern char * hb_strUpper( char * szText, ULONG ulLen ); /* convert an existing string buffer to upper case */ -extern char * hb_strLower( char * szText, ULONG ulLen ); /* convert an existing string buffer to lower case */ -extern char * hb_strncpy( char * pDest, const char * pSource, ULONG ulLen ); /* copy at most ulLen bytes from string buffer to another buffer and _always_ set 0 in destin buffer */ -extern char * hb_strncat( char * pDest, const char * pSource, ULONG ulLen ); /* copy at most ulLen-strlen(pDest) bytes from string buffer to another buffer and _always_ set 0 in destin buffer */ -extern char * hb_strndup( const char * pszText, ULONG ulLen ); -extern char * hb_strncpyTrim( char * pDest, const char * pSource, ULONG ulLen ); -extern char * hb_strncpyUpper( char * pDest, const char * pSource, ULONG ulLen ); /* copy an existing string buffer to another buffer, as upper case */ -extern char * hb_strncpyUpperTrim( char * pDest, const char * pSource, ULONG ulLen ); -extern double hb_strVal( const char * szText, ULONG ulLen ); /* return the numeric value of a character string representation of a number */ -extern char * hb_strLTrim( const char * szText, ULONG * ulLen ); /* return a pointer to the first non-white space character */ -extern ULONG hb_strRTrimLen( const char * szText, ULONG ulLen, BOOL bAnySpace ); /* return length of a string, ignoring trailing white space (or true spaces) */ -extern BOOL hb_compStrToNum( const char* szNum, HB_LONG * plVal, double * pdVal, int * piDec, int * piWidth ); /* converts string to number, sets iDec, iWidth and returns TRUE if results is double */ -extern BOOL hb_valStrnToNum( const char* szNum, ULONG ulLen, HB_LONG * plVal, double * pdVal, int * piDec, int * piWidth ); -extern BOOL hb_strToNum( const char* szNum, HB_LONG * plVal, double * pdVal ); /* converts string to number, returns TRUE if results is double */ -extern BOOL hb_strnToNum( const char* szNum, ULONG ulLen, HB_LONG * plVal, double * pdVal ); /* converts string to number, returns TRUE if results is double */ -extern char * hb_xstrcat( char *dest, const char *src, ... ); /* Concatenates multiple strings into a single result */ -extern char * hb_xstrcpy( char *szDest, const char *szSrc, ...); /* Concatenates multiple strings into a single result */ +extern HB_EXPORT int hb_stricmp( const char * s1, const char * s2 ); /* compare two strings without regards to case */ +extern HB_EXPORT int hb_strnicmp( const char * s1, const char * s2, ULONG ulLen ); /* compare two string without regards to case, limited by length */ +extern HB_EXPORT char * hb_strupr( char * pszText ); /* convert a string in-place to upper-case */ +extern HB_EXPORT char * hb_strdup( const char * pszText ); /* returns a pointer to a newly allocated copy of the source string */ +extern HB_EXPORT char * hb_strndup( const char * pszText, ULONG ulLen ); /* returns a pointer to a newly allocated copy of the source string not longer then ulLen */ +extern HB_EXPORT ULONG hb_strnlen( const char * pszText, ULONG ulLen ); /* like strlen() but result is limited to ulLen */ +extern HB_EXPORT char * hb_xstrcat( char *dest, const char *src, ... ); /* Concatenates multiple strings into a single result */ +extern HB_EXPORT char * hb_xstrcpy( char *szDest, const char *szSrc, ...); /* Concatenates multiple strings into a single result */ +extern HB_EXPORT BOOL hb_compStrToNum( const char* szNum, HB_LONG * plVal, double * pdVal, int * piDec, int * piWidth ); /* converts string to number, sets iDec, iWidth and returns TRUE if results is double, used by compiler */ +extern HB_EXPORT BOOL hb_valStrnToNum( const char* szNum, ULONG ulLen, HB_LONG * plVal, double * pdVal, int * piDec, int * piWidth ); /* converts string to number, sets iDec, iWidth and returns TRUE if results is double, used by VAL() */ +extern HB_EXPORT BOOL hb_strToNum( const char* szNum, HB_LONG * plVal, double * pdVal ); /* converts string to number, returns TRUE if results is double */ +extern HB_EXPORT BOOL hb_strnToNum( const char* szNum, ULONG ulLen, HB_LONG * plVal, double * pdVal ); /* converts string to number, returns TRUE if results is double */ -extern double hb_numRound( double dResult, int iDec ); /* round a number to a specific number of digits */ -extern double hb_numInt( double dNum ); /* take the integer part of the number */ +extern HB_EXPORT BOOL hb_strMatchRegExp( const char * szString, const char * szMask ); /* compare two strings using a regular expression pattern */ +extern HB_EXPORT BOOL hb_strMatchWild(const char *szString, const char *szPattern ); /* compare two strings using pattern with wildcard (?*) */ +extern HB_EXPORT BOOL hb_strEmpty( const char * szText, ULONG ulLen ); /* returns whether a string contains only white space */ +extern HB_EXPORT void hb_strDescend( char * szStringTo, const char * szStringFrom, ULONG ulLen ); /* copy a string to a buffer, inverting each character */ +extern HB_EXPORT ULONG hb_strAt( const char * szSub, ULONG ulSubLen, const char * szText, ULONG ulLen ); /* returns an index to a sub-string within another string */ +extern HB_EXPORT char * hb_stripOutComments( char* buffer ); /* extract uncommented part of read buffer */ +extern HB_EXPORT char * hb_strUpper( char * szText, ULONG ulLen ); /* convert an existing string buffer to upper case */ +extern HB_EXPORT char * hb_strUpperCopy( char * szText, ULONG ulLen ); +extern HB_EXPORT char * hb_strLower( char * szText, ULONG ulLen ); /* convert an existing string buffer to lower case */ +extern HB_EXPORT char * hb_strncpy( char * pDest, const char * pSource, ULONG ulLen ); /* copy at most ulLen bytes from string buffer to another buffer and _always_ set 0 in destin buffer */ +extern HB_EXPORT char * hb_strncat( char * pDest, const char * pSource, ULONG ulLen ); /* copy at most ulLen-strlen(pDest) bytes from string buffer to another buffer and _always_ set 0 in destin buffer */ +extern HB_EXPORT char * hb_strncpyTrim( char * pDest, const char * pSource, ULONG ulLen ); +extern HB_EXPORT char * hb_strncpyUpper( char * pDest, const char * pSource, ULONG ulLen ); /* copy an existing string buffer to another buffer, as upper case */ +extern HB_EXPORT char * hb_strncpyUpperTrim( char * pDest, const char * pSource, ULONG ulLen ); +extern HB_EXPORT double hb_strVal( const char * szText, ULONG ulLen ); /* return the numeric value of a character string representation of a number */ +extern HB_EXPORT char * hb_strLTrim( const char * szText, ULONG * ulLen ); /* return a pointer to the first non-white space character */ +extern HB_EXPORT ULONG hb_strRTrimLen( const char * szText, ULONG ulLen, BOOL bAnySpace ); /* return length of a string, ignoring trailing white space (or true spaces) */ +extern HB_EXPORT double hb_numRound( double dResult, int iDec ); /* round a number to a specific number of digits */ +extern HB_EXPORT double hb_numInt( double dNum ); /* take the integer part of the number */ + +/* architecture dependent number conversions */ +extern HB_EXPORT void hb_put_ieee754( BYTE * ptr, double d ); +extern HB_EXPORT double hb_get_ieee754( BYTE * ptr ); +extern HB_EXPORT void hb_put_ord_ieee754( BYTE * ptr, double d ); +extern HB_EXPORT double hb_get_ord_ieee754( BYTE * ptr ); +extern HB_EXPORT double hb_get_rev_double( BYTE * ptr ); +extern HB_EXPORT double hb_get_std_double( BYTE * ptr ); + +#if defined( HB_LONG_LONG_OFF ) + extern HB_EXPORT double hb_get_le_int64( BYTE * ptr ); + extern HB_EXPORT double hb_get_le_uint64( BYTE * ptr ); + extern HB_EXPORT void hb_put_le_uint64( BYTE * ptr, double d ); +#endif /* class management */ extern void hb_clsReleaseAll( void ); /* releases all defined classes */ @@ -679,6 +696,7 @@ extern char * hb_verPlatform( void ); /* retrieves a newly allocated buffer cont extern char * hb_verCompiler( void ); /* retrieves a newly allocated buffer containing compiler version */ extern char * hb_verHarbour( void ); /* retrieves a newly allocated buffer containing harbour version */ extern void hb_verBuildInfo( void ); /* display harbour, compiler, and platform versions to standard console */ +extern BOOL HB_EXPORT hb_iswinnt(void); /* return .T. if OS == WinNt, 2000, XP */ /* environment variables access */ /* WARNING: This returned pointer must be freed if not NULL using hb_xfree( ( void * ) ptr ); */ diff --git a/harbour/include/hbapifs.h b/harbour/include/hbapifs.h index 706d68e354..7d681177dc 100644 --- a/harbour/include/hbapifs.h +++ b/harbour/include/hbapifs.h @@ -59,11 +59,13 @@ HB_EXTERN_BEGIN #define FS_ERROR F_ERROR -#if defined(X__WIN32__) + +#if defined( HB_WIN32_IO ) typedef long FHANDLE; #else -typedef int FHANDLE; +typedef int FHANDLE; #endif + /* File locking flags */ #define FL_LOCK 0x0000 /* Lock a region */ #define FL_UNLOCK 0x0001 /* Unlock a region */ @@ -89,7 +91,6 @@ typedef int FHANDLE; #define FXO_SHARELOCK 0x4000 /* emulate DOS SH_DENY* mode in POSIX OS */ #define FXO_COPYNAME 0x8000 /* copy final szPath into pFilename */ - /* File attributes flags */ #define HB_FA_ALL 0 #define HB_FA_READONLY 1 @@ -109,62 +110,70 @@ typedef int FHANDLE; #define HB_FA_ENCRYPTED 16384 #define HB_FA_VOLCOMP 32768 /* volume supports compression. */ -extern BOOL HB_EXPORT hb_fsChDir ( BYTE * pszDirName ); /* change working directory */ -extern USHORT HB_EXPORT hb_fsChDrv ( BYTE nDrive ); /* change working drive */ -extern void HB_EXPORT hb_fsClose ( FHANDLE hFileHandle ); /* close a file */ -extern void HB_EXPORT hb_fsCommit ( FHANDLE hFileHandle ); /* commit updates of a file */ -extern FHANDLE HB_EXPORT hb_fsCreate ( BYTE * pszFileName, USHORT uiAttr ); /* create a file */ -extern FHANDLE HB_EXPORT hb_fsCreateEx ( BYTE * pszFilename, USHORT uiAttr, USHORT uiFlags ); /* create a file, with specific open mode */ -extern FHANDLE HB_EXPORT hb_fsCreateTemp ( const BYTE * pszDir, const BYTE * pszPrefix, USHORT uiAttr, BYTE * pszName ); /* create a temporary file from components */ -extern BYTE HB_EXPORT * hb_fsCurDir ( USHORT uiDrive ); /* retrieve a static pointer containing current directory for specified drive */ -extern USHORT HB_EXPORT hb_fsCurDirBuff ( USHORT uiDrive, BYTE * pbyBuffer, ULONG ulLen ); /* copy current directory for given drive into a buffer */ -extern BYTE HB_EXPORT hb_fsCurDrv ( void ); /* retrieve current drive number */ -extern BOOL HB_EXPORT hb_fsDelete ( BYTE * pszFileName ); /* delete a file */ -extern BOOL HB_EXPORT hb_fsEof ( FHANDLE hFileHandle ); /* determine if an open file is position at end-of-file */ -extern USHORT HB_EXPORT hb_fsError ( void ); /* retrieve file system error */ -extern BOOL HB_EXPORT hb_fsFile ( BYTE * pszFileName ); /* determine if a file exists */ -extern ULONG HB_EXPORT hb_fsFSize ( BYTE * pszFileName, BOOL bUseDirEntry ); /* determine the size of a file */ -extern FHANDLE HB_EXPORT hb_fsExtOpen ( BYTE * pszFileName, BYTE * pDefExt, - USHORT uiFlags, BYTE * pPaths, PHB_ITEM pError ); /* open a file using default extension and a list of paths */ -extern USHORT HB_EXPORT hb_fsIsDrv ( BYTE nDrive ); /* determine if a drive number is a valid drive */ -extern BOOL HB_EXPORT hb_fsIsDevice ( FHANDLE hFileHandle ); /* determine if a file is attached to a device (console?) */ -extern BOOL HB_EXPORT hb_fsLock ( FHANDLE hFileHandle, ULONG ulStart, - ULONG ulLength, USHORT uiMode ); /* request a lock on a portion of a file */ -extern BOOL HB_EXPORT hb_fsLockLarge ( FHANDLE hFileHandle, HB_FOFFSET ulStart, - HB_FOFFSET ulLength, USHORT uiMode ); /* request a lock on a portion of a file using 64bit API */ -extern BOOL HB_EXPORT hb_fsMkDir ( BYTE * pszDirName ); /* create a directory */ -extern FHANDLE HB_EXPORT hb_fsOpen ( BYTE * pszFileName, USHORT uiFlags ); /* open a file */ -extern USHORT HB_EXPORT hb_fsRead ( FHANDLE hFileHandle, BYTE * pBuff, USHORT ulCount ); /* read contents of a file into a buffer (<=64K) */ -extern ULONG HB_EXPORT hb_fsReadLarge ( FHANDLE hFileHandle, BYTE * pBuff, ULONG ulCount ); /* read contents of a file into a buffer (>64K) */ -extern BOOL HB_EXPORT hb_fsRmDir ( BYTE * pszDirName ); /* remove a directory */ -extern BOOL HB_EXPORT hb_fsRename ( BYTE * pszOldName, BYTE * pszNewName ); /* rename a file */ -extern ULONG HB_EXPORT hb_fsSeek ( FHANDLE hFileHandle, LONG lOffset, USHORT uiMode ); /* reposition an open file */ + +extern BOOL HB_EXPORT hb_fsChDir ( BYTE * pszDirName ); /* change working directory */ +extern USHORT HB_EXPORT hb_fsChDrv ( BYTE nDrive ); /* change working drive */ +extern void HB_EXPORT hb_fsClose ( FHANDLE hFileHandle ); /* close a file */ +extern void HB_EXPORT hb_fsCommit ( FHANDLE hFileHandle ); /* commit updates of a file */ +extern FHANDLE HB_EXPORT hb_fsCreate ( BYTE * pszFileName, USHORT uiAttr ); /* create a file */ +extern FHANDLE HB_EXPORT hb_fsCreateEx ( BYTE * pszFilename, USHORT uiAttr, USHORT uiFlags ); /* create a file, with specific open mode */ +extern FHANDLE HB_EXPORT hb_fsCreateTemp ( const BYTE * pszDir, const BYTE * pszPrefix, USHORT uiAttr, BYTE * pszName ); /* create a temporary file from components */ +extern BYTE HB_EXPORT * hb_fsCurDir ( USHORT uiDrive ); /* retrieve a static pointer containing current directory for specified drive */ +extern USHORT HB_EXPORT hb_fsCurDirBuff ( USHORT uiDrive, BYTE * pbyBuffer, ULONG ulLen ); /* copy current directory for given drive into a buffer */ +extern BYTE HB_EXPORT hb_fsCurDrv ( void ); /* retrieve current drive number */ +extern BOOL HB_EXPORT hb_fsDelete ( BYTE * pszFileName ); /* delete a file */ +extern BOOL HB_EXPORT hb_fsEof ( FHANDLE hFileHandle ); /* determine if an open file is position at end-of-file */ +extern USHORT HB_EXPORT hb_fsError ( void ); /* retrieve file system error */ +extern USHORT HB_EXPORT hb_fsOsError ( void ); /* retrieve system dependant file system error */ +extern BOOL HB_EXPORT hb_fsFile ( BYTE * pszFileName ); /* determine if a file exists */ +extern ULONG HB_EXPORT hb_fsFSize ( BYTE * pszFileName, BOOL bUseDirEntry ); /* determine the size of a file */ +extern FHANDLE HB_EXPORT hb_fsExtOpen ( BYTE * pszFileName, BYTE * pDefExt, + USHORT uiFlags, BYTE * pPaths, PHB_ITEM pError ); /* open a file using default extension and a list of paths */ +extern USHORT HB_EXPORT hb_fsIsDrv ( BYTE nDrive ); /* determine if a drive number is a valid drive */ +extern BOOL HB_EXPORT hb_fsIsDevice ( FHANDLE hFileHandle ); /* determine if a file is attached to a device (console?) */ +extern BOOL HB_EXPORT hb_fsLock ( FHANDLE hFileHandle, ULONG ulStart, ULONG ulLength, USHORT uiMode ); /* request a lock on a portion of a file */ +extern BOOL HB_EXPORT hb_fsLockLarge ( FHANDLE hFileHandle, HB_FOFFSET ulStart, + HB_FOFFSET ulLength, USHORT uiMode ); /* request a lock on a portion of a file using 64bit API */ +extern BOOL HB_EXPORT hb_fsMkDir ( BYTE * pszDirName ); /* create a directory */ +extern FHANDLE HB_EXPORT hb_fsOpen ( BYTE * pszFileName, USHORT uiFlags ); /* open a file */ +extern USHORT HB_EXPORT hb_fsRead ( FHANDLE hFileHandle, BYTE * pBuff, USHORT ulCount ); /* read contents of a file into a buffer (<=64K) */ +extern ULONG HB_EXPORT hb_fsReadLarge ( FHANDLE hFileHandle, BYTE * pBuff, ULONG ulCount ); /* read contents of a file into a buffer (>64K) */ +extern BOOL HB_EXPORT hb_fsRmDir ( BYTE * pszDirName ); /* remove a directory */ +extern BOOL HB_EXPORT hb_fsRename ( BYTE * pszOldName, BYTE * pszNewName ); /* rename a file */ +extern ULONG HB_EXPORT hb_fsSeek ( FHANDLE hFileHandle, LONG lOffset, USHORT uiMode ); /* reposition an open file */ extern HB_FOFFSET HB_EXPORT hb_fsSeekLarge( FHANDLE hFileHandle, HB_FOFFSET llOffset, USHORT uiFlags ); /* reposition an open file using 64bit API */ -extern ULONG HB_EXPORT hb_fsTell ( FHANDLE hFileHandle ); /* retrieve the current position of a file */ -extern BOOL HB_EXPORT hb_fsSetDevMode ( FHANDLE hFileHandle, USHORT uiDevMode ); /* change the device mode of a file (text/binary) */ -extern void HB_EXPORT hb_fsSetError ( USHORT uiError ); /* set the file system error number */ -extern USHORT HB_EXPORT hb_fsWrite ( FHANDLE hFileHandle, BYTE * pBuff, USHORT ulCount ); /* write to an open file from a buffer (<=64K) */ -extern ULONG HB_EXPORT hb_fsWriteLarge ( FHANDLE hFileHandle, BYTE * pBuff, ULONG ulCount ); /* write to an open file from a buffer (>64K) */ -extern FHANDLE HB_EXPORT hb_fsPOpen ( BYTE * pFilename, BYTE * pMode ); +extern ULONG HB_EXPORT hb_fsTell ( FHANDLE hFileHandle ); /* retrieve the current position of a file */ +extern void HB_EXPORT hb_fsSetDevMode ( FHANDLE hFileHandle, USHORT uiDevMode ); /* change the device mode of a file (text/binary) */ +extern void HB_EXPORT hb_fsSetError ( USHORT uiError ); /* set the file system DOS error number */ +extern void HB_EXPORT hb_fsSetIOError ( BOOL fResult, USHORT uiOperation ); /* set the file system error number after IO operation */ +extern USHORT HB_EXPORT hb_fsWrite ( FHANDLE hFileHandle, BYTE * pBuff, USHORT ulCount ); /* write to an open file from a buffer (<=64K) */ +extern ULONG HB_EXPORT hb_fsWriteLarge ( FHANDLE hFileHandle, BYTE * pBuff, ULONG ulCount ); /* write to an open file from a buffer (>64K) */ +extern FHANDLE HB_EXPORT hb_fsPOpen( BYTE * pFilename, BYTE * pMode ); #define hb_fsFLock( h, s, l ) hb_fsLock( h, s, l, FL_LOCK ) #define hb_fsFUnlock( h, s, l ) hb_fsLock( h, s, l, FL_UNLOCK ) +#if defined( OS_UNIX_COMPATIBLE ) && !defined( HB_USE_SHARELOCKS_OFF ) +# define HB_USE_SHARELOCKS +# define HB_SHARELOCK_POS 0x7fffffffUL +# define HB_SHARELOCK_SIZE 0x1UL +#endif + #define HB_MAX_DRIVE_LENGTH 10 #define HB_MAX_FILE_EXT 10 /* Filename support */ typedef struct { - char szBuffer[ _POSIX_PATH_MAX + HB_MAX_DRIVE_LENGTH + HB_MAX_FILE_EXT + 1 ]; /* TOFIX: +10 is for the drive letter support, and should be changed to some manifest constant */ + char szBuffer[ _POSIX_PATH_MAX + HB_MAX_DRIVE_LENGTH + 4 ]; char * szPath; char * szName; char * szExtension; char * szDrive; } HB_FNAME, * PHB_FNAME, * HB_FNAME_PTR; -extern PHB_FNAME hb_fsFNameSplit( char * pszFileName ); /* Split given filename into path, name and extension */ -extern char * hb_fsFNameMerge( char * pszFileName, PHB_FNAME pFileName ); /* This function joins path, name and extension into a string with a filename */ +extern PHB_FNAME HB_EXPORT hb_fsFNameSplit( char * pszFileName ); /* Split given filename into path, name and extension */ +extern char HB_EXPORT * hb_fsFNameMerge( char * pszFileName, PHB_FNAME pFileName ); /* This function joins path, name and extension into a string with a filename */ /* Searchable path support */ typedef struct _HB_PATHNAMES @@ -173,12 +182,13 @@ typedef struct _HB_PATHNAMES struct _HB_PATHNAMES * pNext; } HB_PATHNAMES; -extern void hb_fsAddSearchPath( char * szPath, HB_PATHNAMES * * pSearchList ); +extern void HB_EXPORT hb_fsAddSearchPath( char * szPath, HB_PATHNAMES ** pSearchList ); +extern void HB_EXPORT hb_fsFreeSearchPath( HB_PATHNAMES * pSearchList ); -extern BOOL hb_spFile( BYTE * pFilename, BYTE RetPath[ _POSIX_PATH_MAX + HB_MAX_DRIVE_LENGTH + HB_MAX_FILE_EXT + 1 ] ); -extern FHANDLE hb_spOpen( BYTE * pFilename, USHORT uiFlags ); -extern FHANDLE hb_spCreate( BYTE * pFilename, USHORT uiAttr ); -extern FHANDLE hb_spCreateEx( BYTE * pFilename, USHORT uiAttr, USHORT uiFlags ); +extern BOOL HB_EXPORT hb_spFile( BYTE * pFilename, BYTE * pRetPath ); +extern FHANDLE HB_EXPORT hb_spOpen( BYTE * pFilename, USHORT uiFlags ); +extern FHANDLE HB_EXPORT hb_spCreate( BYTE * pFilename, USHORT uiAttr ); +extern FHANDLE HB_EXPORT hb_spCreateEx( BYTE * pFilename, USHORT uiAttr, USHORT uiFlags ); /* File Find API structure */ typedef struct @@ -210,8 +220,7 @@ extern USHORT hb_fsAttrFromRaw( ULONG raw_attr ); extern ULONG hb_fsAttrToRaw( USHORT uiAttr ); extern USHORT hb_fsAttrEncode( const char * szAttr ); extern char * hb_fsAttrDecode( USHORT uiAttr, char * szAttr ); -extern BYTE * hb_filecase ( char * ); /* Convert string to environment case */ -extern BYTE HB_EXPORT * hb_fileNameConv(char *str) ; +extern BYTE HB_EXPORT * hb_fileNameConv( char *str ); HB_EXTERN_END diff --git a/harbour/include/hbcomp.h b/harbour/include/hbcomp.h index 5e4cad4787..44d59acc90 100644 --- a/harbour/include/hbcomp.h +++ b/harbour/include/hbcomp.h @@ -147,7 +147,7 @@ typedef struct _VAR typedef struct __FUNC { char * szName; /* name of a defined Clipper function */ - char cScope; /* scope of a defined Clipper function */ + HB_SYMBOLSCOPE cScope; /* scope of a defined Clipper function */ BYTE bFlags; /* some flags we may need */ USHORT wParamCount; /* number of declared parameters */ USHORT wParamNum; /* current parameter number */ @@ -206,12 +206,12 @@ typedef struct /* compiler symbol support structure */ typedef struct _COMSYMBOL { - char * szName; /* the name of the symbol */ - char cScope; /* the scope of the symbol */ - BYTE cType; - BOOL bFunc; /* is it a function name (TRUE) or memvar (FALSE) */ - PCOMCLASS pClass; - struct _COMSYMBOL * pNext; /* pointer to the next defined symbol */ + char * szName; /* the name of the symbol */ + HB_SYMBOLSCOPE cScope; /* the scope of the symbol */ + BYTE cType; + BOOL bFunc; /* is it a function name (TRUE) or memvar (FALSE) */ + PCOMCLASS pClass; + struct _COMSYMBOL * pNext; /* pointer to the next defined symbol */ } COMSYMBOL, * PCOMSYMBOL; /* symbol table support structures */ diff --git a/harbour/include/hbdefs.h b/harbour/include/hbdefs.h index 181e6c9ba7..dcc8ae3b2a 100644 --- a/harbour/include/hbdefs.h +++ b/harbour/include/hbdefs.h @@ -66,12 +66,15 @@ #define HB_LONG_LONG_OFF */ -#if defined( _WIN64 ) -# undef HB_LONG_LONG_OFF -# define HB_STRICT_ALIGNMENT -#endif +#if defined( HB_OS_WIN_32 ) || defined( _WIN64 ) + #if defined( _WIN64 ) + #undef HB_LONG_LONG_OFF + #define HB_STRICT_ALIGNMENT + #if !defined( HB_OS_WIN_32 ) + #define HB_OS_WIN_32 + #endif + #endif -#if defined( HB_OS_WIN_32 ) #if !defined( HB_WIN32_IO_OFF ) #define HB_WIN32_IO #endif @@ -142,6 +145,14 @@ #define HB_XREGS x #endif +#elif defined( HB_OS_DARWIN ) + + /* Detect if it is Darwin < 6.x */ + #include + #ifndef PTHREAD_MUTEX_RECURSIVE + #define HB_OS_DARWIN_5 + #endif + #endif #if ! defined( HB_DONT_DEFINE_BASIC_TYPES ) @@ -173,6 +184,7 @@ #define TRUE (!0) #ifndef HB_LONG_LONG_OFF + #if ! defined(_WINNT_H) #if !defined(LONGLONG) #if defined(__GNUC__) @@ -190,38 +202,38 @@ #endif #endif - #ifdef __GNUC__ - #if defined(ULLONG_MAX) + #if !defined(ULONGLONG_MAX) + #if defined(_UI64_MAX) + #define ULONGLONG_MAX _UI64_MAX + #elif defined(ULLONG_MAX) #define ULONGLONG_MAX ULLONG_MAX #elif defined(ULONG_LONG_MAX) #define ULONGLONG_MAX ULONG_LONG_MAX #else #define ULONGLONG_MAX 18446744073709551615ULL #endif - #if defined(LLONG_MAX) + #endif + #if !defined(LONGLONG_MAX) + #if defined(_I64_MAX) + #define LONGLONG_MAX _I64_MAX + #elif defined(LLONG_MAX) #define LONGLONG_MAX LLONG_MAX #elif defined(LONG_LONG_MAX) #define LONGLONG_MAX LONG_LONG_MAX #else #define LONGLONG_MAX 9223372036854775807LL #endif - #if defined(LLONG_MIN) + #endif + #if !defined(LONGLONG_MIN) + #if defined(_I64_MIN) + #define LONGLONG_MIN _I64_MIN + #elif defined(LLONG_MIN) #define LONGLONG_MIN LLONG_MIN #elif defined(LONG_LONG_MIN) #define LONGLONG_MIN LONG_LONG_MIN #else #define LONGLONG_MIN (-LONGLONG_MAX - 1LL) #endif - #else - #if !defined(LONGLONG_MIN) - #define LONGLONG_MIN _I64_MIN - #endif - #if !defined(LONGLONG_MAX) - #define LONGLONG_MAX _I64_MAX - #endif - #if !defined(ULONGLONG_MAX) - #define ULONGLONG_MAX _UI64_MAX - #endif #endif #endif /* HB_LONG_LONG_OFF */ @@ -231,7 +243,9 @@ * below are some hacks which don't have to be true on some machines * please update it if necessary */ -#if ( ULONG_MAX > UINT_MAX && UINT_MAX > USHRT_MAX ) || defined( _WIN64 ) +#if defined( _WIN64 ) +# define HB_ARCH_64BIT +#elif ULONG_MAX > UINT_MAX && UINT_MAX > USHRT_MAX # define HB_ARCH_64BIT #elif ULONG_MAX == UINT_MAX && UINT_MAX > USHRT_MAX # define HB_ARCH_32BIT @@ -375,19 +389,33 @@ #define HB_LIM_INT32(l) ( INT32_MIN <= (l) && (l) <= INT32_MAX ) #define HB_LIM_INT64(l) ( INT64_MIN <= (l) && (l) <= INT64_MAX ) -#if HB_LONG_MAX > 10000000000 +/* + * It's a hack for MSC which doesn't support LL suffix for LONGLONG + * numeric constant. This suffix is necessary for some compilers - + * without it they cut the number to LONG + */ +#if ( defined( _MSC_VER ) || defined( __BORLANDC__ ) ) && !defined(__DMC__) +# define HB_LL( num ) num +#else +# define HB_LL( num ) num##LL +#endif + +#if HB_LONG_MAX > HB_LL( 10000000000 ) # define HB_LONG_LENGTH( l ) ( ( (l) <= -1000000000 || (l) >= HB_LL( 10000000000 ) ) ? 20 : 10 ) #else # define HB_LONG_LENGTH( l ) ( ( (l) <= -1000000000 ) ? 20 : 10 ) #endif + #if HB_INT_MIN <= -1000000000 # define HB_INT_LENGTH( i ) ( ( (i) <= -1000000000 ) ? 20 : 10 ) #else # define HB_INT_LENGTH( i ) 10 #endif + /* NOTE: Yes, -999999999.0 is right instead of -1000000000.0 [vszakats] */ /* This comment is from hb_vmNeg() - if it's true only in this case then the limit should be changed and this function fixed */ + #define HB_DBL_LENGTH( d ) ( ( (d) >= 10000000000.0 || (d) <= -999999999.0 ) ? 20 : 10 ) /* uncomment this if you need strict Clipper compatibility */ @@ -410,11 +438,11 @@ typedef unsigned long HB_COUNTER; #endif #ifdef HB_LONG_LONG_OFF - typedef LONG HB_FOFFSET; - /* we can add hack with double as work around what should - effectively give 52bit file size limit */ + typedef LONG HB_FOFFSET; + /* we can add hack with double as work around what should + effectively give 52bit file size limit */ #else - typedef LONGLONG HB_FOFFSET; + typedef LONGLONG HB_FOFFSET; #endif /* maximum length of double number in decimal representation: @@ -508,16 +536,6 @@ typedef unsigned long HB_COUNTER; ( ( ( UINT32 ) ( w ) & 0x00FF0000 ) >> 8 ) | \ ( ( ( UINT32 ) ( w ) & 0xFF000000 ) >> 24 ) ) ) -/* - * It's a hack for MSC which doesn't support LL suffix for LONGLONG - * numeric constant. This suffix is necessary for some compilers - - * without it they cut the number to LONG - */ -#if defined( _MSC_VER ) || defined( __BORLANDC__ ) -# define HB_LL( num ) ((LONGLONG)num) -#else -# define HB_LL( num ) num##LL -#endif #ifndef PFLL # if defined( __BORLANDC__ ) || defined( _MSC_VER ) @@ -542,7 +560,7 @@ typedef unsigned long HB_COUNTER; ( ( ( UINT64 ) ( w ) & HB_LL( 0x00FF000000000000 ) ) >> 40 ) | \ ( ( ( UINT64 ) ( w ) & HB_LL( 0xFF00000000000000 ) ) >> 56 ) ) ) -/* +/* * on some machines it's not safe to directly access pointers stored * at byte buffer they have to be stored at odd (or other alignment) * addresses. @@ -590,27 +608,135 @@ typedef unsigned long HB_COUNTER; # define HB_GET_PTR( p ) ( ( void * ) HB_GET_LONG( p ) ) #endif +/* Macros to store/retrive double value */ +#if defined( __GNUC__ ) +# define HB_GET_REV_DOUBLE( p ) \ + ( { \ + union { \ + double dbl; \ + BYTE buffer[ 8 ]; \ + } u; \ + u.buffer[ 0 ] = (( BYTE * )( p ))[ 7 ]; \ + u.buffer[ 1 ] = (( BYTE * )( p ))[ 6 ]; \ + u.buffer[ 2 ] = (( BYTE * )( p ))[ 5 ]; \ + u.buffer[ 3 ] = (( BYTE * )( p ))[ 4 ]; \ + u.buffer[ 4 ] = (( BYTE * )( p ))[ 3 ]; \ + u.buffer[ 5 ] = (( BYTE * )( p ))[ 2 ]; \ + u.buffer[ 6 ] = (( BYTE * )( p ))[ 1 ]; \ + u.buffer[ 7 ] = (( BYTE * )( p ))[ 0 ]; \ + u.dbl; \ + } ) +# define HB_GET_STD_DOUBLE( p ) \ + ( { \ + union { \ + double dbl; \ + BYTE buffer[ 8 ]; \ + } u; \ + u.buffer[ 0 ] = (( BYTE * )( p ))[ 0 ]; \ + u.buffer[ 1 ] = (( BYTE * )( p ))[ 1 ]; \ + u.buffer[ 2 ] = (( BYTE * )( p ))[ 2 ]; \ + u.buffer[ 3 ] = (( BYTE * )( p ))[ 3 ]; \ + u.buffer[ 4 ] = (( BYTE * )( p ))[ 4 ]; \ + u.buffer[ 5 ] = (( BYTE * )( p ))[ 5 ]; \ + u.buffer[ 6 ] = (( BYTE * )( p ))[ 6 ]; \ + u.buffer[ 7 ] = (( BYTE * )( p ))[ 7 ]; \ + u.dbl; \ + } ) +#else +# define HB_GET_REV_DOUBLE( p ) hb_get_rev_double( ( BYTE * ) ( p ) ) +# define HB_GET_STD_DOUBLE( p ) hb_get_std_double( ( BYTE * ) ( p ) ) +#endif + +#define HB_PUT_REV_DOUBLE( p, d ) \ + do { \ + union { \ + double dbl; \ + BYTE buffer[ 8 ]; \ + } u; \ + u.dbl = ( d ); \ + (( BYTE * )( p ))[ 7 ] = u.buffer[ 0 ]; \ + (( BYTE * )( p ))[ 6 ] = u.buffer[ 1 ]; \ + (( BYTE * )( p ))[ 5 ] = u.buffer[ 2 ]; \ + (( BYTE * )( p ))[ 4 ] = u.buffer[ 3 ]; \ + (( BYTE * )( p ))[ 3 ] = u.buffer[ 4 ]; \ + (( BYTE * )( p ))[ 2 ] = u.buffer[ 5 ]; \ + (( BYTE * )( p ))[ 1 ] = u.buffer[ 6 ]; \ + (( BYTE * )( p ))[ 0 ] = u.buffer[ 7 ]; \ + } while ( 0 ) +#define HB_PUT_STD_DOUBLE( p, d ) \ + do { \ + union { \ + double dbl; \ + BYTE buffer[ 8 ]; \ + } u; \ + u.dbl = ( d ); \ + (( BYTE * )( p ))[ 0 ] = u.buffer[ 0 ]; \ + (( BYTE * )( p ))[ 1 ] = u.buffer[ 1 ]; \ + (( BYTE * )( p ))[ 2 ] = u.buffer[ 2 ]; \ + (( BYTE * )( p ))[ 3 ] = u.buffer[ 3 ]; \ + (( BYTE * )( p ))[ 4 ] = u.buffer[ 4 ]; \ + (( BYTE * )( p ))[ 5 ] = u.buffer[ 5 ]; \ + (( BYTE * )( p ))[ 6 ] = u.buffer[ 6 ]; \ + (( BYTE * )( p ))[ 7 ] = u.buffer[ 7 ]; \ + } while ( 0 ) + +/* + * HB_FORCE_IEEE754_DOUBLE will can be used on platforms which use differ + * double format and we want to force storing double number as IEEE754 + * double value for sharing binary data (f.e. PCODE in .hrb files or CDX + * indexes or DBFs with "B" fields. + */ +#if defined( HB_FORCE_IEEE754_DOUBLE ) + +# define HB_GET_LE_DOUBLE( p ) hb_get_ieee754( ( BYTE * ) ( p ) ) +# define HB_PUT_LE_DOUBLE( p, d ) hb_put_ieee754( ( BYTE * ) ( p ), ( d ) ) +# define HB_DBL2ORD( d, o ) hb_put_ord_ieee754( ( o ), *( d ) ) +# define HB_ORD2DBL( o, d ) do { \ + *d = hb_get_ord_ieee754( ( BYTE * ) ( o ) ); \ + } while( 0 ) + +#elif defined( HB_STRICT_ALIGNMENT ) + +# if defined( HB_LITTLE_ENDIAN ) +# define HB_GET_LE_DOUBLE( p ) HB_GET_STD_DOUBLE( ( p ) ) +# define HB_PUT_LE_DOUBLE( p, d ) HB_PUT_STD_DOUBLE( ( p ), ( d ) ) +# elif defined( HB_BIG_ENDIAN ) +# define HB_GET_LE_DOUBLE( p ) HB_GET_REV_DOUBLE( ( p ) ) +# define HB_PUT_LE_DOUBLE( p, d ) HB_PUT_REV_DOUBLE( ( p ), ( d ) ) +# endif + +#else + +# if defined( HB_LITTLE_ENDIAN ) +# define HB_GET_LE_DOUBLE( p ) ( *( double * )( p ) ) +# define HB_PUT_LE_DOUBLE( p, d ) ( *( double * )( p ) = ( double ) ( d ) ) +# elif defined( HB_BIG_ENDIAN ) +# define HB_GET_LE_DOUBLE( p ) HB_GET_REV_DOUBLE( ( p ) ) +# define HB_PUT_LE_DOUBLE( p, d ) HB_PUT_REV_DOUBLE( ( p ), ( d ) ) +# endif + +#endif /* Now the rest of endian macros */ #if defined( HB_STRICT_ALIGNMENT ) || !defined( HB_LITTLE_ENDIAN ) #define HB_GET_LE_UINT16( p ) ( ( UINT16 ) \ - ( ( UINT16 ) (( BYTE * )( p ))[0] | \ - ( UINT16 ) (( BYTE * )( p ))[1] << 8 ) ) + ( ( ( UINT16 ) (( BYTE * )( p ))[0] ) | \ + ( ( UINT16 ) (( BYTE * )( p ))[1] << 8 ) ) ) #define HB_GET_LE_UINT32( p ) ( ( UINT32 ) \ - ( ( UINT32 ) (( BYTE * )( p ))[0] | \ - ( UINT32 ) (( BYTE * )( p ))[1] << 8 | \ - ( UINT32 ) (( BYTE * )( p ))[2] << 16 | \ - ( UINT32 ) (( BYTE * )( p ))[3] << 24 ) ) + ( ( ( UINT32 ) (( BYTE * )( p ))[0] ) | \ + ( ( UINT32 ) (( BYTE * )( p ))[1] << 8 ) | \ + ( ( UINT32 ) (( BYTE * )( p ))[2] << 16 ) | \ + ( ( UINT32 ) (( BYTE * )( p ))[3] << 24 ) ) ) #define HB_GET_LE_UINT64( p ) ( ( UINT64 ) \ - ( ( UINT64 ) (( BYTE * )( p ))[0] | \ - ( UINT64 ) (( BYTE * )( p ))[1] << 8 | \ - ( UINT64 ) (( BYTE * )( p ))[2] << 16 | \ - ( UINT64 ) (( BYTE * )( p ))[3] << 24 | \ - ( UINT64 ) (( BYTE * )( p ))[4] << 32 | \ - ( UINT64 ) (( BYTE * )( p ))[5] << 40 | \ - ( UINT64 ) (( BYTE * )( p ))[6] << 48 | \ - ( UINT64 ) (( BYTE * )( p ))[7] << 56 ) ) + ( ( ( UINT64 ) (( BYTE * )( p ))[0] ) | \ + ( ( UINT64 ) (( BYTE * )( p ))[1] << 8 ) | \ + ( ( UINT64 ) (( BYTE * )( p ))[2] << 16 ) | \ + ( ( UINT64 ) (( BYTE * )( p ))[3] << 24 ) | \ + ( ( UINT64 ) (( BYTE * )( p ))[4] << 32 ) | \ + ( ( UINT64 ) (( BYTE * )( p ))[5] << 40 ) | \ + ( ( UINT64 ) (( BYTE * )( p ))[6] << 48 ) | \ + ( ( UINT64 ) (( BYTE * )( p ))[7] << 56 ) ) ) #define HB_PUT_LE_UINT16( p, w ) do { \ (( BYTE * )( p ))[0] = ( BYTE )( w ); \ @@ -637,22 +763,22 @@ typedef unsigned long HB_COUNTER; #if defined( HB_STRICT_ALIGNMENT ) || !defined( HB_BIG_ENDIAN ) #define HB_GET_BE_UINT16( p ) ( ( UINT16 ) \ - ( ( UINT16 ) (( BYTE * )( p ))[0] << 8 | \ - ( UINT16 ) (( BYTE * )( p ))[1] ) ) + ( ( ( UINT16 ) (( BYTE * )( p ))[0] << 8 ) | \ + ( ( UINT16 ) (( BYTE * )( p ))[1] ) ) ) #define HB_GET_BE_UINT32( p ) ( ( UINT32 ) \ - ( ( UINT32 ) (( BYTE * )( p ))[0] << 24 | \ - ( UINT32 ) (( BYTE * )( p ))[1] << 16 | \ - ( UINT32 ) (( BYTE * )( p ))[2] << 8 | \ - ( UINT32 ) (( BYTE * )( p ))[3] ) ) + ( ( ( UINT32 ) (( BYTE * )( p ))[0] << 24 ) | \ + ( ( UINT32 ) (( BYTE * )( p ))[1] << 16 ) | \ + ( ( UINT32 ) (( BYTE * )( p ))[2] << 8 ) | \ + ( ( UINT32 ) (( BYTE * )( p ))[3] ) ) ) #define HB_GET_BE_UINT64( p ) ( ( UINT64 ) \ - ( ( UINT64 ) (( BYTE * )( p ))[0] << 56 | \ - ( UINT64 ) (( BYTE * )( p ))[1] << 48 | \ - ( UINT64 ) (( BYTE * )( p ))[2] << 40 | \ - ( UINT64 ) (( BYTE * )( p ))[3] << 32 | \ - ( UINT64 ) (( BYTE * )( p ))[4] << 24 | \ - ( UINT64 ) (( BYTE * )( p ))[5] << 16 | \ - ( UINT64 ) (( BYTE * )( p ))[6] << 8 | \ - ( UINT64 ) (( BYTE * )( p ))[7] ) ) + ( ( ( UINT64 ) (( BYTE * )( p ))[0] << 56 ) | \ + ( ( UINT64 ) (( BYTE * )( p ))[1] << 48 ) | \ + ( ( UINT64 ) (( BYTE * )( p ))[2] << 40 ) | \ + ( ( UINT64 ) (( BYTE * )( p ))[3] << 32 ) | \ + ( ( UINT64 ) (( BYTE * )( p ))[4] << 24 ) | \ + ( ( UINT64 ) (( BYTE * )( p ))[5] << 16 ) | \ + ( ( UINT64 ) (( BYTE * )( p ))[6] << 8 ) | \ + ( ( UINT64 ) (( BYTE * )( p ))[7] ) ) ) #define HB_PUT_BE_UINT16( p, w ) do { \ (( BYTE * )( p ))[0] = ( BYTE )( (w) >> 8 ); \ @@ -681,28 +807,28 @@ typedef unsigned long HB_COUNTER; * so we always have to build them from BYTEs and cannot use C casting */ #define HB_GET_LE_INT24( p ) ( ( INT32 ) \ - ( ( INT32 ) (( BYTE * )( p ))[0] | \ - ( INT32 ) (( BYTE * )( p ))[1] << 8 | \ - ( INT32 ) (( BYTE * )( p ))[2] << 16 | \ - ( INT32 ) ((( BYTE * )( p ))[2] & 0x80 ? 0xFF : 0x00 ) << 24 ) ) + ( ( ( INT32 ) (( BYTE * )( p ))[0] ) | \ + ( ( INT32 ) (( BYTE * )( p ))[1] << 8 ) | \ + ( ( INT32 ) (( BYTE * )( p ))[2] << 16 ) | \ + ( ( INT32 ) ((( BYTE * )( p ))[2] & 0x80 ? 0xFF : 0x00 ) << 24 ) ) ) #define HB_GET_LE_UINT24( p ) ( ( UINT32 ) \ - ( ( UINT32 ) (( BYTE * )( p ))[0] | \ - ( UINT32 ) (( BYTE * )( p ))[1] << 8 | \ - ( UINT32 ) (( BYTE * )( p ))[2] << 16 ) ) + ( ( ( UINT32 ) (( BYTE * )( p ))[0] ) | \ + ( ( UINT32 ) (( BYTE * )( p ))[1] << 8 ) | \ + ( ( UINT32 ) (( BYTE * )( p ))[2] << 16 ) ) ) #define HB_PUT_LE_UINT24( p, w ) do { \ (( BYTE * )( p ))[0] = ( BYTE )( w ); \ (( BYTE * )( p ))[1] = ( BYTE )( (w) >> 8 ); \ (( BYTE * )( p ))[2] = ( BYTE )( (w) >> 16 ); \ } while ( 0 ) #define HB_GET_BE_INT24( p ) ( ( INT32 ) \ - ( ( INT32 ) (( BYTE * )( p ))[2] | \ - ( INT32 ) (( BYTE * )( p ))[1] << 8 | \ - ( INT32 ) (( BYTE * )( p ))[0] << 16 | \ - ( INT32 ) ((( BYTE * )( p ))[0] & 0x80 ? 0xFF : 0x00 ) << 24 ) ) + ( ( ( INT32 ) (( BYTE * )( p ))[2] ) | \ + ( ( INT32 ) (( BYTE * )( p ))[1] << 8 ) | \ + ( ( INT32 ) (( BYTE * )( p ))[0] << 16 ) | \ + ( ( INT32 ) ((( BYTE * )( p ))[0] & 0x80 ? 0xFF : 0x00 ) << 24 ) ) ) #define HB_GET_BE_UINT24( p ) ( ( UINT32 ) \ - ( ( UINT32 ) (( BYTE * )( p ))[2] | \ - ( UINT32 ) (( BYTE * )( p ))[1] << 8 | \ - ( UINT32 ) (( BYTE * )( p ))[0] << 16 ) ) + ( ( ( UINT32 ) (( BYTE * )( p ))[2] ) | \ + ( ( UINT32 ) (( BYTE * )( p ))[1] << 8 ) | \ + ( ( UINT32 ) (( BYTE * )( p ))[0] << 16 ) ) ) #define HB_PUT_BE_UINT24( p, w ) do { \ (( BYTE * )( p ))[2] = ( BYTE )( w ); \ (( BYTE * )( p ))[1] = ( BYTE )( (w) >> 8 ); \ @@ -710,7 +836,6 @@ typedef unsigned long HB_COUNTER; } while ( 0 ) - #if defined( HB_PDP_ENDIAN ) #error PDP-Endian support unimplemented. If you have such machine do it yourself. #elif defined( HB_BIG_ENDIAN ) @@ -732,6 +857,7 @@ typedef unsigned long HB_COUNTER; #define HB_USHORT_TO_LE( w ) HB_USHORT_FROM_LE( w ) #define HB_ULONG_TO_LE( l ) HB_ULONG_FROM_LE( l ) +# ifndef HB_FORCE_IEEE754_DOUBLE #define HB_ORD2DBL( o, d ) do { \ if ( ( ( BYTE * ) ( o ) )[ 0 ] & 0x80 ) { \ ( ( BYTE * ) ( d ) )[ 0 ] = ( ( BYTE * ) ( o ) )[ 0 ]; \ @@ -755,7 +881,8 @@ typedef unsigned long HB_COUNTER; #define HB_DBL2ORD( d, o ) do { \ if ( *( double * )( d ) >= 0.0 ) { \ - ( ( BYTE * ) ( o ) )[ 0 ] = ( ( BYTE * ) ( d ) )[ 0 ] ^ ( BYTE ) 0x80; \ + if( *( double * )( d ) == -0.0 ) *( double * )( d ) = 0.0; \ + ( ( BYTE * ) ( o ) )[ 0 ] = ( ( BYTE * ) ( d ) )[ 0 ] ^ ( BYTE ) 0x80; \ ( ( BYTE * ) ( o ) )[ 1 ] = ( ( BYTE * ) ( d ) )[ 1 ]; \ ( ( BYTE * ) ( o ) )[ 2 ] = ( ( BYTE * ) ( d ) )[ 2 ]; \ ( ( BYTE * ) ( o ) )[ 3 ] = ( ( BYTE * ) ( d ) )[ 3 ]; \ @@ -773,66 +900,7 @@ typedef unsigned long HB_COUNTER; ( ( BYTE * ) ( o ) )[ 6 ] = ( ( BYTE * ) ( d ) )[ 6 ] ^ ( BYTE ) 0xFF; \ ( ( BYTE * ) ( o ) )[ 7 ] = ( ( BYTE * ) ( d ) )[ 7 ] ^ ( BYTE ) 0xFF; \ } } while ( 0 ) - -/* - #define HB_ORD2DBL( o, d ) do { \ - *( double * )( d ) = *( double * )( o ); \ - if ( ( ( BYTE * ) ( d ) )[ 0 ] & 0x80 ) { \ - ( ( BYTE * ) ( d ) )[ 0 ] ^= 0x80; \ - } else { \ - ( ( UINT32 * ) ( d ) )[ 0 ] ^= 0xFFFFFFFFL; \ - ( ( UINT32 * ) ( d ) )[ 1 ] ^= 0xFFFFFFFFL; \ - } } while ( 0 ) - #define HB_DBL2ORD( d, o ) do { \ - *( double * )( o ) = *( double * )( d ); \ - if ( *( double * )( o ) >= 0.0 ) { \ - ( ( BYTE * ) ( o ) )[ 0 ] ^= 0x80; \ - } else { \ - ( ( UINT32 * ) ( o ) )[ 0 ] ^= 0xFFFFFFFFL; \ - ( ( UINT32 * ) ( o ) )[ 1 ] ^= 0xFFFFFFFFL; \ - } } while ( 0 ) -*/ - -#if defined( __GNUC__ ) -/* Be careful with double conversion. Some machines can use mixed form - (Little/Big) for BYTE ORDER and WORD ORDER or even completely differ - internal representation */ - - #define HB_GET_LE_DOUBLE( p ) \ - ( { \ - union { \ - double dbl; \ - BYTE buffer[ 8 ]; \ - } u; \ - u.buffer[ 0 ] = (( BYTE * )( p ))[ 7 ]; \ - u.buffer[ 1 ] = (( BYTE * )( p ))[ 6 ]; \ - u.buffer[ 2 ] = (( BYTE * )( p ))[ 5 ]; \ - u.buffer[ 3 ] = (( BYTE * )( p ))[ 4 ]; \ - u.buffer[ 4 ] = (( BYTE * )( p ))[ 3 ]; \ - u.buffer[ 5 ] = (( BYTE * )( p ))[ 2 ]; \ - u.buffer[ 6 ] = (( BYTE * )( p ))[ 1 ]; \ - u.buffer[ 7 ] = (( BYTE * )( p ))[ 0 ]; \ - u.dbl; \ - } ) - #define HB_PUT_LE_DOUBLE( p, d ) \ - do { \ - union { \ - double dbl; \ - BYTE buffer[ 8 ]; \ - } u; \ - u.dbl = ( d ); \ - (( BYTE * )( p ))[ 7 ] = u.buffer[ 0 ]; \ - (( BYTE * )( p ))[ 6 ] = u.buffer[ 1 ]; \ - (( BYTE * )( p ))[ 5 ] = u.buffer[ 2 ]; \ - (( BYTE * )( p ))[ 4 ] = u.buffer[ 3 ]; \ - (( BYTE * )( p ))[ 3 ] = u.buffer[ 4 ]; \ - (( BYTE * )( p ))[ 2 ] = u.buffer[ 5 ]; \ - (( BYTE * )( p ))[ 1 ] = u.buffer[ 6 ]; \ - (( BYTE * )( p ))[ 0 ] = u.buffer[ 7 ]; \ - } while ( 0 ) -#else - #error Little-Endian IEEE 754 double type conversion unimplemented with a non-GCC compiler -#endif +# endif #else /* HB_LITTLE_ENDIAN */ /* We use Little-Endian here */ @@ -848,14 +916,12 @@ typedef unsigned long HB_COUNTER; # endif - #define HB_GET_LE_DOUBLE( p ) ( *( double * )( p ) ) - #define HB_PUT_LE_DOUBLE( p, d ) ( *( double * )( p ) = ( double ) ( d ) ) - #define HB_USHORT_FROM_LE( w ) ( ( USHORT )( w ) ) #define HB_ULONG_FROM_LE( l ) ( ( ULONG )( l ) ) #define HB_USHORT_TO_LE( w ) ( ( USHORT )( w ) ) #define HB_ULONG_TO_LE( l ) ( ( ULONG )( l ) ) +# ifndef HB_FORCE_IEEE754_DOUBLE #define HB_ORD2DBL( o, d ) do { \ if ( ( ( BYTE * ) ( o ) )[ 0 ] & 0x80 ) { \ ( ( BYTE * ) ( d ) )[ 0 ] = ( ( BYTE * ) ( o ) )[ 7 ]; \ @@ -879,7 +945,8 @@ typedef unsigned long HB_COUNTER; #define HB_DBL2ORD( d, o ) do { \ if ( *( double * )( d ) >= 0.0 ) { \ - ( ( BYTE * ) ( o ) )[ 0 ] = ( ( BYTE * ) ( d ) )[ 7 ] ^ ( BYTE ) 0x80; \ + if( *( double * )( d ) == -0.0 ) *( double * )( d ) = 0.0; \ + ( ( BYTE * ) ( o ) )[ 0 ] = ( ( BYTE * ) ( d ) )[ 7 ] ^ ( BYTE ) 0x80; \ ( ( BYTE * ) ( o ) )[ 1 ] = ( ( BYTE * ) ( d ) )[ 6 ]; \ ( ( BYTE * ) ( o ) )[ 2 ] = ( ( BYTE * ) ( d ) )[ 5 ]; \ ( ( BYTE * ) ( o ) )[ 3 ] = ( ( BYTE * ) ( d ) )[ 4 ]; \ @@ -897,6 +964,7 @@ typedef unsigned long HB_COUNTER; ( ( BYTE * ) ( o ) )[ 6 ] = ( ( BYTE * ) ( d ) )[ 1 ] ^ ( BYTE ) 0xFF; \ ( ( BYTE * ) ( o ) )[ 7 ] = ( ( BYTE * ) ( d ) )[ 0 ] ^ ( BYTE ) 0xFF; \ } } while ( 0 ) +# endif #endif @@ -926,24 +994,21 @@ typedef unsigned long HB_COUNTER; #undef HB_PCODE_MKLONGLONG #undef HB_PCODE_MKULONGLONG #undef HB_DBL_LIM_INT64 - #define UINT64_MAXDBL ( (( double ) UINT32_MAX + 1.0) * (( double ) UINT32_MAX + 1.0) - 1 ) - #define HB_GET_LE_INT64( p ) ( ( double ) HB_GET_LE_UINT32( p ) + \ - ( double ) HB_GET_LE_UINT32( p + 4 ) * UINT32_MAX - \ - ((( BYTE * )( p ))[7] & 0x80 ? UINT64_MAXDBL : 0 ) ) - #define HB_GET_LE_UINT64( p ) ( ( double ) HB_GET_LE_UINT32( p ) + \ - ( double ) HB_GET_LE_UINT32( p + 4 ) * UINT32_MAX ) - #define HB_PUT_LE_UINT64( p, w ) do { \ - double _d = ( double ) ( w ); \ - if ( _d < 0 ) \ - _d += UINT64_MAXDBL; \ - HB_PUT_LE_UINT32( p, ( UINT32 ) _d ); \ - HB_PUT_LE_UINT32( p + 4, ( UINT32 ) ( _d / ( double ) UINT32_MAX ) ); \ - } while ( 0 ) + #define UINT64_MAXDBL ( (( double ) UINT32_MAX + 1.0) * \ + (( double ) UINT32_MAX + 1.0) - 1.0 ) + #define HB_GET_LE_INT64( p ) hb_get_le_int64( ( BYTE * ) ( p ) ) + #define HB_GET_LE_UINT64( p ) hb_get_le_uint64( ( BYTE * ) ( p ) ) + #define HB_PUT_LE_UINT64( p, d ) hb_put_le_uint64( ( BYTE * ) ( p ), \ + ( double ) ( d ) ) #define HB_PCODE_MKLONGLONG( p ) (( double ) HB_GET_LE_INT64( p )) #define HB_PCODE_MKULONGLONG( p ) (( double ) HB_GET_LE_UINT64( p )) - #define HB_DBL_LIM_INT64(d) ( (HB_MAXDBL) -UINT64_MAXDBL / 2 - 1 <= (HB_MAXDBL) (d) && (HB_MAXDBL) (d) <= (HB_MAXDBL) UINT64_MAXDBL / 2 ) + #define HB_DBL_LIM_INT64(d) ( (HB_MAXDBL) -UINT64_MAXDBL / 2 - 1 <= \ + (HB_MAXDBL) (d) && (HB_MAXDBL) (d) <= \ + (HB_MAXDBL) UINT64_MAXDBL / 2 ) #endif +#define HB_MACRO2STRING( macro ) HB_MACRO2STRING_( macro ) +#define HB_MACRO2STRING_( macro ) #macro #define HB_SYMBOL_UNUSED( symbol ) ( void ) symbol @@ -1032,7 +1097,7 @@ typedef PHB_FUNC HB_FUNC_PTR; #define HB_FUNC_EXIT( funcname ) HB_EXTERN_C_ static HARBOUR HB_FUN_exit_##funcname ( void ) typedef ULONG HB_HANDLE; /* handle to memvar value */ -typedef char HB_SYMBOLSCOPE; /* stores symbol's scope */ +typedef SHORT HB_SYMBOLSCOPE; /* stores symbol's scope */ typedef BYTE HB_CHAR; typedef BYTE HB_ATTR; diff --git a/harbour/make_gnu.sh b/harbour/make_gnu.sh index 5a84c9dbd0..dd39b72b3b 100644 --- a/harbour/make_gnu.sh +++ b/harbour/make_gnu.sh @@ -15,15 +15,17 @@ # See doc/license.txt for licensing terms. # --------------------------------------------------------------- +name="harbour" + if [ -z "$HB_ARCHITECTURE" ]; then if [ "$OSTYPE" = "msdosdjgpp" ]; then hb_arch="dos" else hb_arch=`uname -s | tr -d "[-]" | tr '[A-Z]' '[a-z]' 2>/dev/null` case "$hb_arch" in - *windows*) hb_arch="w32" ;; - *dos) hb_arch="dos" ;; - *bsd) hb_arch="bsd" ;; + *windows*|*mingw32*) hb_arch="w32" ;; + *dos) hb_arch="dos" ;; + *bsd) hb_arch="bsd" ;; esac fi export HB_ARCHITECTURE="$hb_arch" @@ -70,13 +72,25 @@ fi # export C_USR= # export L_USR= -if [ -z "$PREFIX" ]; then export PREFIX=/usr/local; fi +[ -z "$HB_INSTALL_PREFIX" ] && [ -n "$PREFIX" ] && export HB_INSTALL_PREFIX="$PREFIX" +[ -z "$HB_INSTALL_PREFIX" ] && export HB_INSTALL_PREFIX=/usr/local # Set to constant value to be consistent with the non-GNU make files. -if [ -z "$HB_BIN_INSTALL" ]; then export HB_BIN_INSTALL=$PREFIX/bin/; fi -if [ -z "$HB_LIB_INSTALL" ]; then export HB_LIB_INSTALL=$PREFIX/lib/harbour/; fi -if [ -z "$HB_INC_INSTALL" ]; then export HB_INC_INSTALL=$PREFIX/include/harbour/; fi +case "$HB_INSTALL_PREFIX" in + /usr|/usr/local|/opt) + hb_instsubdir="/$name" + ;; + *) + hb_instsubdir="" + ;; +esac + +if [ -z "$HB_BIN_INSTALL" ]; then export HB_BIN_INSTALL=$HB_INSTALL_PREFIX/bin; fi +if [ -z "$HB_LIB_INSTALL" ]; then export HB_LIB_INSTALL=$HB_INSTALL_PREFIX/lib$hb_instsubdir; fi +if [ -z "$HB_INC_INSTALL" ]; then export HB_INC_INSTALL=$HB_INSTALL_PREFIX/include$hb_instsubdir; fi + + if [ -z "$HB_ARCHITECTURE" ]; then echo "Error: HB_ARCHITECTURE is not set." @@ -115,7 +129,7 @@ if [ -z "$HB_ARCHITECTURE" ] || [ -z "$HB_COMPILER" ]; then echo " - When HB_ARCHITECTURE=dos" echo " - bcc16 (Borland C++ 3.x, 4.x, 5.0x, DOS 16-bit)" echo " - djgpp (Delorie GNU C, DOS 32-bit)" - echo " - rxs32 (EMX/RSXNT/DOS GNU C, DOS 32-bit)" + echo " - rsx32 (EMX/RSXNT/DOS GNU C, DOS 32-bit)" echo " - watcom (Watcom C++ 9.x, 10.x, 11.x, DOS 32-bit)" echo " - When HB_ARCHITECTURE=w32" echo " - bcc32 (Borland C++ 4.x, 5.x, Windows 32-bit)" @@ -153,7 +167,7 @@ else # --------------------------------------------------------------- # Start the GNU make system - if [ "$HB_ARCHITECTURE" = "bsd" ] || [ `uname` = "FreeBSD" ]; then + if [ "$HB_ARCHITECTURE" = "bsd" ] || uname|grep "BSD$" &> /dev/null; then gmake $* else make $* diff --git a/harbour/make_xmingw.sh b/harbour/make_xmingw.sh new file mode 100644 index 0000000000..f9220baa4d --- /dev/null +++ b/harbour/make_xmingw.sh @@ -0,0 +1,66 @@ +#!/bin/sh +[ "$BASH" ] || exec bash `which $0` ${1+"$@"} +# +# $Id$ +# +# This script simplifies cross-compiling xHarbour for Windows from Unix systems. +# +# Copyright 2003-2005 by Phil Krylov +# + +UNAME=`uname` + +export HB_ARCHITECTURE=w32 +export HB_COMPILER=mingw32 + +[ -z "$HB_INSTALL_PREFIX" ] && export HB_INSTALL_PREFIX=/usr/local/mingw32-harbour +export CC_C_USR="-DHOST_OS_UNIX_COMPATIBLE" +export C_USR="$CC_C_USR $C_USR" +export CC_PRG_USR="-D__PLATFORM__Windows -undef:__PLATFORM__UNIX -undef:__PLATFORM__$UNAME" +export PRG_USR="$CC_PRG_USR $PRG_USR" + +if [ -f /etc/debian-version ]; then + MINGW_PREFIX=/usr + TARGET=i586-mingw32msvc + CCPREFIX="$TARGET-" +elif [ -f /etc/gentoo-release ]; then + MINGW_PREFIX=/opt/xmingw + TARGET=i386-mingw32msvc + CCPREFIX="$TARGET-" +elif [ "$UNAME" = "FreeBSD" ]; then + MINGW_PREFIX=/usr/local/mingw32 + TARGET="." + CCPREFIX="" +elif find /usr/local/bin -name "i[3456]86-mingw*-gcc" -maxdepth 1 &>/dev/null; then + MINGW_PREFIX=/usr/local + TARGET=`find /usr/local/bin -name "i[3456]86-mingw*-gcc" -maxdepth 1|sed -e '1 !d' -e 's/.*\(i[3456]86-mingw[^-]*\).*/\1/g'` + CCPREFIX="$TARGET-" +else + echo "Can't determine the location for the MinGW32 cross-compiler." + echo "Please add your platform to the $0 script." + exit 1 +fi +CCPATH="$MINGW_PREFIX/bin:$MINGW_PREFIX/$TARGET/bin:" +PATH="$CCPATH$PATH" + +if which harbour &> /dev/null; then + rm -f -r /tmp/harbour.exe + ln -s `which harbour` /tmp/harbour.exe + export HB_BIN_COMPILE=/tmp +else + echo "You must have a working Harbour executable for your platform on your PATH." + exit 1 +fi + +export PATH CCPATH CCPREFIX + +case "$1" in + tgz|gnu) + ext=$1 + shift + . `dirname $0`/make_${ext}.sh "$@" + ;; + *) + . `dirname $0`/make_gnu.sh "$@" + ;; +esac diff --git a/harbour/source/common/Makefile b/harbour/source/common/Makefile index 7518cbd775..5cec42e86d 100644 --- a/harbour/source/common/Makefile +++ b/harbour/source/common/Makefile @@ -13,6 +13,7 @@ C_SOURCES=\ hbtrace.c \ hbver.c \ hbverdsp.c \ + hbarch.c \ reserved.c \ expropt1.c \ expropt2.c \ diff --git a/harbour/source/common/hbarch.c b/harbour/source/common/hbarch.c new file mode 100644 index 0000000000..1230bc7eef --- /dev/null +++ b/harbour/source/common/hbarch.c @@ -0,0 +1,313 @@ +/* + * $Id$ + */ + +/* + * xHarbour Project source code: + * Architecture dependent conversions + * + * Copyright 2005 Przemyslaw Czerpak + * www - http://www.xharbour.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/). + * + * As a special exception, the Harbour Project gives permission for + * additional uses of the text contained in its release of Harbour. + * + * The exception is that, if you link the Harbour libraries with other + * files to produce an executable, this does not by itself cause the + * resulting executable to be covered by the GNU General Public License. + * Your use of that executable is in no way restricted on account of + * linking the Harbour library code into it. + * + * This exception does not however invalidate any other reasons why + * the executable file might be covered by the GNU General Public License. + * + * This exception applies only to the code released by the Harbour + * Project under the name Harbour. If you copy code from other + * Harbour Project or Free Software Foundation releases into a copy of + * Harbour, as the General Public License permits, the exception does + * not apply to the code that you add in this way. To avoid misleading + * anyone as to the status of such modified files, you must delete + * this exception notice from them. + * + * If you write modifications of your own for Harbour, it is your choice + * whether to permit this exception to apply to your modifications. + * If you do not wish that, delete this exception notice. + * + */ + +#include "hbapi.h" +#include "hbmath.h" + +/* + * functions hb_put_ieee754() and hb_get_ieee754() stores / retrieve + * IEEE754 double value making conversion from/to native C double type. + * They should be used on platforms which does not use IEEE754 double + * and user needs binary compatibility, f.e. he wants to share CDXs or + * or DBFs with "B" fields with other station or use common .hrb files + * functions hb_put_ord_ieee754() and hb_get_ord_ieee754() converts + * to/from special modified IEEE754 double form used by some index formats + * like CDX or NSX to create index keys. In this form double numbers can + * be sorted as 8-bytes character values (f.e. with memcmp()) + */ + +#define HB_MANTISSA_BITS 52 +#define HB_MANTISSA_MASK ( ( ( UINT64 ) 1 << HB_MANTISSA_BITS ) - 1 ) +#define HB_EXPONENT_BITS 11 +#define HB_EXPONENT_MASK ( ( 1 << HB_EXPONENT_BITS ) - 1 ) +#define HB_EXPONENT_ADD 0x3ff + +void HB_EXPORT hb_put_ieee754( BYTE * ptr, double d ) +{ + int iExp, iSig; + double df; +#if defined( HB_LONG_LONG_OFF ) + UINT32 l1, l2; + + HB_TRACE(HB_TR_DEBUG, ("hb_put_ieee754(%p, %f)", ptr, d)); + + iSig = d < 0 ? 1 : 0; + if( d == 0.0 ) + { + l1 = l2 = 0; + } + else + { + df = frexp( iSig ? -d : d, &iExp ); + l1 = ( UINT32 ) ldexp( df, HB_MANTISSA_BITS + 1 ); + l2 = ( UINT32 ) ldexp( df, HB_MANTISSA_BITS + 1 - 32 ) & + ( ( ( UINT32 ) 1 << ( HB_MANTISSA_BITS - 32 ) ) - 1 ); + l2 |= ( UINT32 ) ( ( iExp + HB_EXPONENT_ADD - 1 ) & HB_EXPONENT_MASK ) << + ( HB_MANTISSA_BITS - 32 ); + } + l2 |= ( UINT32 ) iSig << ( HB_MANTISSA_BITS + HB_EXPONENT_BITS - 32 ); + HB_PUT_LE_UINT32( ptr, l1 ); + HB_PUT_LE_UINT32( ptr + 4, l2 ); +#else + UINT64 ll; + + HB_TRACE(HB_TR_DEBUG, ("hb_put_ieee754(%p, %f)", ptr, d)); + + iSig = d < 0 ? 1 : 0; + if( d == 0.0 ) + { + ll = 0; + } + else + { + df = frexp( iSig ? -d : d, &iExp ); + ll = ( UINT64 ) ldexp( df, HB_MANTISSA_BITS + 1 ) & HB_MANTISSA_MASK; + ll |= ( UINT64 ) ( ( iExp + HB_EXPONENT_ADD - 1 ) & HB_EXPONENT_MASK ) << + HB_MANTISSA_BITS; + } + ll |= ( UINT64 ) iSig << ( HB_MANTISSA_BITS + HB_EXPONENT_BITS ); + HB_PUT_LE_UINT64( ptr, ll ); +#endif +} + +double HB_EXPORT hb_get_ieee754( BYTE * ptr ) +{ + int iExp, iSig; +#if defined( HB_LONG_LONG_OFF ) + UINT32 l1, l2; + double d; + + HB_TRACE(HB_TR_DEBUG, ("hb_get_ieee754(%p)", ptr)); + + l1 = HB_GET_LE_UINT32( ptr ); + l2 = HB_GET_LE_UINT32( ptr + 4 ); + iSig = ( int ) ( l2 >> ( HB_MANTISSA_BITS + HB_EXPONENT_BITS - 32 ) ) & 1; + iExp = ( int ) ( ( l2 >> ( HB_MANTISSA_BITS - 32 ) ) & HB_EXPONENT_MASK ); + l2 &= ( ( UINT32 ) 1 << ( HB_MANTISSA_BITS - 32 ) ) - 1; + + if( ( l1 | l2 | iExp ) != 0 ) + l2 |= ( UINT32 ) 1 << ( HB_MANTISSA_BITS - 32 ); + + d = ldexp( ( double ) l2, 32 ) + ( double ) l1; + return ldexp( iSig ? -d : d, iExp - HB_MANTISSA_BITS - HB_EXPONENT_ADD ); +#else + UINT64 ll; + + HB_TRACE(HB_TR_DEBUG, ("hb_get_ieee754(%p)", ptr)); + + ll = HB_GET_LE_UINT64( ptr ); + iSig = ( int ) ( ll >> ( HB_MANTISSA_BITS + HB_EXPONENT_BITS ) ) & 1; + iExp = ( int ) ( ( ll >> HB_MANTISSA_BITS ) & HB_EXPONENT_MASK ); + ll &= HB_MANTISSA_MASK; + if( ( ll | iExp ) != 0 ) + ll |= ( UINT64 ) 1 << HB_MANTISSA_BITS; + /* the casting form UINT64 to INT64 is necessary for some + compilers which does not support UINT64 -> double conversion + It will not change results because there is only up to 53bits + set in mantissa */ + return ldexp( iSig ? -( double ) ( INT64 ) ll : ( double ) ( INT64 ) ll, + iExp - HB_MANTISSA_BITS - HB_EXPONENT_ADD ); +#endif +} + +void HB_EXPORT hb_put_ord_ieee754( BYTE * ptr, double d ) +{ + int iExp, iSig; + double df; + UINT32 l1, l2; + + HB_TRACE(HB_TR_DEBUG, ("hb_put_ord_ieee754(%p, %f)", ptr, d)); + + iSig = d < 0 ? 1 : 0; + if( d == 0.0 ) + { + l1 = l2 = 0; + } + else + { + df = frexp( iSig ? -d : d, &iExp ); + l1 = ( UINT32 ) ldexp( df, HB_MANTISSA_BITS + 1 ); + l2 = ( UINT32 ) ldexp( df, HB_MANTISSA_BITS + 1 - 32 ) & + ( ( ( UINT32 ) 1 << ( HB_MANTISSA_BITS - 32 ) ) - 1 ); + l2 |= ( UINT32 ) ( ( iExp + HB_EXPONENT_ADD - 1 ) & HB_EXPONENT_MASK ) << + ( HB_MANTISSA_BITS - 32 ); + } + if( iSig ) + { + l2 ^= 0x7FFFFFFFL; + l1 ^= 0xFFFFFFFFL; + } + else + { + l2 ^= 0x80000000L; + } + HB_PUT_BE_UINT32( ptr, l2 ); + HB_PUT_BE_UINT32( ptr + 4, l1 ); +} + +double HB_EXPORT hb_get_ord_ieee754( BYTE * ptr ) +{ + int iExp, iSig; + UINT32 l1, l2; + double d; + + HB_TRACE(HB_TR_DEBUG, ("hb_get_ord_ieee754(%p)", ptr)); + + l1 = HB_GET_BE_UINT32( ptr + 4 ); + l2 = HB_GET_BE_UINT32( ptr ); + iSig = ( l2 & 0x80000000L ) ? 0 : 1; + if( iSig ) + { + l2 ^= 0x7FFFFFFFL; + l1 ^= 0xFFFFFFFFL; + } + iExp = ( ( l2 >> ( HB_MANTISSA_BITS - 32 ) ) & HB_EXPONENT_MASK ); + l2 &= ( ( UINT32 ) 1 << ( HB_MANTISSA_BITS - 32 ) ) - 1; + + if( ( l1 | l2 | iExp ) != 0 ) + l2 |= ( UINT32 ) 1 << ( HB_MANTISSA_BITS - 32 ); + + d = ldexp( ( double ) l2, 32 ) + ( double ) l1; + return ldexp( iSig ? -d : d, iExp - HB_MANTISSA_BITS - HB_EXPONENT_ADD ); +} + +/* + * I added function hb_get_rev_double() and hb_get_std_double() because + * some compilers does not like constraction used by in HB_GET_LE_DOUBLE + * macro => d = { ... } + */ +double HB_EXPORT hb_get_rev_double( BYTE * ptr ) +{ + union { + double dbl; + BYTE buffer[ 8 ]; + } u; + + HB_TRACE(HB_TR_DEBUG, ("hb_get_rev_double(%p)", ptr)); + + u.buffer[ 0 ] = ptr[ 7 ]; + u.buffer[ 1 ] = ptr[ 6 ]; + u.buffer[ 2 ] = ptr[ 5 ]; + u.buffer[ 3 ] = ptr[ 4 ]; + u.buffer[ 4 ] = ptr[ 3 ]; + u.buffer[ 5 ] = ptr[ 2 ]; + u.buffer[ 6 ] = ptr[ 1 ]; + u.buffer[ 7 ] = ptr[ 0 ]; + + return u.dbl; +} + +double HB_EXPORT hb_get_std_double( BYTE * ptr ) +{ + union { + double dbl; + BYTE buffer[ 8 ]; + } u; + + HB_TRACE(HB_TR_DEBUG, ("hb_get_std_double(%p)", ptr)); + + u.buffer[ 0 ] = ptr[ 0 ]; + u.buffer[ 1 ] = ptr[ 1 ]; + u.buffer[ 2 ] = ptr[ 2 ]; + u.buffer[ 3 ] = ptr[ 3 ]; + u.buffer[ 4 ] = ptr[ 4 ]; + u.buffer[ 5 ] = ptr[ 5 ]; + u.buffer[ 6 ] = ptr[ 6 ]; + u.buffer[ 7 ] = ptr[ 7 ]; + + return u.dbl; +} + +#if defined( HB_LONG_LONG_OFF ) + +/* + * The function below are only for platforms which do not support + * 64 but integer values. So the convert them to/from 'double' + * values. They are necessary for extracting such number from PCODE, + * databases or serialization streams in RPC + */ +double HB_EXPORT hb_get_le_uint64( BYTE * ptr ) +{ + UINT32 l1, l2; + + HB_TRACE(HB_TR_DEBUG, ("hb_get_le_uint64(%p)", ptr)); + + l1 = HB_GET_LE_UINT32( ptr ); + l2 = HB_GET_LE_UINT32( ptr + 4 ); + return ldexp( ( double ) l2, 32 ) + ( double ) l1; +} + +double HB_EXPORT hb_get_le_int64( BYTE * ptr ) +{ + UINT32 l1; + INT32 l2; + + HB_TRACE(HB_TR_DEBUG, ("hb_get_le_int64(%p)", ptr)); + + l1 = HB_GET_LE_UINT32( ptr ); + l2 = HB_GET_LE_INT32( ptr + 4 ); + return ldexp( ( double ) l2, 32 ) + ( double ) l1; +} + +void HB_EXPORT hb_put_le_uint64( BYTE * ptr, double d ) +{ + UINT32 l1, l2; + + HB_TRACE(HB_TR_DEBUG, ("hb_put_le_uint64(%p)", ptr)); + + l1 = ( UINT32 ) ( d ); + l2 = ( UINT32 ) ( d / 4294967296.0 ); + HB_PUT_LE_UINT32( ptr, l1 ); + HB_PUT_LE_UINT32( ptr + 4, l2 ); +} + +#endif diff --git a/harbour/source/common/hbfsapi.c b/harbour/source/common/hbfsapi.c index aa308e1f64..23e1371b11 100644 --- a/harbour/source/common/hbfsapi.c +++ b/harbour/source/common/hbfsapi.c @@ -57,45 +57,51 @@ it will do it. [vszakats] */ extern void hb_fhnd_ForceLink( void ); -/* - * Function that adds at most one path to a list of pathnames to search - */ -static void AddSearchPath( char * szPath, HB_PATHNAMES * * pSearchList ) -{ - HB_PATHNAMES * pPath = *pSearchList; - - if( pPath ) - { - while( pPath->pNext ) - pPath = pPath->pNext; - - pPath->pNext = ( HB_PATHNAMES * ) hb_xgrab( sizeof( HB_PATHNAMES ) ); - pPath = pPath->pNext; - } - else - *pSearchList = pPath = ( HB_PATHNAMES * ) hb_xgrab( sizeof( HB_PATHNAMES ) ); - - pPath->pNext = NULL; - pPath->szPath = szPath; -} - /* * Function that adds zero or more paths to a list of pathnames to search */ -void hb_fsAddSearchPath( char * szPath, HB_PATHNAMES * * pSearchList ) +void hb_fsAddSearchPath( char * szPath, HB_PATHNAMES ** pSearchList ) { char * pPath; char * pDelim; + while( *pSearchList ) + { + pSearchList = &(*pSearchList)->pNext; + } + pPath = hb_strdup( szPath ); while( ( pDelim = strchr( pPath, OS_PATH_LIST_SEPARATOR ) ) != NULL ) { - * pDelim = '\0'; - AddSearchPath( pPath, pSearchList ); + *pDelim = '\0'; + *pSearchList = ( HB_PATHNAMES * ) hb_xgrab( sizeof( HB_PATHNAMES ) ); + (*pSearchList)->szPath = pPath; + pSearchList = &(*pSearchList)->pNext; pPath = pDelim + 1; } + *pSearchList = ( HB_PATHNAMES * ) hb_xgrab( sizeof( HB_PATHNAMES ) ); + (*pSearchList)->szPath = pPath; + (*pSearchList)->pNext = NULL; +} - AddSearchPath( pPath, pSearchList ); +/* + * free list of pathnames to search + */ +void hb_fsFreeSearchPath( HB_PATHNAMES * pSearchList ) +{ + HB_PATHNAMES * pNext; + + /* Only the first path holds an allocated string. + All of the other paths in the list are part of + that first string. */ + hb_xfree( pSearchList->szPath ); + + while( pSearchList ) + { + pNext = pSearchList->pNext; + hb_xfree( pSearchList ); + pSearchList = pNext; + } } /* Split given filename into path, name and extension, plus determine drive */ @@ -103,93 +109,77 @@ PHB_FNAME hb_fsFNameSplit( char * pszFileName ) { PHB_FNAME pFileName; char * pszPos; - char * pszAt; + int iSize, iPos; HB_TRACE(HB_TR_DEBUG, ("hb_fsFNameSplit(%s)", pszFileName)); HB_TRACE(HB_TR_INFO, ("hb_fsFNameSplit: Filename: |%s|\n", pszFileName)); - /* Grab memory, set defaults */ + iPos = iSize = hb_strnlen( pszFileName, _POSIX_PATH_MAX ); + /* Grab memory, set defaults */ pFileName = ( PHB_FNAME ) hb_xgrab( sizeof( HB_FNAME ) ); pszPos = pFileName->szBuffer; + pFileName->szPath = pFileName->szName = pFileName->szExtension = + pFileName->szDrive = NULL; + /* Find the end of the path part, and find out where the name+ext starts */ - pszAt = NULL; - if( pszFileName[ 0 ] != '\0' ) + while( --iPos >= 0 ) { - int iPos = strlen( pszFileName ); - - while( --iPos >= 0 ) + if( strchr( OS_PATH_DELIMITER_LIST, pszFileName[ iPos ] ) ) { - if( strchr( OS_PATH_DELIMITER_LIST, pszFileName[ iPos ] ) ) - { - pszAt = pszFileName + iPos; - break; - } + pFileName->szPath = pszPos; + hb_strncpy( pszPos, pszFileName, iPos + 1 ); + pszPos += iPos + 2; + pszFileName += iPos + 1; + iSize -= iPos + 1; + break; } } - if( pszAt ) - { - pFileName->szPath = pszPos; - pszPos[0] = '\0'; - strncat( pszPos, pszFileName, pszAt - pszFileName + 1 ); - pszPos += pszAt - pszFileName + 1; - *pszPos++ = '\0'; - pszFileName = pszAt + 1; - } - else - pFileName->szPath = NULL; - /* From this point pszFileName will point to the name+ext part of the path */ - /* Split the filename part to name and extension */ - - pszAt = strrchr( pszFileName, '.' ); - if( pszAt && pszAt != pszFileName ) + iPos = iSize; + while( --iPos > 0 ) + { + if( pszFileName[ iPos ] == '.' ) + { + pFileName->szExtension = pszPos; + hb_strncpy( pszPos, pszFileName + iPos, iSize - iPos ); + pszPos += iSize - iPos + 1; + iSize = iPos; + break; + } + } + if( iSize ) { pFileName->szName = pszPos; - pszPos[0] = '\0'; - strncat( pszPos, pszFileName, pszAt - pszFileName ); - pszPos += pszAt - pszFileName; - *pszPos++ = '\0'; - - pFileName->szExtension = pszPos; - strcpy( pszPos, pszAt ); - pszPos += strlen( pszAt ) + 1; - } - else - { - if( pszFileName[ 0 ] != '\0' ) - { - pFileName->szName = pszPos; - strcpy( pszPos, pszFileName ); - pszPos += strlen( pszFileName ) + 1; - } - else - pFileName->szName = NULL; - - pFileName->szExtension = NULL; + hb_strncpy( pszPos, pszFileName, iSize ); + pszPos += iSize + 1; } /* Duplicate the drive letter from the path for easy access on platforms where applicable. Note that the drive info is always present also in the path itself. */ - if( pFileName->szPath && ( pszAt = strchr( pFileName->szPath, ':' ) ) != NULL ) + if( pFileName->szPath ) { - pFileName->szDrive = pszPos; - pszPos[0] = '\0'; - strncat( pszPos, pFileName->szPath, pszAt - pFileName->szPath + 1 ); - pszPos += pszAt - pFileName->szPath + 1; - *pszPos = '\0'; + iPos = 0; + while( iPos < HB_MAX_DRIVE_LENGTH && pFileName->szPath[ iPos ] != '\0' ) + { + if( pFileName->szPath[ iPos ] == ':' ) + { + pFileName->szDrive = pszPos; + hb_strncpy( pszPos, pFileName->szPath, iPos ); + break; + } + ++iPos; + } } - else - pFileName->szDrive = NULL; HB_TRACE(HB_TR_INFO, ("hb_fsFNameSplit: szPath: |%s|\n", pFileName->szPath)); HB_TRACE(HB_TR_INFO, ("hb_fsFNameSplit: szName: |%s|\n", pFileName->szName)); diff --git a/harbour/source/common/hbstr.c b/harbour/source/common/hbstr.c index 678feff3e9..bf041b80f3 100644 --- a/harbour/source/common/hbstr.c +++ b/harbour/source/common/hbstr.c @@ -67,7 +67,7 @@ #include "hbapi.h" #include "hbmath.h" -ULONG hb_strAt( const char * szSub, ULONG ulSubLen, const char * szText, ULONG ulLen ) +ULONG HB_EXPORT hb_strAt( const char * szSub, ULONG ulSubLen, const char * szText, ULONG ulLen ) { HB_TRACE(HB_TR_DEBUG, ("hb_strAt(%s, %lu, %s, %lu)", szSub, ulSubLen, szText, ulLen)); @@ -100,7 +100,7 @@ ULONG hb_strAt( const char * szSub, ULONG ulSubLen, const char * szText, ULONG u return 0; } -char * hb_strupr( char * pszText ) +char HB_EXPORT * hb_strupr( char * pszText ) { char * pszPos; @@ -112,112 +112,19 @@ char * hb_strupr( char * pszText ) return pszText; } -char * hb_strdup( const char * pszText ) +char HB_EXPORT * hb_strdup( const char * pszText ) { char * pszDup; - int iLen = strlen( pszText ) + 1; + ULONG ulLen = strlen( pszText ) + 1; - HB_TRACE(HB_TR_DEBUG, ("hb_strdup(%s, %i)", pszText, iLen)); + HB_TRACE(HB_TR_DEBUG, ("hb_strdup(%s, %ld)", pszText, ulLen)); - pszDup = ( char * ) hb_xgrab( iLen ); - memcpy( pszDup, pszText, iLen ); + pszDup = ( char * ) hb_xgrab( ulLen ); + memcpy( pszDup, pszText, ulLen ); return pszDup; } -int hb_stricmp( const char * s1, const char * s2 ) -{ - int rc = 0; - ULONG l1; - ULONG l2; - ULONG count; - - HB_TRACE(HB_TR_DEBUG, ("hb_stricmp(%s, %s)", s1, s2)); - - l1 = strlen( s1 ); - l2 = strlen( s2 ); - count = ( l1 < l2 ? l1 : l2 ); - - while( rc == 0 && count > 0 ) - { - char c1 = toupper( *s1 ); - char c2 = toupper( *s2 ); - - s1++; - s2++; - - if( c1 != c2 ) - rc = ( c1 < c2 ? -1 : 1 ); - - count--; - } - - if( rc == 0 && l1 != l2 ) - rc = ( l1 < l2 ? -1 : 1 ); - - return rc; -} - -/* - * This function copies szText to destination buffer. - * NOTE: Unlike the documentation for strncpy, this routine will always append - * a null - */ -HB_EXPORT char * hb_strncpy( char * pDest, const char * pSource, ULONG ulLen ) -{ - char *pBuf = pDest; - - HB_TRACE(HB_TR_DEBUG, ("hb_strncpy(%p, %s, %lu)", pDest, pSource, ulLen)); - - pDest[ ulLen ] ='\0'; - - while( ulLen && ( *pDest++ = *pSource++ ) != '\0' ) - { - ulLen--; - } - - while (ulLen--) - { - *pDest++ = '\0'; - } - - return pBuf; -} - -/* - * This function copies szText to destination buffer. - * NOTE: Unlike the documentation for strncat, this routine will always append - * a null and the ulLen param is pDest size not pSource limit - */ -HB_EXPORT char * hb_strncat( char * pDest, const char * pSource, ULONG ulLen ) -{ - char *pBuf = pDest; - - HB_TRACE(HB_TR_DEBUG, ("hb_strncpy(%p, %s, %lu)", pDest, pSource, ulLen)); - - pDest[ ulLen ] ='\0'; - - while( ulLen && *pDest ) - { - pDest++; - ulLen--; - } - - while( ulLen && ( *pDest++ = *pSource++ ) != '\0' ) - { - ulLen--; - } - -/* if someone will need this then please uncomment the cleaning the rest of buffer. */ -/* - while (ulLen--) - { - *pDest++ = '\0'; - } -*/ - return pBuf; -} - char HB_EXPORT * hb_strndup( const char * pszText, ULONG ulLen ) { char * pszDup; @@ -239,103 +146,116 @@ char HB_EXPORT * hb_strndup( const char * pszText, ULONG ulLen ) return pszDup; } - -/* This function copies and converts szText to upper case. - * NOTE: Unlike the documentation for strncpy, this routine will always append - * a null - */ -HB_EXPORT char * hb_strncpyUpper( char * pDest, const char * pSource, ULONG ulLen ) +ULONG HB_EXPORT hb_strnlen( const char * pszText, ULONG ulLen ) { - char *pBuf = pDest; + ULONG ul = 0; - HB_TRACE(HB_TR_DEBUG, ("hb_strncpyUpper(%p, %s, %lu)", pDest, pSource, ulLen)); + HB_TRACE(HB_TR_DEBUG, ("hb_strnlen(%s, %ld)", pszText, ulLen)); - pDest[ ulLen ] ='\0'; - - /* some compilers impliment toupper as a macro, and this has side effects! */ - /* *pDest++ = toupper( *pSource++ ); */ - while( ulLen && (*pDest++ = toupper( *pSource )) != '\0' ) + while( ulLen-- && *pszText++ ) { - ulLen--; - pSource++; + ++ul; } - - while (ulLen--) - { - *pDest++ = '\0'; - } - - return pBuf; + return ul; } -/* This function copies and converts szText to upper case AND Trims it - * NOTE: Unlike the documentation for strncpy, this routine will always append - * a null - */ -HB_EXPORT char * hb_strncpyUpperTrim( char * pDest, const char * pSource, ULONG ulLen ) +HB_EXPORT int hb_stricmp( const char * s1, const char * s2 ) { - char *pBuf = pDest; - ULONG ulSLen = strlen( pSource ); + int rc = 0, c1, c2; - HB_TRACE(HB_TR_DEBUG, ("hb_strncpyUpperTrim(%p, %s, %lu)", pDest, pSource, ulLen)); + HB_TRACE(HB_TR_DEBUG, ("hb_stricmp(%s, %s)", s1, s2)); - pDest[ ulLen ] ='\0'; - - while( ulSLen && pSource[ ulSLen - 1 ] == ' ') + do { - ulSLen--; - } + c1 = toupper( (unsigned char) *s1 ); + c2 = toupper( (unsigned char) *s2 ); - /* some compilers impliment toupper as a macro, and this has side effects! */ - /* *pDest++ = toupper( *pSource++ ); */ - while( ulLen && ulSLen && (*pDest++ = toupper( *pSource )) != '\0' ) - { - ulSLen--; - ulLen--; - pSource++; - } + s1++; + s2++; - while (ulLen--) - { - *pDest++ = '\0'; + if( c1 != c2 ) + { + rc = ( c1 < c2 ? -1 : 1 ); + break; + } } + while ( c1 ); - return pBuf; + return rc; } /* - * This function copies trimed szText to destination buffer. - * NOTE: Unlike the documentation for strncpy, this routine will always append - * a null - */ -HB_EXPORT char * hb_strncpyTrim( char * pDest, const char * pSource, ULONG ulLen ) +AJ: 2004-02-23 +Concatenates multiple strings into a single result. +Eg. hb_xstrcat (buffer, "A", "B", NULL) stores "AB" in buffer. +*/ +char HB_EXPORT * hb_xstrcat ( char *szDest, const char *szSrc, ... ) { - char *pBuf = pDest; - LONG lSLen = strlen( pSource ); + char *szResult = szDest; + va_list va; - HB_TRACE(HB_TR_DEBUG, ("hb_strncpyTrim(%p, %s, %lu)", pDest, pSource, ulLen)); + HB_TRACE(HB_TR_DEBUG, ("hb_xstrcat(%p, %p, ...)", szDest, szSrc)); - pDest[ ulLen ] ='\0'; + while( *szDest ) + szDest++; - while( lSLen && pSource[ lSLen - 1 ] == ' ') + va_start(va, szSrc); + + while( szSrc ) { - lSLen--; + while ( *szSrc ) + *szDest++ = *szSrc++; + szSrc = va_arg ( va, char* ); } - /* some compilers impliment toupper as a macro, and this has side effects! */ - /* *pDest++ = toupper( *pSource++ ); */ - while( ulLen && lSLen && ( *pDest++ = *pSource++ ) != '\0' ) + *szDest = '\0'; + va_end ( va ); + return ( szResult ); +} + +/* +AJ: 2004-02-23 +Concatenates multiple strings into a single result. +Eg. hb_xstrcpy (buffer, "A", "B", NULL) stores "AB" in buffer. +Returns szDest. +Any existing contents of szDest are cleared. If the szDest buffer is NULL, +allocates a new buffer with the required length and returns that. The +buffer is allocated using hb_xgrab(), and should eventually be freed +using hb_xfree(). +*/ +char HB_EXPORT * hb_xstrcpy ( char *szDest, const char *szSrc, ...) +{ + const char *szSrc_Ptr; + va_list va; + size_t dest_size; + + HB_TRACE(HB_TR_DEBUG, ("hb_xstrcpy(%p, %p, ...)", szDest, szSrc)); + + if (szDest == NULL) { - lSLen--; - ulLen--; + va_start (va, szSrc); + szSrc_Ptr = szSrc; + dest_size = 1; + while (szSrc_Ptr) + { + dest_size += strlen (szSrc_Ptr); + szSrc_Ptr = va_arg (va, char *); + } + va_end (va); + + szDest = (char *) hb_xgrab( dest_size ); } - while (ulLen--) + va_start (va, szSrc); + szSrc_Ptr = szSrc; + szDest [0] = '\0'; + while (szSrc_Ptr) { - *pDest++ = '\0'; + hb_xstrcat (szDest, szSrc_Ptr, NULL ); + szSrc_Ptr = va_arg (va, char *); } - - return pBuf; + va_end (va); + return (szDest); } static double hb_numPow10( int nPrecision ) @@ -371,7 +291,7 @@ static double hb_numPow10( int nPrecision ) return pow(10.0, (double) nPrecision); } -double hb_numRound( double dNum, int iDec ) +double HB_EXPORT hb_numRound( double dNum, int iDec ) { static const double doBase = 10.0f; double doComplete5, doComplete5i, dPow; @@ -392,10 +312,88 @@ double hb_numRound( double dNum, int iDec ) doComplete5 = dNum * dPow * doBase; } +/* + * double precision if 15 digit the 16th one is usually wrong but + * can give some information about number, + * Clipper display 16 digit only others are set to 0 + * many people don't know/understand FL arithmetic. They expect + * that it will behaves in the same way as real numbers. It's not + * true but in business application we can try to hide this problem + * for them. Usually they not need such big precision in presented + * numbers so we can decrease the precision to 15 digits and use + * the cut part for proper rounding. It should resolve + * most of problems. But if someone totally not understand FL + * and will try to convert big matrix or sth like that it's quite + * possible that he chose one of the natural school algorithm which + * works nice with real numbers but can give very bad results in FL. + * In such case it could be good to decrease precision even more. + * It not fixes the used algorithm of course but will make many users + * happy because they can see nice (proper) result. + * So maybe it will be good to add SET PRECISION TO for them and + * use the similar hack in ==, >=, <=, <, > operations if it's set. + */ + +//#define HB_NUM_PRECISION 16 + +#ifdef HB_NUM_PRECISION + /* + * this is a hack for people who cannot live without hacked FL values + * in rounding + */ + { + int iDecR, iPrec; + BOOL fNeg; + + if ( dNum < 0 ) + { + fNeg = TRUE; + dNum = -dNum; + } + else + { + fNeg = FALSE; + } + iDecR = (int) log10( dNum ); + iPrec = iDecR + iDec; + + if ( iPrec < -1 ) + { + return 0.0; + } + else + { + if ( iPrec > HB_NUM_PRECISION ) + { + iDec = HB_NUM_PRECISION - ( dNum < 1.0 ? 0 : 1 ) - iDecR; + iPrec = -1; + } + else + { + iPrec -= HB_NUM_PRECISION; + } + } + if ( iDec < 0 ) + { + dPow = hb_numPow10( -iDec ); + doComplete5 = dNum / dPow * doBase + 5.0 + hb_numPow10( iPrec ); + } + else + { + dPow = hb_numPow10( iDec ); + doComplete5 = dNum * dPow * doBase + 5.0 + hb_numPow10( iPrec ); + } + + if ( fNeg ) + { + doComplete5 = -doComplete5; + } + } +#else if( dNum < 0.0f ) doComplete5 -= 5.0f; else doComplete5 += 5.0f; +#endif doComplete5 /= doBase; @@ -407,13 +405,22 @@ double hb_numRound( double dNum, int iDec ) modf( doComplete5, &doComplete5i ); +#if defined( __XCC__ ) || defined( __POCC__ ) + if ( iDec < 16 ) + { + if ( iDec >= 0 ) + return doComplete5i / (LONGLONG) dPow; + else if ( iDec > -16 ) + return doComplete5i * (LONGLONG) dPow; + } +#endif if ( iDec < 0 ) return doComplete5i * dPow; else return doComplete5i / dPow; } -double hb_numInt( double dNum ) +double HB_EXPORT hb_numInt( double dNum ) { double dInt; @@ -432,9 +439,9 @@ static BOOL hb_str2number( BOOL fPCode, const char* szNum, ULONG ulLen, HB_LONG ULONG ulPos = 0; int c, iWidth, iDec = 0, iDecR = 0; - HB_TRACE(HB_TR_DEBUG, ("hb_str2number(%d, %p, %ul %p, %p, %p, %p)", (int) fPCode, szNum, ulLen, lVal, dVal, piDec, piWidth )); + HB_TRACE(HB_TR_DEBUG, ("hb_str2number(%d, %p, %lu, %p, %p, %p, %p)", (int) fPCode, szNum, ulLen, lVal, dVal, piDec, piWidth )); - while ( ulPos < ulLen && isspace( ( BYTE ) szNum[ulPos] ) ) + while ( ulPos < ulLen && isspace( (BYTE) szNum[ulPos] ) ) ulPos++; if ( ulPos >= ulLen ) @@ -545,8 +552,15 @@ static BOOL hb_str2number( BOOL fPCode, const char* szNum, ULONG ulLen, HB_LONG *dVal = (double) *lVal; fDbl = TRUE; } - if ( fDbl && iDec ) - *dVal /= hb_numPow10( iDec ); + if ( iDec ) + { +#if defined( __XCC__ ) || defined( __POCC__ ) + if ( iDec < 16 ) + *dVal /= ( LONGLONG ) hb_numPow10( iDec ); + else +#endif + *dVal /= hb_numPow10( iDec ); + } if ( piDec ) *piDec = iDec + iDecR; @@ -592,7 +606,7 @@ BOOL HB_EXPORT hb_compStrToNum( const char* szNum, HB_LONG * plVal, double * pdV BOOL HB_EXPORT hb_valStrnToNum( const char* szNum, ULONG ulLen, HB_LONG * plVal, double * pdVal, int * piDec, int * piWidth ) { - HB_TRACE(HB_TR_DEBUG, ("hb_valStrToNum( %s, %l, %p, %p, %p, %p)", szNum, ulLen, plVal, pdVal, piDec, piWidth )); + HB_TRACE(HB_TR_DEBUG, ("hb_valStrToNum( %s, %lu, %p, %p, %p, %p)", szNum, ulLen, plVal, pdVal, piDec, piWidth )); return hb_str2number( FALSE, szNum, ulLen, plVal, pdVal, piDec, piWidth ); } @@ -604,94 +618,282 @@ BOOL HB_EXPORT hb_strToNum( const char* szNum, HB_LONG * plVal, double * pdVal ) BOOL HB_EXPORT hb_strnToNum( const char* szNum, ULONG ulLen, HB_LONG * plVal, double * pdVal ) { - HB_TRACE(HB_TR_DEBUG, ("hb_strToNum(%s, %l, %p, %p)", szNum, ulLen, plVal, pdVal )); + HB_TRACE(HB_TR_DEBUG, ("hb_strToNum(%s, %lu, %p, %p)", szNum, ulLen, plVal, pdVal )); return hb_str2number( FALSE, szNum, ulLen, plVal, pdVal, NULL, NULL ); } /* returns the numeric value of a character string representation of a number */ -double hb_strVal( const char * szText, ULONG ulLen ) +double HB_EXPORT hb_strVal( const char * szText, ULONG ulLen ) { HB_LONG lVal; double dVal; - HB_TRACE(HB_TR_DEBUG, ("hb_strVal(%s)", szText)); + HB_TRACE(HB_TR_DEBUG, ("hb_strVal(%s, %lu)", szText, ulLen)); if ( ! hb_str2number( FALSE, szText, ulLen, &lVal, &dVal, NULL, NULL ) ) dVal = ( double ) lVal; return dVal; } -/* -AJ: 2004-02-23 -Concatenates multiple strings into a single result. -Eg. hb_xstrcat (buffer, "A", "B", NULL) stores "AB" in buffer. -*/ -char HB_EXPORT * hb_xstrcat ( char *szDest, const char *szSrc, ... ) +HB_LONG HB_EXPORT hb_strValInt( const char * szText, int * iOverflow ) { - char *szResult = szDest; - va_list va; + HB_LONG lVal; + double dVal; - HB_TRACE(HB_TR_DEBUG, ("hb_xstrcat(%p, %p, ...)", szDest, szSrc)); + HB_TRACE(HB_TR_DEBUG, ("hb_strValInt(%s)", szText)); - while( *szDest ) - szDest++; - - va_start(va, szSrc); - - while( szSrc ) + if ( ! hb_str2number( FALSE, szText, strlen( szText ), &lVal, &dVal, NULL, NULL ) ) { - while ( *szSrc ) - *szDest++ = *szSrc++; - szSrc = va_arg ( va, char* ); + *iOverflow = 1; + return 0; } - - *szDest = '\0'; - va_end ( va ); - return ( szResult ); + *iOverflow = 0; + return lVal; } /* -AJ: 2004-02-23 -Concatenates multiple strings into a single result. -Eg. hb_xstrcpy (buffer, "A", "B", NULL) stores "AB" in buffer. -Returns szDest. -Any existing contents of szDest are cleared. If the szDest buffer is NULL, -allocates a new buffer with the required length and returns that. The -buffer is allocated using hb_xgrab(), and should eventually be freed -using hb_xfree(). -*/ -char HB_EXPORT * hb_xstrcpy ( char *szDest, const char *szSrc, ...) + * This function copies szText to destination buffer. + * NOTE: Unlike the documentation for strncpy, this routine will always append + * a null + */ +HB_EXPORT char * hb_strncpy( char * pDest, const char * pSource, ULONG ulLen ) { - const char *szSrc_Ptr; - va_list va; - size_t dest_size; + char *pBuf = pDest; - HB_TRACE(HB_TR_DEBUG, ("hb_xstrcpy(%p, %p, ...)", szDest, szSrc)); + HB_TRACE(HB_TR_DEBUG, ("hb_strncpy(%p, %s, %lu)", pDest, pSource, ulLen)); - if (szDest == NULL) + pDest[ ulLen ] ='\0'; + + while( ulLen && ( *pDest++ = *pSource++ ) != '\0' ) { - va_start (va, szSrc); - szSrc_Ptr = szSrc; - dest_size = 1; - while (szSrc_Ptr) - { - dest_size += strlen (szSrc_Ptr); - szSrc_Ptr = va_arg (va, char *); - } - va_end (va); - - szDest = (char *) hb_xgrab( dest_size ); + ulLen--; } - va_start (va, szSrc); - szSrc_Ptr = szSrc; - szDest [0] = '\0'; - while (szSrc_Ptr) + while (ulLen--) { - hb_xstrcat (szDest, szSrc_Ptr, NULL ); - szSrc_Ptr = va_arg (va, char *); + *pDest++ = '\0'; } - va_end (va); - return (szDest); + + return pBuf; } +/* + * This function copies szText to destination buffer. + * NOTE: Unlike the documentation for strncat, this routine will always append + * a null and the ulLen param is pDest size not pSource limit + */ +HB_EXPORT char * hb_strncat( char * pDest, const char * pSource, ULONG ulLen ) +{ + char *pBuf = pDest; + + HB_TRACE(HB_TR_DEBUG, ("hb_strncpy(%p, %s, %lu)", pDest, pSource, ulLen)); + + pDest[ ulLen ] ='\0'; + + while( ulLen && *pDest ) + { + pDest++; + ulLen--; + } + + while( ulLen && ( *pDest++ = *pSource++ ) != '\0' ) + { + ulLen--; + } + +/* if someone will need this then please uncomment the cleaning the rest of + buffer. */ +/* + while (ulLen--) + { + *pDest++ = '\0'; + } +*/ + return pBuf; +} + +/* This function copies and converts szText to upper case. + */ +/* + * NOTE: Unlike the documentation for strncpy, this routine will always append + * a null + * pt + */ +HB_EXPORT char * hb_strncpyUpper( char * pDest, const char * pSource, ULONG ulLen ) +{ + char *pBuf = pDest; + + HB_TRACE(HB_TR_DEBUG, ("hb_strncpyUpper(%p, %s, %lu)", pDest, pSource, ulLen)); + + pDest[ ulLen ] ='\0'; + + /* some compilers impliment toupper as a macro, and this has side effects! */ + /* *pDest++ = toupper( *pSource++ ); */ + while( ulLen && (*pDest++ = toupper( *pSource )) != '\0' ) + { + ulLen--; + pSource++; + } + + while (ulLen--) + { + *pDest++ = '\0'; + } + + return pBuf; +} + +/* This function copies and converts szText to upper case AND Trims it + */ +/* + * NOTE: Unlike the documentation for strncpy, this routine will always append + * a null + * pt + */ +HB_EXPORT char * hb_strncpyUpperTrim( char * pDest, const char * pSource, ULONG ulLen ) +{ + char *pBuf = pDest; + ULONG ulSLen; + + HB_TRACE(HB_TR_DEBUG, ("hb_strncpyUpperTrim(%p, %s, %lu)", pDest, pSource, ulLen)); + + ulSLen = 0; + while ( ulSLen < ulLen && pSource[ ulSLen ] ) + { + ulSLen++; + } + while( ulSLen && pSource[ ulSLen - 1 ] == ' ') + { + ulSLen--; + } + + pDest[ ulLen ] = '\0'; + + /* some compilers impliment toupper as a macro, and this has side effects! */ + /* *pDest++ = toupper( *pSource++ ); */ + while( ulLen && ulSLen && (*pDest++ = toupper( *pSource )) != '\0' ) + { + ulSLen--; + ulLen--; + pSource++; + } + + while (ulLen--) + { + *pDest++ = '\0'; + } + + return pBuf; +} + +/* + * This function copies trimed szText to destination buffer. + * NOTE: Unlike the documentation for strncpy, this routine will always append + * a null + */ +HB_EXPORT char * hb_strncpyTrim( char * pDest, const char * pSource, ULONG ulLen ) +{ + char *pBuf = pDest; + ULONG ulSLen; + + HB_TRACE(HB_TR_DEBUG, ("hb_strncpyTrim(%p, %s, %lu)", pDest, pSource, ulLen)); + + ulSLen = 0; + while( ulSLen < ulLen && pSource[ ulSLen ] ) + { + ulSLen++; + } + while( ulSLen && pSource[ ulSLen - 1 ] == ' ' ) + { + ulSLen--; + } + + pDest[ ulLen ] ='\0'; + + /* some compilers impliment toupper as a macro, and this has side effects! */ + /* *pDest++ = toupper( *pSource++ ); */ + while( ulLen && ulSLen && ( *pDest++ = *pSource++ ) != '\0' ) + { + ulSLen--; + ulLen--; + } + + while (ulLen--) + { + *pDest++ = '\0'; + } + + return pBuf; +} + +/* + Simple routine to extract uncommented part of (read) buffer +*/ +HB_EXPORT char *hb_stripOutComments( char* buffer ) +{ + if( buffer && *buffer ) + { + USHORT ui = strlen( buffer ); + char *szOut = (char*) hb_xgrab( ui + 1 ); + int i; + int uu = 0; + char *last; + + hb_xmemset( szOut, 0, ui + 1 ); + + for ( i = 0; i < ui; i ++ ) + { + if ( buffer[ i ] == '/' ) + { + if( buffer [ i + 1 ] == '*' ) + { + i ++; + while ( ++ i < ui ) + { + if ( buffer [ i ] == '*' && buffer [ i + 1 ] == '/' ) + { + i += 2; + break; + } + } + } + else if ( buffer[ i + 1 ] == '/' ) + { + while ( ++ i < ui ) + { + if ( buffer [ i ] == '\n' || buffer [ i ] == '\r' ) + { + break; + } + } + } + } + + szOut[ uu ++ ] = buffer[ i ]; + } + + /* trim left */ + while ( HB_ISSPACE( *szOut ) ) + { + strcpy( szOut, szOut + 1 ); + } + + /* trim right */ + last = szOut + strlen ( szOut ); + while ( last > szOut ) + { + if ( !HB_ISSPACE( *( last - 1 ) ) ) + { + break; + } + last--; + } + + *last = 0; + return( szOut ); + } + else + { + return ( NULL ); + } +} diff --git a/harbour/source/common/hbver.c b/harbour/source/common/hbver.c index a7b95314b6..15abf9bc68 100644 --- a/harbour/source/common/hbver.c +++ b/harbour/source/common/hbver.c @@ -291,6 +291,19 @@ char * hb_verPlatform( void ) return pszPlatform; } +BOOL HB_EXPORT hb_iswinnt(void) +{ +#if defined(HB_OS_WIN_32) + + OSVERSIONINFO osvi ; + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx (&osvi); + return(osvi.dwPlatformId == VER_PLATFORM_WIN32_NT); // && osvi.dwMajorVersion >= 4); +#else + return FALSE ; +#endif +} + /* NOTE: The caller must free the returned buffer. [vszakats] */ char * hb_verCompiler( void ) diff --git a/harbour/source/compiler/cmdcheck.c b/harbour/source/compiler/cmdcheck.c index bcdb946de4..3bf3eb7529 100644 --- a/harbour/source/compiler/cmdcheck.c +++ b/harbour/source/compiler/cmdcheck.c @@ -218,7 +218,7 @@ void hb_compChkCompilerSwitch( int iArg, char * Args[] ) case 'e' : case 'E' : - if( Args[i][j + 1] && toupper( Args[i][j + 1] ) == 'S' && Args[i][j + 2] && isdigit((int) Args[i][j + 2] ) ) + if( Args[i][j + 1] && toupper( ( BYTE ) Args[i][j + 1] ) == 'S' && Args[i][j + 2] && isdigit( ( BYTE ) Args[i][j + 2] ) ) { Switch[2] = 'S'; Switch[3] = Args[i][j + 2]; @@ -241,7 +241,7 @@ void hb_compChkCompilerSwitch( int iArg, char * Args[] ) case 'G' : /* Required argument */ Switch[2] = Args[i][j + 1]; - if( isdigit( (int) Args[i][j + 2] ) ) + if( isdigit( ( BYTE ) Args[i][j + 2] ) ) { /* Optional argument */ Switch[3] = Args[i][j + 2]; @@ -323,7 +323,7 @@ void hb_compChkCompilerSwitch( int iArg, char * Args[] ) case 'q' : case 'Q' : - if( Args[i][j + 1] && isdigit((int) Args[i][j + 1] ) ) + if( Args[i][j + 1] && isdigit( ( BYTE ) Args[i][j + 1] ) ) { Switch[2] = Args[i][j + 1]; Switch[3] = '\0'; @@ -346,13 +346,13 @@ void hb_compChkCompilerSwitch( int iArg, char * Args[] ) Args[i] += (j - 1); hb_compChkEnvironVar( Args[i] ); - /* Accept rest as part of .CH Path and continue with next Args[]. */ + /* Accept rest as part of .CH Path or "undef:" and continue with next Args[]. */ j = strlen( Args[i] ); continue; case 'w' : case 'W' : - if( Args[i][j + 1] && isdigit((int) Args[i][j + 1] ) ) + if( Args[i][j + 1] && isdigit( ( BYTE ) Args[i][j + 1] ) ) { Switch[2] = Args[i][j + 1]; Switch[3] = '\0'; @@ -710,10 +710,10 @@ void hb_compChkEnvironVar( char * szSwitch ) -n1 no start up procedure and no implicit start up procedure */ if( *( s + 1 ) == '1' ) - { + { hb_comp_bStartProc = FALSE; hb_comp_bNoStartUp = TRUE; - } + } /* -n or -n0 no implicit start up procedure */ @@ -786,6 +786,15 @@ void hb_compChkEnvironVar( char * szSwitch ) case 'u': case 'U': + if ( s[1] && toupper( s[1] ) == 'N' + && s[2] && toupper( s[2] ) == 'D' + && s[3] && toupper( s[3] ) == 'E' + && s[4] && toupper( s[4] ) == 'F' + && s[5] == ':' ) + { + /* NOTE: Ignore these -undef: switches will be processed separately */ + break; + } hb_pp_STD_CH = hb_strdup( s + 1 ); break; @@ -864,35 +873,64 @@ void hb_compChkPaths( void ) static void hb_compChkDefineSwitch( char * pszSwitch ) { - if( pszSwitch && HB_ISOPTSEP( pszSwitch[ 0 ] ) && - ( pszSwitch[ 1 ] == 'd' || pszSwitch[ 1 ] == 'D' ) ) + if( pszSwitch && HB_ISOPTSEP( pszSwitch[ 0 ] ) ) { - char *szDefText = hb_strdup( pszSwitch + 2 ), *pAssign, *sDefLine; - unsigned int i = 0; - - while( i < strlen( szDefText ) && ! HB_ISOPTSEP( szDefText[ i ] ) ) - i++; - - szDefText[ i ] = '\0'; - if( szDefText ) + if ( pszSwitch[ 1 ] == 'd' || pszSwitch[ 1 ] == 'D' ) { - if( ( pAssign = strchr( szDefText, '=' ) ) == NULL ) - { - hb_pp_AddDefine( szDefText, 0 ); - } - else - { - szDefText[ pAssign - szDefText ] = '\0'; + char *szDefText = hb_strdup( pszSwitch + 2 ), *pAssign, *sDefLine; + unsigned int i = 0; - /* hb_pp_AddDefine( szDefText, pAssign + 1 ); */ - sDefLine = ( char* ) hb_xgrab( strlen( szDefText ) + 1 + strlen( pAssign + 1 ) + 1 ); - sprintf( sDefLine, "%s %s", szDefText, pAssign + 1 ); - hb_pp_ParseDefine( sDefLine ); - hb_xfree( sDefLine ); + while( i < strlen( szDefText ) && ! HB_ISOPTSEP( szDefText[ i ] ) ) + i++; + + szDefText[ i ] = '\0'; + if( szDefText ) + { + if( ( pAssign = strchr( szDefText, '=' ) ) == NULL ) + { + hb_pp_AddDefine( szDefText, 0 ); + } + else + { + szDefText[ pAssign - szDefText ] = '\0'; + + /* hb_pp_AddDefine( szDefText, pAssign + 1 ); */ + sDefLine = ( char* ) hb_xgrab( strlen( szDefText ) + 1 + strlen( pAssign + 1 ) + 1 ); + sprintf( sDefLine, "%s %s", szDefText, pAssign + 1 ); + hb_pp_ParseDefine( sDefLine ); + hb_xfree( sDefLine ); + } } + + hb_xfree( szDefText ); } + else if ( pszSwitch[1] && toupper( pszSwitch[1] ) == 'U' && + pszSwitch[2] && toupper( pszSwitch[2] ) == 'N' && + pszSwitch[3] && toupper( pszSwitch[3] ) == 'D' && + pszSwitch[4] && toupper( pszSwitch[4] ) == 'E' && + pszSwitch[5] && toupper( pszSwitch[5] ) == 'F' && + pszSwitch[6] == ':' ) + { + char *szDefText = hb_strdup( pszSwitch + 7 ); + char *szDefLine; + unsigned int i = 0; - hb_xfree( szDefText ); + while ( szDefText[ i ] && ! HB_ISOPTSEP( szDefText[ i ] ) ) + { + i++; + } + + szDefText[ i ] = '\0'; + + if ( szDefText[ 0 ] ) + { + szDefLine = (char *) hb_xgrab( 7 + strlen( szDefText ) + 1 ); + sprintf( szDefLine, "#undef %s", szDefText ); + hb_pp_ParseDirective( szDefLine ); + hb_xfree( szDefLine ); + } + hb_xfree( szDefText ); + } } } diff --git a/harbour/source/compiler/gencobj.c b/harbour/source/compiler/gencobj.c index d45cb29536..6a9e2a94f4 100644 --- a/harbour/source/compiler/gencobj.c +++ b/harbour/source/compiler/gencobj.c @@ -50,15 +50,18 @@ void hb_compGenCObj( PHB_FNAME pFileName ) char szOutPath[ _POSIX_PATH_MAX ] = "\0"; #if defined( HOST_OS_UNIX_COMPATIBLE ) char szDefaultUnixPath[ _POSIX_PATH_MAX ] = "/etc:/usr/local/etc"; + char * pszEnv = szDefaultUnixPath; #define HB_NULL_STR " > /dev/null" #define HB_ACCESS_FLAG F_OK #elif defined( OS_DOS_COMPATIBLE ) + char * pszEnv = hb_getenv( "PATH" ); #define HB_NULL_STR " >nul" #define HB_ACCESS_FLAG 0 +#else + char * pszEnv = NULL; #endif FILE * yyc; char * pszCfg; - char * pszEnv; BOOL bVerbose = FALSE; /* Don't show C compiler messages (default). */ BOOL bDelTmp = TRUE; /* Delete intermediate C file (default). */ int iSuccess; @@ -75,7 +78,7 @@ void hb_compGenCObj( PHB_FNAME pFileName ) /* Set up things */ #if defined( OS_DOS_COMPATIBLE ) pszEnv = hb_getenv( "PATH" ); -#elif defined( OS_UNIX_COMPATIBLE ) +#elif defined( HOST_OS_UNIX_COMPATIBLE ) pszEnv = szDefaultUnixPath; #else pszEnv = NULL; diff --git a/harbour/source/pp/ppcore.c b/harbour/source/pp/ppcore.c index 9ed00d62ff..9f8bbfabfa 100644 --- a/harbour/source/pp/ppcore.c +++ b/harbour/source/pp/ppcore.c @@ -84,7 +84,7 @@ #if defined( OS_UNIX_COMPATIBLE ) #include #else - #include + #include #endif int hb_pp_ParseDefine( char * ); /* Process #define directive */ diff --git a/harbour/source/rtl/Makefile b/harbour/source/rtl/Makefile index e526d52554..862ac6f0a4 100644 --- a/harbour/source/rtl/Makefile +++ b/harbour/source/rtl/Makefile @@ -36,6 +36,7 @@ C_SOURCES=\ filesys.c \ fkmax.c \ fnsplit.c \ + fserror.c \ fssize.c \ fstemp.c \ gete.c \ diff --git a/harbour/source/rtl/file.c b/harbour/source/rtl/file.c index b5c2609fe1..430a9b5952 100644 --- a/harbour/source/rtl/file.c +++ b/harbour/source/rtl/file.c @@ -59,7 +59,7 @@ BOOL HB_EXPORT hb_fsFile( BYTE * pFilename ) HB_TRACE(HB_TR_DEBUG, ("hb_fsFile(%s)", ( char * ) pFilename)); - pFilename = hb_filecase( hb_strdup( ( char * ) pFilename ) ); + pFilename = hb_fileNameConv( hb_strdup( ( char * ) pFilename) ); if( ( ffind = hb_fsFindFirst( ( char * ) pFilename, HB_FA_ALL ) ) != NULL ) { diff --git a/harbour/source/rtl/filesys.c b/harbour/source/rtl/filesys.c index 43ee23d47c..6712d54697 100644 --- a/harbour/source/rtl/filesys.c +++ b/harbour/source/rtl/filesys.c @@ -104,22 +104,23 @@ #include "hbapi.h" #include "hbapifs.h" #include "hbapierr.h" -#include "hbset.h" #include "hb_io.h" +#include "hbset.h" #if defined(OS_UNIX_COMPATIBLE) #include #include #include #include - #if !defined( HB_OS_DARWIN ) - extern char **environ; - #else + #if defined( HB_OS_DARWIN ) #include #define environ (*_NSGetEnviron()) + #elif !defined( __WATCOMC__ ) + extern char **environ; #endif #endif -#if ( defined(__BORLANDC__) || defined(__IBMCPP__) || defined(_MSC_VER) || \ + +#if ( defined(__DMC__) || defined(__BORLANDC__) || defined(__IBMCPP__) || defined(_MSC_VER) || \ defined(__MINGW32__) || defined(__WATCOMC__) ) && !defined( HB_OS_UNIX ) #include #include @@ -134,7 +135,7 @@ #include #endif - #if defined(_MSC_VER) || defined(__MINGW32__) + #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__DMC__) #include #define ftruncate _chsize #if defined(__MINGW32__) && !defined(_LK_UNLCK) @@ -146,7 +147,7 @@ #if !defined(HAVE_POSIX_IO) #define HAVE_POSIX_IO #endif -#elif defined(__GNUC__) || defined( HB_OS_UNIX ) +#elif defined(__GNUC__) || defined(HB_OS_UNIX) #include #include #include @@ -167,29 +168,60 @@ #if defined(HB_OS_HPUX) extern int fdatasync(int fildes); -#endif - -#if defined(HB_OS_DOS) +#elif defined(HB_OS_DOS) #include -#endif - -#if defined( HB_WIN32_IO ) +#elif defined(HB_OS_OS2) + #include + #include + #include + #include + #ifndef SH_COMPAT + #define SH_COMPAT 0x0000 + #endif +#elif defined( HB_WIN32_IO ) #include - #if ( defined( _MSC_VER ) || defined( __LCC__ ) ) && !defined( INVALID_SET_FILE_POINTER ) + #if ( defined(__DMC__) || defined( _MSC_VER ) || defined( __LCC__ ) ) && !defined( INVALID_SET_FILE_POINTER ) #define INVALID_SET_FILE_POINTER ((DWORD)-1) #endif #endif -#ifdef HB_OS_OS2 - #include - #include - #include -#endif +/* 27/08/2004 - + HB_FS_GETDRIVE() should return a number in the range 0..25 ('A'..'Z') + HB_FS_SETDRIVE() should accept a number inside same range. + + If a particular platform/compiler returns/accepts different ranges of + values, simply define a branch for that platform. + + NOTE: There is not an implicit "current disk", ALWAYS use + + my_func( hb_fsCurDrv(), ...) + + to refer to current disk +*/ #if defined( __DJGPP__ ) - #define _getdrive() ( getdisk() + 1 ) - #define _chdrive(n) setdisk( (n) - 1 ) + #define HB_FS_GETDRIVE(n) do { n = getdisk(); } while( 0 ) + #define HB_FS_SETDRIVE(n) setdisk( n ) + +#elif defined( __WATCOMC__ ) + #define HB_FS_GETDRIVE(n) do { _dos_getdrive( &( n ) ); --( n ); } while( 0 ) + #define HB_FS_SETDRIVE(n) do { \ + UINT uiDummy; \ + _dos_setdrive( ( n ) + 1, &uiDummy ); \ + } while( 0 ) + +#elif defined(HB_OS_OS2) + #define HB_FS_GETDRIVE(n) do { n = _getdrive() - 'A'; } while( 0 ) + #define HB_FS_SETDRIVE(n) _chdrive( ( n ) + 'A' ) + +#else + #define HB_FS_GETDRIVE(n) do { \ + n = _getdrive(); \ + n -= ( ( n ) < 'A' ) ? 1 : 'A'; \ + } while( 0 ) + #define HB_FS_SETDRIVE(n) _chdrive( ( n ) + 1 ) + #endif #ifndef O_BINARY @@ -200,86 +232,12 @@ #define O_LARGEFILE 0 /* O_LARGEFILE is used for LFS in 32-bit Linux */ #endif -#ifndef S_IEXEC - #define S_IEXEC 0x0040 /* owner may execute */ -#endif - -#ifndef S_IRWXU - #define S_IRWXU (S_IRUSR | S_IWUSR | S_IXUSR) -#endif - -#ifndef S_IRUSR - #define S_IRUSR 0x0100 /* owner may read */ -#endif - -#ifndef S_IWUSR - #define S_IWUSR 0x0080 /* owner may write */ -#endif - -#ifndef S_IXUSR - #define S_IXUSR 0x0040 /* owner may execute */ -#endif - -#ifndef S_IRWXG - #define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP) -#endif - -#ifndef S_IRGRP - #define S_IRGRP 0x00020 /* read permission, group */ -#endif - -#ifndef S_IWGRP - #define S_IWGRP 0x00010 /* write permission, grougroup */ -#endif - -#ifndef S_IXGRP - #define S_IXGRP 0x00008/* execute/search permission, group */ -#endif - -#ifndef S_IRWXO - #define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH) -#endif - -#ifndef S_IROTH - #define S_IROTH 0x00004 /* read permission, other */ -#endif - -#ifndef S_IWOTH - #define S_IWOTH 0x00002 /* write permission, other */ -#endif - -#ifndef S_IXOTH - #define S_IXOTH 0x00001/* execute/search permission, other */ -#endif - -#ifndef SH_COMPAT - #define SH_COMPAT 0x00 /* Compatibility */ -#endif - -#ifndef SH_DENYRW - #define SH_DENYRW 0x10 /* Deny read/write */ -#endif - -#ifndef SH_DENYWR - #define SH_DENYWR 0x20 /* Deny write */ -#endif - -#ifndef SH_DENYRD - #define SH_DENYRD 0x30 /* Deny read */ -#endif - -#ifndef SH_DENYNO - #define SH_DENYNO 0x40 /* Deny nothing */ -#endif - -static USHORT s_uiErrorLast = 0; - -#if defined(HAVE_POSIX_IO) || defined(_MSC_VER) || defined(__MINGW32__) +#if defined(HAVE_POSIX_IO) || defined( HB_WIN32_IO ) || defined(_MSC_VER) || defined(__MINGW32__) || defined(__LCC__) || defined(__DMC__) /* Only compilers with Posix or Posix-like I/O support are supported */ #define HB_FS_FILE_IO #endif -#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__IBMCPP__) || defined(__WATCOMC__) +#if defined(__DMC__) || defined(_MSC_VER) || defined(__MINGW32__) || defined(__IBMCPP__) || defined(__WATCOMC__) || defined(HB_OS_OS2) /* These compilers use sopen() rather than open(), because their versions of open() do not support combined O_ and SH_ flags */ #define HB_FS_SOPEN @@ -291,169 +249,249 @@ static USHORT s_uiErrorLast = 0; #define HB_FS_LARGE_OPTIMIZED #endif -#if defined(X__WIN32__) - #if !defined(__BORLANDC__) - extern int WintoDosError( DWORD dwError ); - #else - extern int __IOerror( int dosErr ); - extern int __NTerror( void ); - #endif - - static HANDLE DostoWinHandle( FHANDLE fHandle ); - -#endif - -/* Convert HARBOUR flags to IO subsystem flags */ +static BOOL s_fUseWaitLocks = TRUE; #if defined(HB_FS_FILE_IO) -static int convert_open_flags( USHORT uiFlags ) +#if defined(HB_WIN32_IO) + + #if defined( __LCC__ ) + __inline void * LongToHandle( const long h ) + { + return((void *) (INT_PTR) h ); + } + #endif + + #if ( defined(__DMC__) || ( defined( _MSC_VER ) && ( _MSC_VER >= 1010 ) && ( ! defined( _BASETSD_H_) || ! defined( HandleToLong ) || defined(__USE_INLINE__) ) && ! defined( __POCC__ ) ) ) + #if defined(__DMC__) && !defined(INT_PTR) + #ifdef _WIN64 + typedef __int64 INT_PTR, *PINT_PTR; + #else + typedef long INT_PTR, *PINT_PTR; + #endif + #endif + + + __inline void * LongToHandle( const long h ) + { + return((void *) (INT_PTR) h ); + } + + __inline long HandleToLong( const void *h ) + { + return((long) h ); + } + #endif + +HANDLE DostoWinHandle( FHANDLE fHandle ) { - /* by default FO_READ + FO_COMPAT is set */ - int result_flags = 0; + HANDLE hHandle = (HANDLE) LongToHandle( fHandle ); - HB_TRACE(HB_TR_DEBUG, ("convert_open_flags(%hu)", uiFlags)); - - result_flags |= O_BINARY | O_LARGEFILE; - HB_TRACE(HB_TR_INFO, ("convert_open_flags: added O_BINARY | O_LARGEFILE\n")); - -#if defined(HB_FS_SOPEN) - if( ( uiFlags & ( FO_WRITE | FO_READWRITE ) ) == FO_READ ) + switch( fHandle ) { - result_flags |= O_RDONLY; - HB_TRACE(HB_TR_INFO, ("convert_open_flags: added O_RDONLY\n")); - } -#else - if( ( uiFlags & ( FO_WRITE | FO_READWRITE ) ) == FO_READ ) - { - result_flags |= ( O_RDONLY | SH_COMPAT ); - HB_TRACE(HB_TR_INFO, ("convert_open_flags: added O_RDONLY SH_COMPAT\n")); - } -#endif + case 0: + return GetStdHandle(STD_INPUT_HANDLE); - /* read & write flags */ - if( uiFlags & FO_WRITE ) - { - result_flags |= O_WRONLY; - HB_TRACE(HB_TR_INFO, ("convert_open_flags: added O_WRONLY\n")); + case 1: + return GetStdHandle(STD_OUTPUT_HANDLE); + + case 2: + return GetStdHandle(STD_ERROR_HANDLE); + + default: + return hHandle; } - - if( uiFlags & FO_READWRITE ) - { - result_flags |= O_RDWR; - HB_TRACE(HB_TR_INFO, ("convert_open_flags: added O_RDWR\n")); - } - -#if ! defined(HB_FS_SOPEN) && ! defined( HB_OS_UNIX ) - /* shared flags */ - if( ( uiFlags & FO_DENYREAD ) == FO_DENYREAD ) - { - result_flags |= SH_DENYRD; - HB_TRACE(HB_TR_INFO, ("convert_open_flags: added SH_DENYRD\n")); - } - - else if( uiFlags & FO_EXCLUSIVE ) - { - result_flags |= SH_DENYRW; - HB_TRACE(HB_TR_INFO, ("convert_open_flags: added SH_DENYRW\n")); - } - - else if( uiFlags & FO_DENYWRITE ) - { - result_flags |= SH_DENYWR; - HB_TRACE(HB_TR_INFO, ("convert_open_flags: added SH_DENYWR\n")); - } - - if( uiFlags & FO_DENYNONE ) - { - result_flags |= SH_DENYNO; - HB_TRACE(HB_TR_INFO, ("convert_open_flags: added SH_DENYNO\n")); - } - - if( uiFlags & FO_SHARED ) - { - result_flags |= SH_DENYNO; - HB_TRACE(HB_TR_INFO, ("convert_open_flags: added SH_DENYNO\n")); - } -#endif - - if( uiFlags & FO_CREAT ) - { - result_flags |= O_CREAT; - HB_TRACE(HB_TR_INFO, ("convert_open_flags: added O_CREAT\n")); - } - - if( uiFlags & FO_TRUNC ) - { - result_flags |= O_TRUNC; - HB_TRACE(HB_TR_INFO, ("convert_open_flags: added O_TRUNC\n")); - } - - if( uiFlags & FO_EXCL ) - { - result_flags |= O_EXCL; - HB_TRACE(HB_TR_INFO, ("convert_open_flags: added O_EXCL\n")); - } - - HB_TRACE(HB_TR_INFO, ("convert_open_flags: result is 0x%04x\n", result_flags)); - - return result_flags; } -static unsigned convert_pmode_flags( USHORT uiFlags ) +static void convert_open_flags( BOOL fCreate, USHORT uiAttr, USHORT uiFlags, + DWORD *dwMode, DWORD *dwShare, + DWORD *dwCreat, DWORD *dwAttr ) { - unsigned result_pmode; - - HB_TRACE(HB_TR_DEBUG, ("convert_pmode_flags(%hu)", uiFlags)); - - if( uiFlags & FC_HIDDEN ) + if( fCreate ) { - result_pmode = S_IRUSR; + *dwCreat = CREATE_ALWAYS; + *dwMode = GENERIC_READ | GENERIC_WRITE; } else { - result_pmode = S_IRUSR | S_IRGRP | S_IROTH; + if( uiFlags & FO_CREAT ) + { + if( uiFlags & FO_EXCL ) + *dwCreat = CREATE_NEW; + else if( uiFlags & FO_TRUNC ) + *dwCreat = CREATE_ALWAYS; + else + *dwCreat = OPEN_ALWAYS; + } + else if( uiFlags & FO_TRUNC ) + { + *dwCreat = TRUNCATE_EXISTING; + } + else + { + *dwCreat = OPEN_EXISTING; + } + + *dwMode = 0; + switch( uiFlags & ( FO_READ | FO_WRITE | FO_READWRITE ) ) + { + case FO_READWRITE: + *dwMode |= GENERIC_READ | GENERIC_WRITE; + break; + case FO_WRITE: + *dwMode |= GENERIC_WRITE; + break; + case FO_READ: + *dwMode |= GENERIC_READ; + break; + } } - if( !( uiFlags & FC_READONLY) ) + /* shared flags */ + switch( uiFlags & ( FO_DENYREAD | FO_DENYWRITE | FO_EXCLUSIVE | FO_DENYNONE ) ) { - if( result_pmode & S_IRUSR ) result_pmode |= S_IWUSR; - if( result_pmode & S_IRGRP ) result_pmode |= S_IWGRP; - if( result_pmode & S_IROTH ) result_pmode |= S_IWOTH; + case FO_DENYREAD: + *dwShare = FILE_SHARE_WRITE; + break; + case FO_DENYWRITE: + *dwShare = FILE_SHARE_READ; + break; + case FO_EXCLUSIVE: + *dwShare = 0; + break; + default: + *dwShare = FILE_SHARE_WRITE | FILE_SHARE_READ; + break; } - if( uiFlags & FC_SYSTEM ) + /* file attributes flags */ + if( uiAttr == FC_NORMAL ) { - if( result_pmode & S_IRUSR ) result_pmode |= S_IXUSR; - if( result_pmode & S_IRGRP ) result_pmode |= S_IXGRP; - if( result_pmode & S_IROTH ) result_pmode |= S_IXOTH; + *dwAttr = FILE_ATTRIBUTE_NORMAL; + } + else + { + *dwAttr = FILE_ATTRIBUTE_ARCHIVE; + if( uiAttr & FC_READONLY ) + *dwAttr |= FILE_ATTRIBUTE_READONLY; + if( uiAttr & FC_HIDDEN ) + *dwAttr |= FILE_ATTRIBUTE_HIDDEN; + if( uiAttr & FC_SYSTEM ) + *dwAttr |= FILE_ATTRIBUTE_SYSTEM; + } +} + +#else + +static void convert_open_flags( BOOL fCreate, USHORT uiAttr, USHORT uiFlags, + int *flags, unsigned *mode, + int *share, int *attr ) +{ + HB_TRACE(HB_TR_DEBUG, ("convert_open_flags(%d, %hu, %hu, %p, %p, %p, %p)", fCreate, uiAttr, uiFlags, flags, mode, share, attr)); + + /* file access mode */ +#if defined( HB_OS_UNIX ) + *mode = ( uiAttr & FC_HIDDEN ) ? S_IRUSR : ( S_IRUSR | S_IRGRP | S_IROTH ); + if( !( uiAttr & FC_READONLY ) ) + { + if( *mode & S_IRUSR ) *mode |= S_IWUSR; + if( *mode & S_IRGRP ) *mode |= S_IWGRP; + if( *mode & S_IROTH ) *mode |= S_IWOTH; + } + if( uiAttr & FC_SYSTEM ) + { + if( *mode & S_IRUSR ) *mode |= S_IXUSR; + if( *mode & S_IRGRP ) *mode |= S_IXGRP; + if( *mode & S_IROTH ) *mode |= S_IXOTH; + } +#else + *mode = S_IREAD | + ( ( uiAttr & FC_READONLY ) ? 0 : S_IWRITE ) | + ( ( uiAttr & FC_SYSTEM ) ? S_IEXEC : 0 ); +#endif + + /* dos file attributes */ +#if defined(HB_FS_DOSATTR) + if( uiAttr == FC_NORMAL ) + { + *attr = _A_NORMAL; + } + else + { + *attr = _A_ARCH; + if( uiAttr & FC_READONLY ) + *attr |= _A_READONLY; + if( uiAttr & FC_HIDDEN ) + *attr |= _A_HIDDEN; + if( uiAttr & FC_SYSTEM ) + *attr |= _A_SYSTEM; + } +#else + *attr = 0; +#endif + + if( fCreate ) + { + *flags = O_RDWR | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE | + ( ( uiFlags & FO_EXCL ) ? O_EXCL : 0 ); + } + else + { + *attr = 0; + *flags = O_BINARY | O_LARGEFILE; + switch( uiFlags & ( FO_READ | FO_WRITE | FO_READWRITE ) ) + { + case FO_READ: + *flags |= O_RDONLY; + break; + case FO_WRITE: + *flags |= O_WRONLY; + break; + case FO_READWRITE: + *flags |= O_RDWR; + break; + default: + /* this should not happen and it's here to force default OS behavior */ + *flags |= ( O_RDONLY | O_WRONLY | O_RDWR ); + break; + } + + if( uiFlags & FO_CREAT ) *flags |= O_CREAT; + if( uiFlags & FO_TRUNC ) *flags |= O_TRUNC; + if( uiFlags & FO_EXCL ) *flags |= O_EXCL; } - HB_TRACE(HB_TR_INFO, ("convert_pmode_flags: 0x%04x\n", result_pmode)); + /* shared flags (HB_FS_SOPEN) */ +#if defined(_MSC_VER) || defined(__DMC__) + if( ( uiFlags & FO_DENYREAD ) == FO_DENYREAD ) + *share = _SH_DENYRD; + else if( uiFlags & FO_EXCLUSIVE ) + *share = _SH_DENYRW; + else if( uiFlags & FO_DENYWRITE ) + *share = _SH_DENYWR; + else if( uiFlags & FO_DENYNONE ) + *share = _SH_DENYNO; + else + *share = _SH_COMPAT; +#elif !defined( HB_OS_UNIX ) + if( ( uiFlags & FO_DENYREAD ) == FO_DENYREAD ) + *share = SH_DENYRD; + else if( uiFlags & FO_EXCLUSIVE ) + *share = SH_DENYRW; + else if( uiFlags & FO_DENYWRITE ) + *share = SH_DENYWR; + else if( uiFlags & FO_DENYNONE ) + *share = SH_DENYNO; + else + *share = SH_COMPAT; +#else + *share = 0; +#endif + + HB_TRACE(HB_TR_INFO, ("convert_open_flags: flags=0x%04x, mode=0x%04x, share=0x%04x, attr=0x%04x", *flags, *mode, *share, *attr)); - return result_pmode; -} - -static void convert_create_flags( USHORT uiFlags, int * result_flags, unsigned * result_pmode ) -{ - HB_TRACE(HB_TR_DEBUG, ("convert_create_flags(%hu, %p, %p)", uiFlags, result_flags, result_pmode)); - - /* by default FC_NORMAL is set */ - *result_flags = O_BINARY | O_CREAT | O_TRUNC | O_RDWR | O_LARGEFILE; - *result_pmode = convert_pmode_flags( uiFlags ); - - HB_TRACE(HB_TR_INFO, ("convert_create_flags: 0x%04x, 0x%04x\n", *result_flags, *result_pmode)); -} - -static void convert_create_flags_ex( USHORT uiAttr, USHORT uiFlags, int * result_flags, unsigned * result_pmode ) -{ - HB_TRACE(HB_TR_DEBUG, ("convert_create_flags_ex(%hu, %hu, %p, %p)", uiAttr, uiFlags, result_flags, result_pmode)); - - convert_create_flags( uiAttr, result_flags, result_pmode ); - *result_flags |= convert_open_flags( uiFlags ); - - HB_TRACE(HB_TR_INFO, ("convert_create_flags: 0x%04x, 0x%04x\n", *result_flags, *result_pmode)); } +#endif static int convert_seek_flags( USHORT uiFlags ) { @@ -473,67 +511,12 @@ static int convert_seek_flags( USHORT uiFlags ) #endif -/* - Convert file and dir case. The allowed SET options are: - LOWER - Convert all caracters of file to lower - UPPER - Convert all caracters of file to upper - MIXED - Leave as is - - The allowed environment options are: - FILECASE - define the case of file - DIRCASE - define the case of path - DIRSEPARATOR - define separator of path (Ex. "/") -*/ - -BYTE * hb_filecase( char * str ) -{ - char * filename; - char * dirname = str; - size_t dirlen; - - /* Look for filename (Last "\" or DIRSEPARATOR) */ - if( hb_set.HB_SET_DIRSEPARATOR != '\\' ) - { - char * strbak = str; - - while( *strbak ) - { - if( *strbak == '\\' ) - *strbak = hb_set.HB_SET_DIRSEPARATOR; - - strbak++; - } - } - - if( ( filename = strrchr( str, hb_set.HB_SET_DIRSEPARATOR ) ) != NULL ) - filename++; - else - filename = str; - - dirlen = filename - str; - - /* FILECASE */ - - if( hb_set.HB_SET_FILECASE == HB_SET_CASE_LOWER ) - hb_strLower( filename, strlen( filename ) ); - else if( hb_set.HB_SET_FILECASE == HB_SET_CASE_UPPER ) - hb_strUpper( filename, strlen( filename ) ); - - /* DIRCASE */ - - if( hb_set.HB_SET_DIRCASE == HB_SET_CASE_LOWER ) - hb_strLower( dirname, dirlen ); - else if( hb_set.HB_SET_DIRCASE == HB_SET_CASE_UPPER ) - hb_strUpper( dirname, dirlen ); - - return ( BYTE * ) str; -} /* * FILESYS.API FUNCTIONS -- */ -FHANDLE hb_fsPOpen( BYTE * pFilename, BYTE * pMode ) +FHANDLE HB_EXPORT hb_fsPOpen( BYTE * pFilename, BYTE * pMode ) { FHANDLE hFileHandle = FS_ERROR; @@ -620,7 +603,7 @@ FHANDLE hb_fsPOpen( BYTE * pFilename, BYTE * pMode ) } } - s_uiErrorLast = hFileHandle != FS_ERROR ? 0 : errno; + hb_fsSetIOError( hFileHandle != FS_ERROR, 0 ); if( pbyTmp ) hb_xfree( pbyTmp ); @@ -629,7 +612,8 @@ FHANDLE hb_fsPOpen( BYTE * pFilename, BYTE * pMode ) HB_SYMBOL_UNUSED( pFilename ); HB_SYMBOL_UNUSED( pMode ); - s_uiErrorLast = FS_ERROR; + + hb_fsSetError( (USHORT) FS_ERROR ); #endif @@ -642,178 +626,101 @@ FHANDLE HB_EXPORT hb_fsOpen( BYTE * pFilename, USHORT uiFlags ) HB_TRACE(HB_TR_DEBUG, ("hb_fsOpen(%p, %hu)", pFilename, uiFlags)); - pFilename = hb_filecase( hb_strdup( ( char * ) pFilename ) ); + pFilename = hb_fileNameConv( hb_strdup( ( char * ) pFilename) ); -#if defined(X__WIN32__) +#if defined(HB_WIN32_IO) { - DWORD dwFlags = 0; - DWORD dwShare = FILE_SHARE_READ | FILE_SHARE_WRITE; + DWORD dwMode, dwShare, dwCreat, dwAttr; HANDLE hFile; - /* read & write flags */ - switch( uiFlags & 3) - { - case FO_READWRITE : - dwFlags |= GENERIC_READ | GENERIC_WRITE; - break; + convert_open_flags( FALSE, FC_NORMAL, uiFlags, &dwMode, &dwShare, &dwCreat, &dwAttr ); - case FO_WRITE: - dwFlags |= GENERIC_WRITE; - break; + hFile = ( HANDLE ) CreateFile( ( char * ) pFilename, dwMode, dwShare, + NULL, dwCreat, dwAttr, NULL ); - case FO_READ : - dwFlags |= GENERIC_READ; - break; - } + hb_fsSetIOError( hFile != ( HANDLE ) INVALID_HANDLE_VALUE, 0 ); - - /* shared flags */ - switch (uiFlags & ( FO_DENYREAD | FO_DENYWRITE | FO_EXCLUSIVE | FO_DENYNONE ) ) - { - case FO_DENYREAD : - - dwShare = FILE_SHARE_WRITE; - break; - - case FO_DENYWRITE : - - dwShare = FILE_SHARE_READ; - break; - - case FO_EXCLUSIVE: - - dwShare = 0; - break; - - } - errno = 0; - - hFile = ( HANDLE ) CreateFile( ( char * ) pFilename, dwFlags, - dwShare, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); - - if( hFile == ( HANDLE ) INVALID_HANDLE_VALUE ) - #if !defined(__BORLANDC__) - errno=WintoDosError(GetLastError()); - #else - __NTerror(); - #endif - - /* errno = GetLastError(); */ - hFileHandle=HandleToLong(hFile); - s_uiErrorLast = errno; + hFileHandle = HandleToLong(hFile); } - -#elif defined(HAVE_POSIX_IO) && ! defined(__IBMCPP__) && ! defined(_MSC_VER) - - hFileHandle = open( ( char * ) pFilename, convert_open_flags( uiFlags ), - convert_pmode_flags( 0 ) ); - s_uiErrorLast = hFileHandle != FS_ERROR ? 0 : errno; - -#elif defined(_MSC_VER) +#elif defined(HB_FS_FILE_IO) { - int iShare = _SH_DENYNO; + int flags, share, attr; + unsigned mode; - if( ( uiFlags & FO_DENYREAD ) == FO_DENYREAD ) - iShare = _SH_DENYRD; - - else if( uiFlags & FO_EXCLUSIVE ) - iShare = _SH_DENYRW; - - else if( uiFlags & FO_DENYWRITE ) - iShare = _SH_DENYWR; - - errno = 0; - if( iShare ) - hFileHandle = _sopen( ( char * ) pFilename, convert_open_flags( uiFlags ), iShare ); + convert_open_flags( FALSE, FC_NORMAL, uiFlags, &flags, &mode, &share, &attr ); +#if defined(_MSC_VER) || defined(__DMC__) + if( share ) + hFileHandle = _sopen( ( char * ) pFilename, flags, share, mode ); else - hFileHandle = _open( ( char * ) pFilename, convert_open_flags( uiFlags ) ); - s_uiErrorLast = errno; - } - -#elif defined(__MINGW32__) || defined(__IBMCPP__) - - { - int iShare = SH_DENYNO; - - if( ( uiFlags & FO_DENYREAD ) == FO_DENYREAD ) - iShare = SH_DENYRD; - - else if( uiFlags & FO_EXCLUSIVE ) - iShare = SH_DENYRW; - - else if( uiFlags & FO_DENYWRITE ) - iShare = SH_DENYWR; - - if( iShare ) - hFileHandle = sopen( ( char * ) pFilename, convert_open_flags( uiFlags ), iShare ); + hFileHandle = _open( ( char * ) pFilename, flags, mode ); +#elif defined(HB_FS_SOPEN) + if( share ) + hFileHandle = sopen( ( char * ) pFilename, flags, share, mode ); else - hFileHandle = open( ( char * ) pFilename, convert_open_flags( uiFlags ) ); - s_uiErrorLast = hFileHandle != FS_ERROR ? 0 : errno; + hFileHandle = open( ( char * ) pFilename, flags, mode ); +#else + hFileHandle = open( ( char * ) pFilename, flags | share, mode ); +#endif + hb_fsSetIOError( hFileHandle != FS_ERROR, 0 ); } - #else hFileHandle = FS_ERROR; - s_uiErrorLast = FS_ERROR; + hb_fsSetError( (USHORT) FS_ERROR ); #endif hb_xfree( pFilename ); + return hFileHandle; } FHANDLE HB_EXPORT hb_fsCreate( BYTE * pFilename, USHORT uiAttr ) { FHANDLE hFileHandle; - int oflag; - unsigned pmode; HB_TRACE(HB_TR_DEBUG, ("hb_fsCreate(%p, %hu)", pFilename, uiAttr)); - pFilename = hb_filecase( hb_strdup( ( char * ) pFilename ) ); - s_uiErrorLast = 0; - -#if defined(X__WIN32__) + pFilename = hb_fileNameConv( hb_strdup( ( char * ) pFilename ) ); +#if defined(HB_WIN32_IO) { - DWORD dwFlags = FILE_ATTRIBUTE_ARCHIVE; + DWORD dwMode, dwShare, dwCreat, dwAttr; HANDLE hFile; - if( uiAttr & FC_READONLY ) - dwFlags |= FILE_ATTRIBUTE_READONLY; + convert_open_flags( TRUE, uiAttr, FO_EXCLUSIVE, &dwMode, &dwShare, &dwCreat, &dwAttr ); - if( uiAttr & FC_HIDDEN ) - dwFlags |= FILE_ATTRIBUTE_HIDDEN; + hFile = ( HANDLE ) CreateFile( ( char * ) pFilename, dwMode, dwShare, + NULL, dwCreat, dwAttr, NULL ); - if( uiAttr & FC_SYSTEM ) - dwFlags |= FILE_ATTRIBUTE_SYSTEM; + hb_fsSetIOError( hFile != ( HANDLE ) INVALID_HANDLE_VALUE, 0 ); - errno = 0; - - hFile = ( HANDLE ) CreateFile( ( char * ) pFilename, - GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, - dwFlags, NULL ); - - if( hFile == ( HANDLE ) INVALID_HANDLE_VALUE ) - errno = GetLastError(); - hFileHandle=HandleToLong(hFile); - s_uiErrorLast = errno; + hFileHandle = HandleToLong(hFile); } - #elif defined(HB_FS_FILE_IO) + { + int flags, share, attr; + unsigned mode; + convert_open_flags( TRUE, uiAttr, FO_EXCLUSIVE, &flags, &mode, &share, &attr ); - convert_create_flags( uiAttr, &oflag, &pmode ); - hFileHandle = open( ( char * ) pFilename, oflag, pmode ); - s_uiErrorLast = hFileHandle != FS_ERROR ? 0 : errno; - +#if defined(HB_FS_DOSCREAT) + hFileHandle = _creat( ( char * ) pFilename, attr ); +#elif defined(HB_FS_SOPEN) + hFileHandle = open( ( char * ) pFilename, flags, mode ); +#else + hFileHandle = open( ( char * ) pFilename, flags | share, mode ); +#endif + hb_fsSetIOError( hFileHandle != FS_ERROR, 0 ); + } #else hFileHandle = FS_ERROR; - s_uiErrorLast = FS_ERROR; + hb_fsSetError( (USHORT) FS_ERROR ); #endif hb_xfree( pFilename ); + return hFileHandle; } @@ -826,29 +733,47 @@ FHANDLE HB_EXPORT hb_fsCreate( BYTE * pFilename, USHORT uiAttr ) FHANDLE HB_EXPORT hb_fsCreateEx( BYTE * pFilename, USHORT uiAttr, USHORT uiFlags ) { FHANDLE hFileHandle; - int oflag; - unsigned pmode; HB_TRACE(HB_TR_DEBUG, ("hb_fsCreateEx(%p, %hu, %hu)", pFilename, uiAttr, uiFlags)); - pFilename = hb_filecase( hb_strdup( ( char * ) pFilename ) ); + pFilename = hb_fileNameConv( hb_strdup( ( char * ) pFilename ) ); - s_uiErrorLast = 0; +#if defined( HB_WIN32_IO ) + { + DWORD dwMode, dwShare, dwCreat, dwAttr; + HANDLE hFile; -#if defined(HB_FS_FILE_IO) + convert_open_flags( TRUE, uiAttr, uiFlags, &dwMode, &dwShare, &dwCreat, &dwAttr ); - convert_create_flags_ex( uiAttr, uiFlags, &oflag, &pmode ); - hFileHandle = open( ( char * ) pFilename, oflag, pmode ); - s_uiErrorLast = hFileHandle != FS_ERROR ? 0 : errno; + hFile = ( HANDLE ) CreateFile( ( char * ) pFilename, dwMode, dwShare, + NULL, dwCreat, dwAttr, NULL ); + hb_fsSetIOError( hFile != ( HANDLE ) INVALID_HANDLE_VALUE, 0 ); + + hFileHandle = HandleToLong(hFile); + } +#elif defined(HB_FS_FILE_IO) + { + int flags, share, attr; + unsigned mode; + convert_open_flags( TRUE, uiAttr, uiFlags, &flags, &mode, &share, &attr ); + +#if defined(HB_FS_SOPEN) + hFileHandle = open( ( char * ) pFilename, flags, mode ); +#else + hFileHandle = open( ( char * ) pFilename, flags | share, mode ); +#endif + hb_fsSetIOError( hFileHandle != FS_ERROR, 0 ); + } #else hFileHandle = FS_ERROR; - s_uiErrorLast = FS_ERROR; + hb_fsSetError( (USHORT) FS_ERROR ); #endif hb_xfree( pFilename ); + return hFileHandle; } @@ -858,89 +783,69 @@ void HB_EXPORT hb_fsClose( FHANDLE hFileHandle ) #if defined(HB_FS_FILE_IO) - errno = 0; - - #if defined(X__WIN32__) - - if( ! CloseHandle( DostoWinHandle( hFileHandle ) ) ) - { - #if !defined(__BORLANDC__) - errno = WintoDosError( GetLastError() ); - #else - __NTerror(); - #endif - } - + #if defined(HB_WIN32_IO) + hb_fsSetIOError( CloseHandle( DostoWinHandle( hFileHandle ) ), 0 ); #else - close( hFileHandle ); + hb_fsSetIOError( close( hFileHandle ) == 0, 0 ); #endif - s_uiErrorLast = errno; - #else - s_uiErrorLast = FS_ERROR; + hb_fsSetError( (USHORT) FS_ERROR ); #endif - - /* Convert 'Invalid Memory Block' to 'Invalid Handle' */ - if( s_uiErrorLast == 9 ) - s_uiErrorLast = 6; } -BOOL hb_fsSetDevMode( FHANDLE hFileHandle, USHORT uiDevMode ) +void HB_EXPORT hb_fsSetDevMode( FHANDLE hFileHandle, USHORT uiDevMode ) { - BOOL bResult; - HB_TRACE(HB_TR_DEBUG, ("hb_fsSetDevMode(%p, %hu)", hFileHandle, uiDevMode)); -#if defined(__BORLANDC__) || defined(__IBMCPP__) || defined(__DJGPP__) || defined(__CYGWIN__) || defined(__WATCOMC__) + /* TODO: HB_WIN32_IO support */ + +#if defined(__BORLANDC__) || defined(__IBMCPP__) || defined(__DJGPP__) || defined(__CYGWIN__) || defined(__WATCOMC__) || defined(HB_OS_OS2) +{ + int iRet = 0; - errno = 0; switch( uiDevMode ) { case FD_BINARY: - bResult = ( setmode( hFileHandle, O_BINARY ) != -1 ); + iRet = setmode( hFileHandle, O_BINARY ); break; case FD_TEXT: - bResult = ( setmode( hFileHandle, O_TEXT ) != -1 ); + iRet = setmode( hFileHandle, O_TEXT ); break; - - default: - bResult = FALSE; } - s_uiErrorLast = errno; + hb_fsSetIOError( iRet != -1, 0 ); +} +#elif defined(_MSC_VER) || defined(__MINGW32__) || defined(__DMC__) +{ + int iRet = 0; -#elif defined(_MSC_VER) || defined(__MINGW32__) - - errno = 0; switch( uiDevMode ) { case FD_BINARY: - bResult = ( _setmode( hFileHandle, _O_BINARY ) != -1 ); + iRet = _setmode( hFileHandle, _O_BINARY ); break; case FD_TEXT: - bResult = ( _setmode( hFileHandle, _O_TEXT ) != -1 ); + iRet = _setmode( hFileHandle, _O_TEXT ); break; - - default: - bResult = FALSE; } - s_uiErrorLast = errno; - -#else + hb_fsSetIOError( iRet != -1, 0 ); +} +#elif defined( HB_OS_UNIX ) HB_SYMBOL_UNUSED( hFileHandle ); HB_SYMBOL_UNUSED( uiDevMode ); + hb_fsSetError( ( USHORT ) FS_ERROR ); - bResult = FALSE; - s_uiErrorLast = ( USHORT ) FS_ERROR; +#else + + hb_fsSetError( (USHORT) FS_ERROR ); #endif - return bResult; } USHORT HB_EXPORT hb_fsRead( FHANDLE hFileHandle, BYTE * pBuff, USHORT uiCount ) @@ -951,28 +856,28 @@ USHORT HB_EXPORT hb_fsRead( FHANDLE hFileHandle, BYTE * pBuff, USHORT uiCount ) #if defined(HB_FS_FILE_IO) - errno = 0; - - #if defined(X__WIN32__) + #if defined(HB_WIN32_IO) { - DWORD dwRead = 0; - if( ! ReadFile( DostoWinHandle( hFileHandle ), pBuff, ( DWORD ) uiCount, &dwRead, NULL ) ) - errno = GetLastError(); - uiRead = ( USHORT ) dwRead; + DWORD dwRead ; + BOOL fResult; + fResult = ReadFile( DostoWinHandle(hFileHandle), pBuff, (DWORD)uiCount, &dwRead, NULL ); + hb_fsSetIOError( fResult, 0 ); + + uiRead = fResult ? ( USHORT ) dwRead : 0; } #else uiRead = read( hFileHandle, pBuff, uiCount ); + hb_fsSetIOError( uiRead != ( USHORT ) -1, 0 ); #endif - s_uiErrorLast = errno; if( uiRead == ( USHORT ) -1 ) uiRead = 0; #else uiRead = 0; - s_uiErrorLast = FS_ERROR; + hb_fsSetError( (USHORT) FS_ERROR ); #endif @@ -987,36 +892,51 @@ USHORT HB_EXPORT hb_fsWrite( FHANDLE hFileHandle, BYTE * pBuff, USHORT uiCount #if defined(HB_FS_FILE_IO) - errno = 0; - - #if defined(X__WIN32__) + #if defined(HB_WIN32_IO) { DWORD dwWritten = 0; - if( ! WriteFile( DostoWinHandle( hFileHandle ), pBuff, uiCount, &dwWritten, NULL ) ) - errno = GetLastError(); - uiWritten = ( USHORT ) dwWritten; + BOOL fResult; + + if ( uiCount ) + { + fResult = WriteFile( DostoWinHandle(hFileHandle), pBuff, uiCount, &dwWritten, NULL ); + } + else + { + dwWritten = 0; + fResult = SetEndOfFile( DostoWinHandle(hFileHandle) ); + } + hb_fsSetIOError( fResult, 0 ); + + uiWritten = fResult ? ( USHORT ) dwWritten : 0; } #else - if( uiCount ) { uiWritten = write( hFileHandle, pBuff, uiCount ); + hb_fsSetIOError( uiWritten != ( USHORT ) -1, 0 ); if( uiWritten == ( USHORT ) -1 ) uiWritten = 0; } else { +#if defined(HB_OS_LINUX) && defined(__USE_LARGEFILE64) + /* + * The macro: __USE_LARGEFILE64 is set when _LARGEFILE64_SOURCE is + * define and efectively enables lseek64/flock64/ftruncate64 functions + * on 32bit machines. + */ + hb_fsSetIOError( ftruncate64( hFileHandle, lseek64( hFileHandle, 0L, SEEK_CUR ) ) != -1, 0 ); +#else + hb_fsSetIOError( ftruncate( hFileHandle, lseek( hFileHandle, 0L, SEEK_CUR ) ) != -1, 0 ); +#endif uiWritten = 0; - ftruncate( hFileHandle, lseek( hFileHandle, 0L, SEEK_CUR ) ); } - s_uiErrorLast = errno; - #endif - #else uiWritten = 0; - s_uiErrorLast = FS_ERROR; + hb_fsSetError( (USHORT) FS_ERROR ); #endif @@ -1031,63 +951,64 @@ ULONG HB_EXPORT hb_fsReadLarge( FHANDLE hFileHandle, BYTE * pBuff, ULONG ulCount #if defined(HB_FS_FILE_IO) - errno = 0; - - #if defined(X__WIN32__) - { - if( ! ReadFile( DostoWinHandle( hFileHandle ), pBuff, ulCount, &ulRead, NULL ) ) - errno = GetLastError(); - } + #if defined(HB_WIN32_IO) + { + hb_fsSetIOError( ReadFile( DostoWinHandle(hFileHandle), + pBuff, ulCount, &ulRead, NULL ), 0 ); + } #elif defined(HB_FS_LARGE_OPTIMIZED) + { ulRead = read( hFileHandle, pBuff, ulCount ); + hb_fsSetIOError( ulRead != (ULONG) -1, 0 ); + } #else + { + ULONG ulLeftToRead = ulCount; + USHORT uiToRead; + USHORT uiRead; + BYTE * pPtr = pBuff; + + ulRead = 0; + + while( ulLeftToRead ) { - ULONG ulLeftToRead = ulCount; - USHORT uiToRead; - USHORT uiRead; - BYTE * pPtr = pBuff; - - ulRead = 0; - - while( ulLeftToRead ) + /* Determine how much to read this time */ + if( ulLeftToRead > ( ULONG ) INT_MAX ) { - /* Determine how much to read this time */ - if( ulLeftToRead > ( ULONG ) INT_MAX ) - { - uiToRead = INT_MAX; - ulLeftToRead -= ( ULONG ) uiToRead; - } - else - { - uiToRead = ( USHORT ) ulLeftToRead; - ulLeftToRead = 0; - } - - uiRead = read( hFileHandle, pPtr, uiToRead ); - /* -1 on bad hFileHandle - 0 on disk full - */ - - if( uiRead == 0 ) - break; - - if( uiRead == ( USHORT ) -1 ) - { - uiRead = 0; - break; - } - - ulRead += ( ULONG ) uiRead; - pPtr += uiRead; + uiToRead = INT_MAX; + ulLeftToRead -= ( ULONG ) uiToRead; } + else + { + uiToRead = ( USHORT ) ulLeftToRead; + ulLeftToRead = 0; + } + + uiRead = read( hFileHandle, pPtr, uiToRead ); + /* -1 on bad hFileHandle + 0 on disk full + */ + + if( uiRead == 0 ) + break; + + if( uiRead == ( USHORT ) -1 ) + { + uiRead = 0; + break; + } + + ulRead += ( ULONG ) uiRead; + pPtr += uiRead; } + hb_fsSetIOError( ulLeftToRead == 0, 0 ); + } #endif - s_uiErrorLast = errno; #else ulRead = 0; - s_uiErrorLast = FS_ERROR; + hb_fsSetError( (USHORT) FS_ERROR ); #endif @@ -1102,18 +1023,24 @@ ULONG HB_EXPORT hb_fsWriteLarge( FHANDLE hFileHandle, BYTE * pBuff, ULONG ulCoun #if defined(HB_FS_FILE_IO) - errno = 0; - - #if defined(X__WIN32__) + #if defined(HB_WIN32_IO) + { + ulWritten = 0; + if( ulCount ) { - if( ! WriteFile( DostoWinHandle( hFileHandle), pBuff, ulCount, &ulWritten, NULL ) ) - errno = GetLastError(); + hb_fsSetIOError( WriteFile( DostoWinHandle( hFileHandle), pBuff, ulCount, &ulWritten, NULL ), 0 ); } + else + { + hb_fsSetIOError( SetEndOfFile( DostoWinHandle(hFileHandle) ), 0 ); + } + } #else if( ulCount ) #if defined(HB_FS_LARGE_OPTIMIZED) { ulWritten = write( hFileHandle, pBuff, ulCount ); + hb_fsSetIOError( ulWritten != ( ULONG ) -1, 0 ); if( ulWritten == ( ULONG ) -1 ) ulWritten = 0; } @@ -1139,7 +1066,9 @@ ULONG HB_EXPORT hb_fsWriteLarge( FHANDLE hFileHandle, BYTE * pBuff, ULONG ulCoun uiToWrite = ( USHORT ) ulLeftToWrite; ulLeftToWrite = 0; } + uiWritten = write( hFileHandle, pPtr, uiToWrite ); + /* -1 on bad hFileHandle 0 on disk full */ @@ -1156,21 +1085,29 @@ ULONG HB_EXPORT hb_fsWriteLarge( FHANDLE hFileHandle, BYTE * pBuff, ULONG ulCoun ulWritten += ( ULONG ) uiWritten; pPtr += uiWritten; } + hb_fsSetIOError( ulLeftToWrite == 0, 0 ); } #endif else { +#if defined(HB_OS_LINUX) && defined(__USE_LARGEFILE64) + /* + * The macro: __USE_LARGEFILE64 is set when _LARGEFILE64_SOURCE is + * define and efectively enables lseek64/flock64/ftruncate64 functions + * on 32bit machines. + */ + hb_fsSetIOError( ftruncate64( hFileHandle, lseek64( hFileHandle, 0L, SEEK_CUR ) ) != -1, 0 ); +#else + hb_fsSetIOError( ftruncate( hFileHandle, lseek( hFileHandle, 0L, SEEK_CUR ) ) != -1, 0 ); +#endif ulWritten = 0; - ftruncate( hFileHandle, lseek( hFileHandle, 0L, SEEK_CUR ) ); } - #endif - s_uiErrorLast = errno; + #endif #else - ulWritten = 0; - s_uiErrorLast = FS_ERROR; + hb_fsSetError( (USHORT) FS_ERROR ); #endif @@ -1181,20 +1118,26 @@ void HB_EXPORT hb_fsCommit( FHANDLE hFileHandle ) { HB_TRACE(HB_TR_DEBUG, ("hb_fsCommit(%p)", hFileHandle)); -#if defined(X__WIN32__) - - FlushFileBuffers( ( HANDLE ) DostoWinHandle( hFileHandle ) ); - s_uiErrorLast = ( USHORT ) GetLastError(); +#if defined(HB_OS_WIN_32) + { + #if defined(HB_WIN32_IO) + hb_fsSetIOError( FlushFileBuffers( ( HANDLE ) DostoWinHandle( hFileHandle ) ), 0 ); + #else + #if defined(__WATCOMC__) + hb_fsSetIOError( fsync( hFileHandle ) == 0, 0 ); + #else + hb_fsSetIOError( _commit( hFileHandle ) == 0, 0 ); + #endif + #endif + } #elif defined(HB_OS_OS2) { errno = 0; - /* TODO: what about error code from DosResetBuffer() call? */ DosResetBuffer( hFileHandle ); - - s_uiErrorLast = errno; + hb_fsSetIOError( errno == 0, 0 ); } #elif defined(HB_OS_UNIX) @@ -1202,45 +1145,45 @@ void HB_EXPORT hb_fsCommit( FHANDLE hFileHandle ) /* NOTE: close() functions releases all lock regardles if it is an * original or duplicated file handle */ - #if defined(_POSIX_SYNCHRONIZED_IO) && (_POSIX_SYNCHRONIZED_IO > 0) + #if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO + 0 > 0 /* faster - flushes data buffers only, without updating directory info */ - s_uiErrorLast = ( fdatasync( hFileHandle ) < -1 ) ? FS_ERROR : 0; - if( s_uiErrorLast == EINVAL ) - { - /* This implementation does not support synchronised I/O for - this file, so use the slower method that flushes all file - data buffers and i-node info for this file. - */ - s_uiErrorLast = ( fsync( hFileHandle ) < -1 ) ? FS_ERROR : 0; - } + hb_fsSetIOError( fdatasync( hFileHandle ) == 0, 0 ); #else /* slower - flushes all file data buffers and i-node info */ - s_uiErrorLast = ( fsync( hFileHandle ) < -1 ) ? FS_ERROR : 0; + hb_fsSetIOError( fsync( hFileHandle ) == 0, 0 ); #endif #elif defined(__WATCOMC__) - _dos_commit( hFileHandle ); + hb_fsSetIOError( fsync( hFileHandle ) == 0, 0 ); #elif defined(HB_FS_FILE_IO) && !defined(HB_OS_OS2) && !defined(HB_OS_UNIX) + /* This hack is very dangerous. POSIX standard define that if _ANY_ + file handle is closed all locks set by the process on the file + pointed by this descriptor are removed. It doesn't matter they + were done using different descriptor. It means that we now clean + all locks on hFileHandle with the code below if the OS is POSIX + compilant. I vote to disable it. + */ { int dup_handle; - - errno = 0; + BOOL fResult = FALSE; dup_handle = dup( hFileHandle ); if( dup_handle != -1 ) + { close( dup_handle ); - - s_uiErrorLast = errno; + fResult = TRUE; + } + hb_fsSetIOError( fResult, 0 ); } #else - s_uiErrorLast = FS_ERROR; + hb_fsSetError( (USHORT) FS_ERROR ); #endif } @@ -1252,32 +1195,63 @@ BOOL HB_EXPORT hb_fsLock ( FHANDLE hFileHandle, ULONG ulStart, HB_TRACE(HB_TR_DEBUG, ("hb_fsLock(%p, %lu, %lu, %hu)", hFileHandle, ulStart, ulLength, uiMode)); -#if defined(X__WIN32__) - +#if defined(HB_WIN32_IO) { - errno = 0; - switch( uiMode & FL_MASK ) - { - case FL_LOCK: - bResult = ( LockFile( DostoWinHandle(hFileHandle), ulStart,0, ulLength,0 ) == 0 ); - break; - - case FL_UNLOCK: - bResult = ( UnlockFile( DostoWinHandle(hFileHandle), ulStart,0, ulLength,0 ) == 0 ); - break; - - default: - bResult = FALSE; - } - s_uiErrorLast = errno; - } + static BOOL s_bInit = 0, s_bWinNt ; + if ( !s_bInit ) + { + s_bInit = TRUE ; + s_bWinNt = hb_iswinnt() ; + } + switch( uiMode & FL_MASK ) + { + case FL_LOCK: + { + if ( s_bWinNt ) + { + OVERLAPPED sOlap ; + DWORD dwFlags ; + memset( &sOlap, 0, sizeof( OVERLAPPED ) ) ; + sOlap.Offset = ( ULONG ) ulStart ; + dwFlags = ( uiMode & FLX_SHARED ) ? 0 : LOCKFILE_EXCLUSIVE_LOCK ; + if ( !s_fUseWaitLocks || !( uiMode & FLX_WAIT ) ) + { + dwFlags |= LOCKFILE_FAIL_IMMEDIATELY ; + } + bResult = LockFileEx( DostoWinHandle( hFileHandle ), dwFlags, 0, ulLength, 0, &sOlap ); + } + else + { + bResult = LockFile( DostoWinHandle( hFileHandle ), ulStart, 0, ulLength,0 ); + } + break; + } + case FL_UNLOCK: + { + if ( s_bWinNt ) + { + OVERLAPPED sOlap ; + memset( &sOlap, 0, sizeof( OVERLAPPED ) ) ; + sOlap.Offset = ( ULONG ) ulStart ; + bResult = UnlockFileEx( DostoWinHandle( hFileHandle ), 0, ulLength,0, &sOlap ); + } + else + { + bResult = UnlockFile( DostoWinHandle( hFileHandle ), ulStart, 0, ulLength,0 ); + } + break; + + } + default: + bResult = FALSE; + } + } + hb_fsSetIOError( bResult, 0 ); #elif defined(HB_OS_OS2) { struct _FILELOCK fl, ful; - errno = 0; - switch( uiMode & FL_MASK ) { case FL_LOCK: @@ -1305,17 +1279,17 @@ BOOL HB_EXPORT hb_fsLock ( FHANDLE hFileHandle, ULONG ulStart, default: bResult = FALSE; } - s_uiErrorLast = errno; + hb_fsSetIOError( bResult, 0 ); } -#elif defined(_MSC_VER) +#elif defined(_MSC_VER) || defined(__DMC__) { - ULONG ulOldPos = hb_fsSeek( hFileHandle, ulStart, FS_SET ); + ULONG ulOldPos = lseek( hFileHandle, 0L, SEEK_CUR ); - errno = 0; + lseek( hFileHandle, ulStart, SEEK_SET ); switch( uiMode & FL_MASK ) { case FL_LOCK: - bResult = ( locking( hFileHandle, _LK_LOCK, ulLength ) == 0 ); + bResult = ( locking( hFileHandle, _LK_NBLCK, ulLength ) == 0 ); break; case FL_UNLOCK: @@ -1325,15 +1299,14 @@ BOOL HB_EXPORT hb_fsLock ( FHANDLE hFileHandle, ULONG ulStart, default: bResult = FALSE; } - s_uiErrorLast = errno; - - hb_fsSeek( hFileHandle, ulOldPos, FS_SET ); + hb_fsSetIOError( bResult, 0 ); + lseek( hFileHandle, ulOldPos, SEEK_SET ); } #elif defined(__MINGW32__) { - ULONG ulOldPos = hb_fsSeek( hFileHandle, ulStart, FS_SET ); + ULONG ulOldPos = lseek( hFileHandle, 0L, SEEK_CUR ); - errno = 0; + lseek( hFileHandle, ulStart, SEEK_SET ); switch( uiMode & FL_MASK ) { case FL_LOCK: @@ -1347,9 +1320,8 @@ BOOL HB_EXPORT hb_fsLock ( FHANDLE hFileHandle, ULONG ulStart, default: bResult = FALSE; } - s_uiErrorLast = errno; - - hb_fsSeek( hFileHandle, ulOldPos, FS_SET ); + hb_fsSetIOError( bResult, 0 ); + lseek( hFileHandle, ulOldPos, SEEK_SET ); } #elif defined(HB_OS_UNIX) { @@ -1386,12 +1358,10 @@ BOOL HB_EXPORT hb_fsLock ( FHANDLE hFileHandle, ULONG ulStart, default: bResult = FALSE; } - s_uiErrorLast = bResult ? 0 : errno; + hb_fsSetIOError( bResult, 0 ); } - #elif defined(HAVE_POSIX_IO) && !defined(__IBMCPP__) && ( !defined(__GNUC__) || defined(__DJGPP__) ) - errno = 0; switch( uiMode & FL_MASK ) { case FL_LOCK: @@ -1405,12 +1375,12 @@ BOOL HB_EXPORT hb_fsLock ( FHANDLE hFileHandle, ULONG ulStart, default: bResult = FALSE; } - s_uiErrorLast = errno; + hb_fsSetIOError( bResult, 0 ); #else bResult = FALSE; - s_uiErrorLast = FS_ERROR; + hb_fsSetError( (USHORT) FS_ERROR ); #endif @@ -1424,12 +1394,81 @@ BOOL HB_EXPORT hb_fsLockLarge( FHANDLE hFileHandle, HB_FOFFSET ulStart, HB_TRACE(HB_TR_DEBUG, ("hb_fsLockLarge(%p, %" PFHL "u, %" PFHL "u, %hu)", hFileHandle, ulStart, ulLength, uiMode)); -#if defined(HB_FS_FILE_IO) && defined(HB_OS_LINUX) && \ - defined(__USE_LARGEFILE64) - /* +#if defined(HB_WIN32_IO) + { + DWORD dwOffsetLo = ( DWORD ) ( ulStart & 0xFFFFFFFF ), + dwOffsetHi = ( DWORD ) ( ulStart >> 32 ), + dwLengthLo = ( DWORD ) ( ulLength & 0xFFFFFFFF ), + dwLengthHi = ( DWORD ) ( ulLength >> 32 ); + + static BOOL s_bInit = 0, s_bWinNt ; + + if ( !s_bInit ) + { + s_bInit = TRUE ; + s_bWinNt = hb_iswinnt() ; + } + + switch( uiMode & FL_MASK ) + { + case FL_LOCK: + if ( s_bWinNt ) + { + OVERLAPPED sOlap ; + DWORD dwFlags ; + + dwFlags = ( ( uiMode & FLX_SHARED ) ? 0 : LOCKFILE_EXCLUSIVE_LOCK ); + if ( !s_fUseWaitLocks || !( uiMode & FLX_WAIT ) ) + { + dwFlags |= LOCKFILE_FAIL_IMMEDIATELY ; + } + + memset( &sOlap, 0, sizeof( OVERLAPPED ) ); + sOlap.Offset = dwOffsetLo; + sOlap.OffsetHigh = dwOffsetHi; + + bResult = LockFileEx( DostoWinHandle( hFileHandle ), dwFlags, 0, + dwLengthLo, dwLengthHi, &sOlap ); + } + else + { + bResult = LockFile( DostoWinHandle( hFileHandle ), + dwOffsetLo, dwOffsetHi, + dwLengthLo, dwLengthHi ); + } + break; + + case FL_UNLOCK: + if ( s_bWinNt ) + { + OVERLAPPED sOlap ; + + memset( &sOlap, 0, sizeof( OVERLAPPED ) ); + sOlap.Offset = dwOffsetLo; + sOlap.OffsetHigh = dwOffsetHi; + + bResult = UnlockFileEx( DostoWinHandle( hFileHandle ), 0, + dwLengthLo, dwLengthHi, &sOlap ); + } + else + { + bResult = UnlockFile( DostoWinHandle( hFileHandle ), + dwOffsetLo, dwOffsetHi, + dwLengthLo, dwLengthHi ); + } + break; + + default: + bResult = FALSE; + } + hb_fsSetIOError( bResult, 0 ); + + } +#elif defined(HB_OS_LINUX) && defined(__USE_LARGEFILE64) + /* * The macro: __USE_LARGEFILE64 is set when _LARGEFILE64_SOURCE is - * define and efectively enables lseek64/flock64 functions on 32bit - * machines. + * define and efectively enables lseek64/flock64/ftruncate64 functions + * on 32bit machines. */ { struct flock64 lock_info; @@ -1463,7 +1502,7 @@ BOOL HB_EXPORT hb_fsLockLarge( FHANDLE hFileHandle, HB_FOFFSET ulStart, default: bResult = FALSE; } - s_uiErrorLast = bResult ? 0 : errno; + hb_fsSetIOError( bResult, 0 ); } #else bResult = hb_fsLock( hFileHandle, (ULONG) ulStart, (ULONG) ulLength, uiMode ); @@ -1475,94 +1514,83 @@ BOOL HB_EXPORT hb_fsLockLarge( FHANDLE hFileHandle, HB_FOFFSET ulStart, ULONG HB_EXPORT hb_fsSeek( FHANDLE hFileHandle, LONG lOffset, USHORT uiFlags ) { ULONG ulPos; - USHORT Flags; HB_TRACE(HB_TR_DEBUG, ("hb_fsSeek(%p, %ld, %hu)", hFileHandle, lOffset, uiFlags)); - Flags = convert_seek_flags( uiFlags ); - - if( lOffset < 0 && Flags == SEEK_SET ) - { +#if defined(HB_FS_FILE_IO) +{ + USHORT Flags = convert_seek_flags( uiFlags ); #if defined(HB_OS_OS2) + { + APIRET ret; + /* This DOS hack creates 2GB file size limit, Druzus */ + if( lOffset < 0 && Flags == SEEK_SET ) { - APIRET ret = DosSetFilePtr( hFileHandle, 0, SEEK_CUR, &ulPos ); - - if( ret != 0 ) - { - ulPos = 0; - s_uiErrorLast = ( USHORT ) ret; - } - } - - #elif defined(HB_FS_FILE_IO) - - /* get current offset */ - errno = 0; - #if defined(X__WIN32__) - ulPos = SetFilePointer( DostoWinHandle( hFileHandle ), 0, NULL, FILE_CURRENT ); - if( ( DWORD ) ulPos == 0xFFFFFFFF ) - errno = GetLastError(); - #else - ulPos = lseek( hFileHandle, 0, SEEK_CUR ); - #endif - if( errno != 0 ) - { - ulPos = 0; - s_uiErrorLast = errno; + ret = 1; + hb_fsSetError( 25 ); /* 'Seek Error' */ } else - s_uiErrorLast = 25; /* 'Seek Error' */ - - #else - - ulPos = 0; - s_uiErrorLast = 25; /* 'Seek Error' */ - - #endif - - } - else - { - - #if defined(HB_OS_OS2) - { - APIRET ret = DosSetFilePtr( hFileHandle, lOffset, Flags, &ulPos ); - - if( ret != 0 ) + ret = DosSetFilePtr( hFileHandle, lOffset, Flags, &ulPos ); + /* TODO: what we should do with this error code? Is it DOS compatible? */ + hb_fsSetError(( USHORT ) ret ); + } + if( ret != 0 ) + { + /* FIXME: it should work if DosSetFilePtr is lseek compatible + but maybe OS2 has DosGetFilePtr too, if not then remove this + comment, Druzus */ + if ( DosSetFilePtr( hFileHandle, 0, SEEK_CUR, &ulPos ) != 0 ) { ulPos = 0; - s_uiErrorLast = ( USHORT ) ret; } } - - #elif defined(HB_FS_FILE_IO) - - errno = 0; - #if defined(X__WIN32__) - ulPos = SetFilePointer( DostoWinHandle( hFileHandle ), lOffset, NULL, ( DWORD ) Flags ); - if( ( DWORD ) ulPos == 0xFFFFFFFF ) - errno = GetLastError(); - #else - ulPos = lseek( hFileHandle, lOffset, Flags ); - #endif - if( errno != 0 ) - ulPos = 0; - s_uiErrorLast = errno; - - #else - - ulPos = 0; - s_uiErrorLast = FS_ERROR; - - #endif - - /* Convert 'Unknown Command' to 'Seek Error' */ - if( s_uiErrorLast == 22 ) - s_uiErrorLast = 25; } + #elif defined(HB_WIN32_IO) + /* This DOS hack creates 2GB file size limit, Druzus */ + if( lOffset < 0 && Flags == SEEK_SET ) + { + ulPos = (ULONG) INVALID_SET_FILE_POINTER; + hb_fsSetError( 25 ); /* 'Seek Error' */ + } + else + { + ulPos = (DWORD) SetFilePointer( DostoWinHandle(hFileHandle), lOffset, NULL, (DWORD)Flags ); + hb_fsSetIOError( (DWORD) ulPos != INVALID_SET_FILE_POINTER, 0 ); + } + + if ( (DWORD) ulPos == INVALID_SET_FILE_POINTER ) + { + ulPos = (DWORD) SetFilePointer( DostoWinHandle(hFileHandle), 0, NULL, SEEK_CUR ); + } + #else + /* This DOS hack creates 2GB file size limit, Druzus */ + if( lOffset < 0 && Flags == SEEK_SET ) + { + ulPos = (ULONG) -1; + hb_fsSetError( 25 ); /* 'Seek Error' */ + } + else + { + ulPos = lseek( hFileHandle, lOffset, Flags ); + hb_fsSetIOError( ulPos != (ULONG) -1, 0 ); + } + if ( ulPos == (ULONG) -1 ) + { + ulPos = lseek( hFileHandle, 0L, SEEK_CUR ); + if ( ulPos == (ULONG) -1 ) + { + ulPos = 0; + } + } + #endif + } +#else + hb_fsSetError( 25 ); + ulPos = 0; +#endif return ulPos; } @@ -1573,17 +1601,54 @@ HB_FOFFSET HB_EXPORT hb_fsSeekLarge( FHANDLE hFileHandle, HB_FOFFSET llOffset, U HB_TRACE(HB_TR_DEBUG, ("hb_fsSeekLarge(%p, %" PFHL "u, %hu)", hFileHandle, llOffset, uiFlags)); -#if defined(HB_FS_FILE_IO) && defined(HB_OS_LINUX) && \ - defined(__USE_LARGEFILE64) - /* +#if defined(HB_WIN32_IO) + { + USHORT Flags = convert_seek_flags( uiFlags ); + + ULONG ulOffsetLow = ( ULONG ) ( llOffset & ULONG_MAX ), + ulOffsetHigh = ( ULONG ) ( llOffset >> 32 ); + + if( llOffset < 0 && Flags == SEEK_SET ) + { + llPos = ( HB_FOFFSET ) INVALID_SET_FILE_POINTER; + hb_fsSetError( 25 ); /* 'Seek Error' */ + } + else + { + ulOffsetLow = SetFilePointer( DostoWinHandle( hFileHandle ), + ulOffsetLow, (PLONG) &ulOffsetHigh, + ( DWORD ) Flags ); + llPos = ( ( HB_FOFFSET ) ulOffsetHigh << 32 ) | ulOffsetLow; + hb_fsSetIOError( llPos != ( HB_FOFFSET ) INVALID_SET_FILE_POINTER, 0 ); + } + + if ( llPos == ( HB_FOFFSET ) INVALID_SET_FILE_POINTER ) + { + ulOffsetHigh = 0; + ulOffsetLow = SetFilePointer( DostoWinHandle( hFileHandle ), + 0, (PLONG) &ulOffsetHigh, SEEK_CUR ); + llPos = ( ( HB_FOFFSET ) ulOffsetHigh << 32 ) | ulOffsetLow; + } + } +#elif defined(HB_OS_LINUX) && defined(__USE_LARGEFILE64) + /* * The macro: __USE_LARGEFILE64 is set when _LARGEFILE64_SOURCE is - * define and efectively enables lseek64/flock64 functions on 32bit - * machines. + * define and efectively enables lseek64/flock64/ftruncate64 functions + * on 32bit machines. */ { USHORT Flags = convert_seek_flags( uiFlags ); - llPos = lseek64( hFileHandle, llOffset, Flags ); - s_uiErrorLast = ( llPos != (HB_FOFFSET) -1 ? 0 : errno ); + + if( llOffset < 0 && Flags == SEEK_SET ) + { + llPos = (HB_FOFFSET) -1; + hb_fsSetError( 25 ); /* 'Seek Error' */ + } + else + { + llPos = lseek64( hFileHandle, llOffset, Flags ); + hb_fsSetIOError( llPos != (HB_FOFFSET) -1, 0 ); + } if ( llPos == (HB_FOFFSET) -1 ) { @@ -1597,7 +1662,7 @@ HB_FOFFSET HB_EXPORT hb_fsSeekLarge( FHANDLE hFileHandle, HB_FOFFSET llOffset, U return llPos; } -ULONG HB_EXPORT hb_fsTell( FHANDLE hFileHandle ) +ULONG HB_EXPORT hb_fsTell( FHANDLE hFileHandle ) { ULONG ulPos; @@ -1605,77 +1670,56 @@ ULONG HB_EXPORT hb_fsTell( FHANDLE hFileHandle ) #if defined(HB_FS_FILE_IO) - errno = 0; - #if defined(X__WIN32__) - ulPos = SetFilePointer( DostoWinHandle( hFileHandle ), 0, NULL, FILE_CURRENT ); - if( ( DWORD ) ulPos == 0xFFFFFFFF ) - errno = GetLastError(); + #if defined(HB_WIN32_IO) + ulPos = (DWORD) SetFilePointer( DostoWinHandle(hFileHandle), 0, NULL, FILE_CURRENT ); + hb_fsSetIOError( (DWORD) ulPos != INVALID_SET_FILE_POINTER, 0 ); #else ulPos = lseek( hFileHandle, 0L, SEEK_CUR ); + hb_fsSetIOError( ulPos != (ULONG) -1, 0 ); #endif - s_uiErrorLast = errno; #else - ulPos = 0; - s_uiErrorLast = FS_ERROR; + ulPos = (ULONG) -1; + hb_fsSetError( (USHORT) FS_ERROR ); #endif return ulPos; } -USHORT HB_EXPORT hb_fsError( void ) -{ - HB_TRACE(HB_TR_DEBUG, ("hb_fsError()")); - - return s_uiErrorLast; -} - -void hb_fsSetError( USHORT uiError ) -{ - HB_TRACE(HB_TR_DEBUG, ("hb_fsSetError(%hu)", uiError)); - - s_uiErrorLast = uiError; -} - BOOL HB_EXPORT hb_fsDelete( BYTE * pFilename ) { BOOL bResult; HB_TRACE(HB_TR_DEBUG, ("hb_fsDelete(%s)", (char*) pFilename)); -#if defined(X__WIN32__) + pFilename = hb_fileNameConv( hb_strdup( ( char * ) pFilename ) ); - if( ( bResult = DeleteFile( ( char * ) pFilename ) ) == 0 ) - { - #if !defined(__BORLANDC__) - errno = WintoDosError( GetLastError() ); - #else - __NTerror(); - #endif - } - s_uiErrorLast = errno; +#if defined(HB_OS_WIN_32) + + bResult = DeleteFile( ( char * ) pFilename ); + hb_fsSetIOError( bResult, 0 ); #elif defined(HAVE_POSIX_IO) - errno = 0; - bResult = ( unlink( ( char * ) pFilename ) == 0 ); - s_uiErrorLast = errno; - -#elif defined(_MSC_VER) || defined(__MINGW32__) - - errno = 0; bResult = ( remove( ( char * ) pFilename ) == 0 ); - s_uiErrorLast = errno; + hb_fsSetIOError( bResult, 0 ); + +#elif defined(_MSC_VER) || defined(__MINGW32__) || defined(__DMC__) + + bResult = ( remove( ( char * ) pFilename ) == 0 ); + hb_fsSetIOError( bResult, 0 ); #else bResult = FALSE; - s_uiErrorLast = FS_ERROR; + hb_fsSetError( (USHORT) FS_ERROR ); #endif + hb_xfree( pFilename ) ; + return bResult; } @@ -1685,32 +1729,29 @@ BOOL HB_EXPORT hb_fsRename( BYTE * pOldName, BYTE * pNewName ) HB_TRACE(HB_TR_DEBUG, ("hb_fsRename(%s, %s)", (char*) pOldName, (char*) pNewName)); -#if defined(X__WIN32__) + pOldName = hb_fileNameConv( hb_strdup( ( char * ) pOldName ) ); + pNewName = hb_fileNameConv( hb_strdup( ( char * ) pNewName ) ); - errno = 0; - if( ( bResult = MoveFile( ( char * ) pOldName, ( char * ) pNewName ) ) == 0 ) - { - #if !defined(__BORLANDC__) - errno = WintoDosError( GetLastError() ); - #else - __NTerror(); - #endif - } - s_uiErrorLast = errno; +#if defined(HB_OS_WIN_32) + + bResult = MoveFile( ( char * ) pOldName, ( char * ) pNewName ); + hb_fsSetIOError( bResult, 0 ); #elif defined(HB_FS_FILE_IO) - errno = 0; bResult = ( rename( ( char * ) pOldName, ( char * ) pNewName ) == 0 ); - s_uiErrorLast = errno; + hb_fsSetIOError( bResult, 0 ); #else bResult = FALSE; - s_uiErrorLast = FS_ERROR; + hb_fsSetError( (USHORT) FS_ERROR ); #endif + hb_xfree( pOldName ) ; + hb_xfree( pNewName ) ; + return bResult; } @@ -1720,22 +1761,17 @@ BOOL HB_EXPORT hb_fsMkDir( BYTE * pDirname ) HB_TRACE(HB_TR_DEBUG, ("hb_fsMkDir(%s)", (char*) pDirname)); - pDirname = ( BYTE * ) hb_strdup ( ( char * ) pDirname ); + pDirname = hb_fileNameConv( hb_strdup( ( char * ) pDirname ) ); - if( hb_set.HB_SET_DIRCASE == HB_SET_CASE_LOWER ) - pDirname = ( BYTE * ) hb_strLower( ( char *) pDirname, strlen( ( char *) pDirname ) ); - else if( hb_set.HB_SET_DIRCASE == HB_SET_CASE_UPPER) - pDirname = ( BYTE * ) hb_strUpper( ( char *) pDirname, strlen( ( char *) pDirname ) ); + HB_TRACE(HB_TR_DEBUG, ("hb_fsMkDir(%s)", (char*) pDirname)); #if defined(HB_OS_WIN_32) bResult = CreateDirectory( ( char * ) pDirname, NULL ); - s_uiErrorLast = ( USHORT ) GetLastError(); + hb_fsSetIOError( bResult, 0 ); #elif defined(HAVE_POSIX_IO) || defined(__MINGW32__) - errno = 0; - # if ! defined(HB_OS_UNIX) && \ ( defined(__WATCOMC__) || defined(__BORLANDC__) || \ defined(__IBMCPP__) || defined(__MINGW32__) ) @@ -1743,17 +1779,16 @@ BOOL HB_EXPORT hb_fsMkDir( BYTE * pDirname ) # else bResult = ( mkdir( ( char * ) pDirname, S_IRWXU | S_IRWXG | S_IRWXO ) == 0 ); # endif - - s_uiErrorLast = errno; + hb_fsSetIOError( bResult, 0 ); #else bResult = FALSE; - s_uiErrorLast = FS_ERROR; + hb_fsSetError( (USHORT) FS_ERROR ); #endif - hb_xfree( pDirname ); + hb_xfree(pDirname) ; return bResult; } @@ -1764,28 +1799,22 @@ BOOL HB_EXPORT hb_fsChDir( BYTE * pDirname ) HB_TRACE(HB_TR_DEBUG, ("hb_fsChDir(%s)", (char*) pDirname)); - pDirname = ( BYTE *) hb_strdup ( ( char * ) pDirname ); - - if( hb_set.HB_SET_DIRCASE == HB_SET_CASE_LOWER ) - pDirname = ( BYTE * ) hb_strLower( ( char *) pDirname, strlen( ( char *) pDirname ) ); - else if( hb_set.HB_SET_DIRCASE == HB_SET_CASE_UPPER) - pDirname = ( BYTE * ) hb_strUpper( ( char *) pDirname, strlen( ( char *) pDirname ) ); + pDirname = hb_fileNameConv( hb_strdup( ( char * ) pDirname ) ); #if defined(HB_OS_WIN_32) bResult = SetCurrentDirectory( ( char * ) pDirname ); - s_uiErrorLast = ( USHORT ) GetLastError(); + hb_fsSetIOError( bResult, 0 ); #elif defined(HAVE_POSIX_IO) || defined(__MINGW32__) - errno = 0; bResult = ( chdir( ( char * ) pDirname ) == 0 ); - s_uiErrorLast = errno; + hb_fsSetIOError( bResult, 0 ); #else bResult = FALSE; - s_uiErrorLast = FS_ERROR; + hb_fsSetError( (USHORT) FS_ERROR ); #endif @@ -1800,28 +1829,22 @@ BOOL HB_EXPORT hb_fsRmDir( BYTE * pDirname ) HB_TRACE(HB_TR_DEBUG, ("hb_fsRmDir(%s)", (char*) pDirname)); - pDirname = ( BYTE * ) hb_strdup ( ( char * ) pDirname ); - - if( hb_set.HB_SET_DIRCASE == HB_SET_CASE_LOWER ) - pDirname = ( BYTE * ) hb_strLower( ( char *) pDirname, strlen( ( char *) pDirname ) ); - else if( hb_set.HB_SET_DIRCASE == HB_SET_CASE_UPPER) - pDirname = ( BYTE * ) hb_strUpper( ( char *) pDirname, strlen( ( char *) pDirname ) ); + pDirname = hb_fileNameConv( hb_strdup( ( char * ) pDirname ) ); #if defined(HB_OS_WIN_32) bResult = RemoveDirectory( ( char * ) pDirname ); - s_uiErrorLast = ( USHORT ) GetLastError(); + hb_fsSetIOError( bResult, 0 ); #elif defined(HAVE_POSIX_IO) || defined(__MINGW32__) - errno = 0; bResult = ( rmdir( ( char * ) pDirname ) == 0 ); - s_uiErrorLast = errno; + hb_fsSetIOError( bResult, 0 ); #else bResult = FALSE; - s_uiErrorLast = FS_ERROR; + hb_fsSetError( (USHORT) FS_ERROR ); #endif @@ -1849,49 +1872,79 @@ BYTE * HB_EXPORT hb_fsCurDir( USHORT uiDrive ) USHORT HB_EXPORT hb_fsCurDirBuff( USHORT uiDrive, BYTE * pbyBuffer, ULONG ulLen ) { - HB_TRACE(HB_TR_DEBUG, ("hb_fsCurDirBuff(%hu)", uiDrive)); + USHORT uiCurDrv = uiDrive, usError; + BOOL fResult; - HB_SYMBOL_UNUSED( uiDrive ); + HB_TRACE(HB_TR_DEBUG, ("hb_fsCurDirBuff(%hu)", uiDrive)); pbyBuffer[ 0 ] = '\0'; + /* + * do not cover this code by OS_HAS_DRIVE_LETTER macro + * It will allow us to add drive emulation in hb_fsCurDrv()/hb_fsChDrv() + * and hb_fileNameConv() + */ +#if !defined(HB_OS_OS2) + if( uiDrive ) + { + uiCurDrv = hb_fsCurDrv() + 1; + if( uiDrive != uiCurDrv ) + { + hb_fsChDrv( uiDrive - 1 ); + } + } +#endif + #if defined(HB_OS_WIN_32) - GetCurrentDirectory( ulLen, ( char * ) pbyBuffer ); - s_uiErrorLast = ( USHORT ) GetLastError(); + fResult = GetCurrentDirectory( ulLen, ( char * ) pbyBuffer ); + hb_fsSetIOError( fResult, 0 ); + +#elif defined(HB_OS_OS2) + + fResult = ( _getcwd1( (char *) pbyBuffer, uiDrive + 'A' - 1 ) == 0 ); + hb_fsSetIOError( fResult, 0 ); #elif defined(HAVE_POSIX_IO) - errno = 0; - getcwd( ( char * ) pbyBuffer, ulLen ); - s_uiErrorLast = errno; + fResult = ( getcwd( ( char * ) pbyBuffer, ulLen ) != NULL ); + hb_fsSetIOError( fResult, 0 ); #elif defined(__MINGW32__) - errno = 0; - _getdcwd( uiDrive, pbyBuffer, ulLen ); - s_uiErrorLast = errno; + fResult = ( _getdcwd( uiDrive, pbyBuffer, ulLen ) != NULL ); + hb_fsSetIOError( fResult, 0 ); #else - s_uiErrorLast = FS_ERROR; + fResult = FALSE; + hb_fsSetError( (USHORT) FS_ERROR ); #endif - /* Strip the leading drive spec, and leading backslash if there's one. */ + usError = hb_fsError(); + if( uiDrive != uiCurDrv ) + { + hb_fsChDrv( uiCurDrv - 1 ); + hb_fsSetError( usError ); + } + + if( usError == 0 ) { BYTE * pbyStart = pbyBuffer; + /* Strip the leading drive spec, and leading backslash if there's one. */ /* NOTE: A trailing underscore is not returned on this platform, so we don't need to strip it. [vszakats] */ - if( pbyStart[ 1 ] == ':' ) +#if defined(OS_HAS_DRIVE_LETTER) + if( pbyStart[ 1 ] == OS_DRIVE_DELIMITER ) { pbyStart += 2; ulLen -= 2; } - +#endif if( strchr( OS_PATH_DELIMITER_LIST, pbyStart[ 0 ] ) ) { pbyStart++; @@ -1900,18 +1953,15 @@ USHORT HB_EXPORT hb_fsCurDirBuff( USHORT uiDrive, BYTE * pbyBuffer, ULONG ulLen if( pbyBuffer != pbyStart ) memmove( pbyBuffer, pbyStart, ulLen ); - } - - /* Strip the trailing (back)slash if there's one */ - - { - ULONG ulLen = strlen( ( char * ) pbyBuffer ); + /* Strip the trailing (back)slash if there's one */ if( strchr( OS_PATH_DELIMITER_LIST, pbyBuffer[ ulLen - 1 ] ) ) - pbyBuffer[ ulLen - 1 ] = '\0'; + ulLen--; + + pbyBuffer[ ulLen ] = '\0'; } - return s_uiErrorLast; + return usError; } /* NOTE: 0=A:, 1=B:, 2=C:, 3=D:, ... */ @@ -1923,59 +1973,32 @@ USHORT HB_EXPORT hb_fsChDrv( BYTE nDrive ) HB_TRACE(HB_TR_DEBUG, ("hb_fsChDrv(%d)", (int) nDrive)); #if defined(OS_HAS_DRIVE_LETTER) - - #if defined( __WATCOMC__ ) - { - /* 'unsigned int' _have to_ be used in Watcom - */ - unsigned int uiSave; - unsigned int uiTotal; + /* 'unsigned int' _have to_ be used in Watcom */ + UINT uiSave, uiNewDrive; - /* 1 = A:, 2 = B:, 3 = C:, etc - * _dos_*() functions don't set 'errno' - */ - _dos_getdrive( &uiSave ); + HB_FS_GETDRIVE( uiSave ); + HB_FS_SETDRIVE( nDrive ); + HB_FS_GETDRIVE( uiNewDrive ); - _dos_setdrive( nDrive + 1, &uiTotal ); - _dos_getdrive( &uiTotal ); - if( ( nDrive + 1 ) == uiTotal ) + if( ( UINT ) nDrive == uiNewDrive ) { uiResult = 0; - s_uiErrorLast = 0; + hb_fsSetError( 0 ); } else { - _dos_setdrive( uiSave, &uiTotal ); - uiResult = FS_ERROR; - s_uiErrorLast = FS_ERROR; - } - } - #else - { - USHORT uiSave = _getdrive(); + HB_FS_SETDRIVE( uiSave ); - errno = 0; - _chdrive( nDrive + 1 ); - if( ( nDrive + 1 ) == _getdrive() ) - { - uiResult = 0; - s_uiErrorLast = errno; + uiResult = (USHORT) FS_ERROR; + hb_fsSetError( (USHORT) FS_ERROR ); } - else - { - _chdrive( uiSave ); - uiResult = FS_ERROR; - s_uiErrorLast = FS_ERROR; - } - } - #endif + } #else HB_SYMBOL_UNUSED( nDrive ); - uiResult = ( USHORT ) FS_ERROR; - s_uiErrorLast = ( USHORT ) FS_ERROR; + hb_fsSetError( ( USHORT ) FS_ERROR ); #endif @@ -1995,58 +2018,32 @@ USHORT HB_EXPORT hb_fsIsDrv( BYTE nDrive ) HB_TRACE(HB_TR_DEBUG, ("hb_fsIsDrv(%d)", (int) nDrive)); #if defined(OS_HAS_DRIVE_LETTER) - - #if defined( __WATCOMC__ ) - { /* 'unsigned int' _have to_ be used in Watcom */ - unsigned int uiSave; - unsigned int uiTotal; + UINT uiSave, uiNewDrive; - /* 1= A:, 2 = B:, 3 = C:, etc - * _dos_*() functions don't set 'errno' - */ - _dos_getdrive( &uiSave ); - - s_uiErrorLast = 0; - uiResult = 0; - _dos_setdrive( nDrive + 1, &uiTotal ); - _dos_getdrive( &uiTotal ); - if( ( nDrive + 1 ) != uiTotal ) + HB_FS_GETDRIVE( uiSave ); + HB_FS_SETDRIVE( nDrive ); + HB_FS_GETDRIVE( uiNewDrive ); + if( ( UINT ) nDrive != uiNewDrive ) { - s_uiErrorLast = FS_ERROR; - uiResult = FS_ERROR; - } - _dos_setdrive( uiSave, &uiTotal ); - } - #else - { - USHORT uiSave = _getdrive(); - - errno = 0; - _chdrive( nDrive + 1 ); - if( ( nDrive + 1 ) == _getdrive() ) - { - uiResult = 0; - s_uiErrorLast = errno; + uiResult = (USHORT) FS_ERROR; + hb_fsSetError( (USHORT) FS_ERROR ); } else { - uiResult = FS_ERROR; - s_uiErrorLast = FS_ERROR; + uiResult = 0; + hb_fsSetError( 0 ); } - - _chdrive( uiSave ); + HB_FS_SETDRIVE( uiSave ); } - #endif #else HB_SYMBOL_UNUSED( nDrive ); - uiResult = ( USHORT ) FS_ERROR; - s_uiErrorLast = ( USHORT ) FS_ERROR; + hb_fsSetError( ( USHORT ) FS_ERROR ); #endif @@ -2061,14 +2058,13 @@ BOOL HB_EXPORT hb_fsIsDevice( FHANDLE hFileHandle ) #if defined(HB_FS_FILE_IO) - errno = 0; bResult = ( isatty( hFileHandle ) != 0 ); - s_uiErrorLast = errno; + hb_fsSetIOError( bResult, 0 ); #else bResult = FALSE; - s_uiErrorLast = FS_ERROR; + hb_fsSetError( (USHORT) FS_ERROR ); HB_SYMBOL_UNUSED( hFileHandle ); #endif @@ -2086,45 +2082,12 @@ BYTE HB_EXPORT hb_fsCurDrv( void ) #if defined(OS_HAS_DRIVE_LETTER) - #if defined( __WATCOMC__ ) - { - /* 'unsigned int' _have to_ be used in Watcom - */ - unsigned uiDrive; - - /* 1 = A:, 2 = B:, 3 = C:, etc - * _dos_*() functions don't set 'errno' - */ - _dos_getdrive( &uiDrive ); - s_uiErrorLast = 0; - uiResult = ( USHORT ) uiDrive - 1; - } - #else - { - errno = 0; - uiResult = _getdrive(); - #if defined(__DJGPP__) - /* _getdrive() returned a drive number, base 0. */ - #else - if( uiResult < 65 ) - { - /* _getdrive() returned a drive number, base 1. */ - uiResult--; - } - else - { - /* _getdrive() returned a drive letter. */ - uiResult -= 65; - } - #endif - s_uiErrorLast = errno; - } - #endif + HB_FS_GETDRIVE( uiResult ); #else uiResult = 0; - s_uiErrorLast = ( USHORT ) FS_ERROR; + hb_fsSetError( ( USHORT ) FS_ERROR ); #endif @@ -2296,87 +2259,116 @@ FHANDLE HB_EXPORT hb_fsExtOpen( BYTE * pFilename, BYTE * pDefExt, return hFile; } - -BOOL hb_fsEof( FHANDLE hFileHandle ) +BOOL HB_EXPORT hb_fsEof( FHANDLE hFileHandle ) { #if defined(__DJGPP__) || defined(__CYGWIN__) || defined(OS_UNIX_COMPATIBLE) - long curPos = lseek( hFileHandle, 0L, SEEK_CUR ); - long endPos = lseek( hFileHandle, 0L, SEEK_END ); - long newPos = lseek( hFileHandle, curPos, SEEK_SET ); - if( newPos == -1L ) + LONG curPos; + LONG endPos; + LONG newPos; + BOOL fResult = FALSE; + + curPos = lseek( hFileHandle, 0L, SEEK_CUR ); + if ( curPos != -1 ) { - hb_fsSetError( errno ); + endPos = lseek( hFileHandle, 0L, SEEK_END ); + newPos = lseek( hFileHandle, curPos, SEEK_SET ); + fResult = ( endPos != -1 && newPos == curPos ); } - else if( newPos != curPos ) + else { - hb_fsSetError( ( USHORT ) FS_ERROR ); + endPos = -1; } - return curPos >= endPos; + hb_fsSetIOError( fResult, 0 ); + + return ( !fResult || curPos == endPos ); #else return eof( hFileHandle ) != 0; #endif } -#if defined(X__WIN32__) +BYTE HB_EXPORT * hb_fileNameConv( char *str ) { +/* + Convert file and dir case. The allowed SET options are: + LOWER - Convert all caracters of file to lower + UPPER - Convert all caracters of file to upper + MIXED - Leave as is -static HANDLE DostoWinHandle( FHANDLE fHandle) -{ - switch( fHandle ) + The allowed environment options are: + FILECASE - define the case of file + DIRCASE - define the case of path + DIRSEPARATOR - define separator of path (Ex. "/") +*/ + char *filename; + ULONG ulDirLen, ulFileLen; + +#ifdef __XHARBOUR__ + if ( hb_set.HB_SET_TRIMFILENAME ) { - case 0: - return GetStdHandle(STD_INPUT_HANDLE); - case 1: - return GetStdHandle(STD_OUTPUT_HANDLE); - case 2: - return GetStdHandle(STD_ERROR_HANDLE); - default : - return LongToHandle( fHandle ); - } -} + char *szFileTrim; + ULONG ulLen; + ulLen = hb_strRTrimLen( str, strlen( str ), FALSE ); + szFileTrim = hb_strLTrim( str, &ulLen ); + if ( str != szFileTrim ) + { + memmove( str, szFileTrim, ulLen ); + } + str[ulLen] = '\0'; + } #endif -BYTE HB_EXPORT * hb_fileNameConv(char *str) { -/* - Convert file and dir case. The allowed SET options are: - LOWER - Convert all caracters of file to lower - UPPER - Convert all caracters of file to upper - MIXED - Leave as is - - The allowed environment options are: - FILECASE - define the case of file - DIRCASE - define the case of path - DIRSEPARATOR - define separator of path (Ex. "/") -*/ - size_t a; - char *filename; - char *dirname=str; - size_t dirlen; - /* char * szFileTrim =str; */ - /* Look for filename (Last "\" or DIRSEPARATOR) */ - if( hb_set.HB_SET_DIRSEPARATOR != '\\' ) { - for(a=0;a 0 ) + { + if( hb_set.HB_SET_FILECASE == HB_SET_CASE_LOWER ) + hb_strLower( filename, strlen(filename) ); + else if( hb_set.HB_SET_FILECASE == HB_SET_CASE_UPPER ) + hb_strUpper( filename, strlen(filename) ); + } /* DIRCASE */ - if( hb_set.HB_SET_DIRCASE == HB_SET_CASE_LOWER ) - hb_strLower(dirname,dirlen); - else if( hb_set.HB_SET_DIRCASE == HB_SET_CASE_UPPER ) - hb_strUpper(dirname,dirlen); + if ( ulDirLen > 0 ) + { + if ( hb_set.HB_SET_DIRCASE == HB_SET_CASE_LOWER ) + hb_strLower( str, ulDirLen ); + else if( hb_set.HB_SET_DIRCASE == HB_SET_CASE_UPPER ) + hb_strUpper( str, ulDirLen ); + } return (( BYTE * ) str); } +BOOL HB_EXPORT hb_fsDisableWaitLocks( int iSet ) +{ + BOOL fRetVal = s_fUseWaitLocks; + + if ( iSet >= 0 ) + { + s_fUseWaitLocks = ( iSet == 0 ); + } + return fRetVal; +} diff --git a/harbour/source/rtl/fserror.c b/harbour/source/rtl/fserror.c new file mode 100644 index 0000000000..989e5c517b --- /dev/null +++ b/harbour/source/rtl/fserror.c @@ -0,0 +1,238 @@ +/* + * $Id$ + */ + +/* + * xHarbour Project source code: + * + * + * Copyright 2003 Przemyslaw Czerpak + * www - http://www.xharbour.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/). + * + * As a special exception, the Harbour Project gives permission for + * additional uses of the text contained in its release of Harbour. + * + * The exception is that, if you link the Harbour libraries with other + * files to produce an executable, this does not by itself cause the + * resulting executable to be covered by the GNU General Public License. + * Your use of that executable is in no way restricted on account of + * linking the Harbour library code into it. + * + * This exception does not however invalidate any other reasons why + * the executable file might be covered by the GNU General Public License. + * + * This exception applies only to the code released by the Harbour + * Project under the name Harbour. If you copy code from other + * Harbour Project or Free Software Foundation releases into a copy of + * Harbour, as the General Public License permits, the exception does + * not apply to the code that you add in this way. To avoid misleading + * anyone as to the status of such modified files, you must delete + * this exception notice from them. + * + * If you write modifications of your own for Harbour, it is your choice + * whether to permit this exception to apply to your modifications. + * If you do not wish that, delete this exception notice. + * + */ + +#ifndef HB_OS_WIN_32_USED + #define HB_OS_WIN_32_USED +#endif + +#include "hbapi.h" +#include "hbapifs.h" +#include "hb_io.h" +#include + +static USHORT s_uiErrorLast = 0; +static USHORT s_uiOsErrorLast = 0; + + +/* Try to translate C errno into DOS error code */ + +#if !defined(HB_WIN32_IO) +static int hb_errnoToDosError( int ErrCode ) +{ + int iResult; + +#if defined(__BORLANDC__) + /* These C compilers use DOS error codes in errno */ + iResult = ErrCode; +#else + switch ( ErrCode ) + { + case ENOENT: + iResult = 2; /* File not found */ + break; +#if defined( ENOTDIR ) + case ENOTDIR: + iResult = 3; /* Path not found */ + break; +#endif +#if defined( ENFILE ) + case ENFILE: +#endif + case EMFILE: + iResult = 4; /* Too many open files */ + break; + case EACCES: +#if defined( ETXTBSY ) + case ETXTBSY: +#endif + iResult = 5; /* Access denied */ + break; + case EBADF: + iResult = 6; /* Invalid handle */ + break; + case ENOMEM: + iResult = 8; /* Insufficient memory */ + break; +#if defined( EFAULT ) + case EFAULT: + iResult = 9; /* Invalid memory block address */ + break; +#endif + case EINVAL: + iResult = 13; /* Invalid data */ + break; +#if defined( EROFS ) + case EROFS: + iResult = 19; /* Attempt to write on write-protected diskette */ + break; +#endif +#if defined( ESPIPE ) + case ESPIPE: + iResult = 25; /* Seek error */ + break; +#endif + case EPIPE: + iResult = 29; /* Write fault */ + break; + case EEXIST: + iResult = 32; /* Sharing violation */ + break; + case EAGAIN: + iResult = 33; /* Lock violation */ + break; + default: + iResult = ErrCode; + break; + } +#endif + + return iResult; +} +#endif + +#if defined(HB_WIN32_IO) || defined(HB_OS_WIN_32) +static int hb_WinToDosError( ULONG ulError ) +{ + int iResult; + + switch ( ulError ) + { + case ERROR_ALREADY_EXISTS: + iResult = 5; + break; + case ERROR_FILE_NOT_FOUND: + iResult = 2; + break; + case ERROR_PATH_NOT_FOUND: + iResult = 3; + break; + case ERROR_TOO_MANY_OPEN_FILES: + iResult = 4; + break; + case ERROR_INVALID_HANDLE: + iResult = 6; + break; + case 25: + iResult = 25; + break; + + default: + iResult = ( int ) ulError ; + break; + } + + return iResult; +} +#endif + +/* return DOS error code of last operation */ +USHORT HB_EXPORT hb_fsError( void ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_fsError()")); + + return s_uiErrorLast; +} + +/* return real error code of last operation */ +USHORT HB_EXPORT hb_fsOsError( void ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_fsError()")); + + return s_uiOsErrorLast; +} + +/* set DOS error code for last operation */ +void HB_EXPORT hb_fsSetError( USHORT uiError ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_fsSetError(%hu)", uiError)); + + /* TODO: untranslate uiError into errno */ + s_uiOsErrorLast = s_uiErrorLast = uiError; +} + +/* set error code for last operation */ +void HB_EXPORT hb_fsSetIOError( BOOL fResult, USHORT uiOperation ) +{ + + /* TODO: implement it */ + HB_SYMBOL_UNUSED( uiOperation ); + + if ( fResult ) + { + s_uiOsErrorLast = s_uiErrorLast = 0; + } + else + { +#if defined(HB_WIN32_IO) || defined(HB_OS_WIN_32) + s_uiOsErrorLast = (USHORT) GetLastError(); + s_uiErrorLast = hb_WinToDosError( s_uiOsErrorLast ); +#elif defined(_MSC_VER) || defined(__DMC__) + #ifdef __XCC__ + extern unsigned long _doserrno; + extern void __cdecl _dosmaperr( unsigned long oserrno ); + _dosmaperr( GetLastError() ); + #endif + if ( _doserrno != 0 ) + { + s_uiOsErrorLast = s_uiErrorLast = _doserrno; + } + else + { + s_uiOsErrorLast = errno; + s_uiErrorLast = hb_errnoToDosError( errno ); + } +#else + s_uiOsErrorLast = errno; + s_uiErrorLast = hb_errnoToDosError( s_uiOsErrorLast ); +#endif + } +} diff --git a/harbour/source/rtl/fstemp.c b/harbour/source/rtl/fstemp.c index 5fcaeec721..327bfb8e5f 100644 --- a/harbour/source/rtl/fstemp.c +++ b/harbour/source/rtl/fstemp.c @@ -51,23 +51,51 @@ * */ +#ifndef HB_OS_WIN_32_USED + #define HB_OS_WIN_32_USED +#endif + #include "hbapi.h" #include "hbapifs.h" -#include "hbset.h" - -#include +#include "hbmath.h" #if defined( HB_OS_UNIX ) #include #include /* We need for mkstemp() on BSD */ #endif - /* NOTE: The buffer must be at least _POSIX_PATH_MAX chars long */ +#if !defined( HB_OS_UNIX ) -#if !defined( HB_OS_UNIX ) || defined( __WATCOMC__ ) static BOOL hb_fsTempName( BYTE * pszBuffer, const BYTE * pszDir, const BYTE * pszPrefix ) { + BOOL fResult; + +#if defined(HB_WIN32_IO) + + char cTempDir[ _POSIX_PATH_MAX + 1 ]; + + /* TODO: Implement this: */ + HB_SYMBOL_UNUSED( pszPrefix ); + + if ( pszDir != NULL && pszDir[0] != '\0' ) + { + strncpy( (char *) cTempDir, (const char *) pszDir, _POSIX_PATH_MAX ); + } + else + { + if ( ! GetTempPath( ( DWORD ) _POSIX_PATH_MAX, cTempDir ) ) + { + hb_fsSetIOError( FALSE, 0 ); + return FALSE; + } + } + cTempDir[ _POSIX_PATH_MAX ] = '\0'; + + fResult = GetTempFileName( cTempDir, "xht", 0, (char *) pszBuffer ); + +#else + /* TODO: Implement these: */ HB_SYMBOL_UNUSED( pszDir ); HB_SYMBOL_UNUSED( pszPrefix ); @@ -77,27 +105,25 @@ static BOOL hb_fsTempName( BYTE * pszBuffer, const BYTE * pszDir, const BYTE * p at least this large. */ pszBuffer[ 0 ] = '\0'; + fResult = ( tmpnam( ( char * ) pszBuffer ) != NULL ); - tmpnam( ( char * ) pszBuffer ); - - return pszBuffer[ 0 ] != '\0'; -} #endif + hb_fsSetIOError( fResult, 0 ); + return fResult; +} + /* NOTE: The buffer must be at least _POSIX_PATH_MAX chars long */ -FHANDLE hb_fsCreateTemp( const BYTE * pszDir, const BYTE * pszPrefix, USHORT uiAttr, BYTE * pszName ) +FHANDLE HB_EXPORT hb_fsCreateTemp( const BYTE * pszDir, const BYTE * pszPrefix, USHORT uiAttr, BYTE * pszName ) { USHORT nAttemptLeft = 999; - errno = 0; - -#if !defined( HB_OS_UNIX ) || defined( __WATCOMC__ ) while( --nAttemptLeft ) { if( hb_fsTempName( pszName, pszDir, pszPrefix ) ) { - FHANDLE fhnd = hb_fsCreateEx( pszName, uiAttr, FO_EXCLUSIVE | FO_EXCL); + FHANDLE fhnd = hb_fsCreateEx( pszName, uiAttr, FO_EXCLUSIVE | FO_EXCL ); /* This function may fail, if the generated filename got used between generation and the file creation. */ @@ -114,49 +140,123 @@ FHANDLE hb_fsCreateTemp( const BYTE * pszDir, const BYTE * pszPrefix, USHORT uiA break; } } -#else - HB_SYMBOL_UNUSED( uiAttr ); - if( ( ( pszDir ? strlen( ( char * ) pszDir ) : 0 ) + ( pszPrefix ? strlen( ( char * ) pszPrefix ) : 0 ) + 6 ) < _POSIX_PATH_MAX ) + return FS_ERROR; +} +#else + +#include /* isupper()/islower() */ +#include "hbset.h" + +static BOOL fsGetTempDirByCase( BYTE *pszName, const char *pszTempDir ) +{ + BOOL bOk= FALSE; + if ( pszTempDir!= NULL && *pszTempDir!= '\0' ) { - FHANDLE fhnd; - char cTemplate[_POSIX_PATH_MAX]; - pszName[0] = '\0'; - cTemplate[0] = '\0'; - if( pszDir ) + bOk= TRUE; + strcpy( ( char * ) pszName, ( char * ) pszTempDir ); + if ( hb_set.HB_SET_DIRCASE == HB_SET_CASE_LOWER || hb_set.HB_SET_DIRCASE == HB_SET_CASE_UPPER ) { - int nLen; - strcpy( cTemplate, ( char * ) pszDir ); - nLen = strlen( cTemplate ); - if( cTemplate[nLen] != hb_set.HB_SET_DIRSEPARATOR ) + // check to see if temp directory already upper or lower. If not use current directory ( "." ) + char *psZ = ( char * ) pszName ; + int iChar ; + BOOL bLower = hb_set.HB_SET_DIRCASE == HB_SET_CASE_LOWER ; + while ( *psZ ) { - cTemplate[nLen] = hb_set.HB_SET_DIRSEPARATOR; - cTemplate[nLen+1] = '\0'; - } - } - if( pszPrefix ) - { - strcat( cTemplate, ( char * ) pszPrefix ); - } - strcat( cTemplate, "XXXXXX" ); /* required by mkstemp */ - while( --nAttemptLeft ) - { - fhnd = mkstemp( cTemplate ); - if( fhnd >= 0 ) - { - strcpy( ( char * ) pszName, cTemplate ); - return fhnd; + iChar = ( int ) *psZ; + if ( isalpha( iChar ) && !( bLower ? islower( iChar ) : isupper( iChar ) ) ) + { + bOk = FALSE; + break; + } + psZ++ ; } } } -#endif + return( bOk ) ; +} + +FHANDLE HB_EXPORT hb_fsCreateTemp( const BYTE * pszDir, const BYTE * pszPrefix, USHORT uiAttr, BYTE * pszName ) +{ + /* less attemps */ + int iAttemptLeft = 99, iLen; + FHANDLE fd; + + HB_SYMBOL_UNUSED( uiAttr ); + + do + { + pszName[0] = '\0'; + + if ( pszDir != NULL && pszDir[0] != '\0' ) + { + strcpy( ( char * ) pszName, ( char * ) pszDir ); + } + else if ( !fsGetTempDirByCase( pszName, getenv( "TMPDIR" ) ) && + !fsGetTempDirByCase( pszName, P_tmpdir ) ) + { + strcpy( ( char * ) pszName, "." ); + } + if ( pszName[0] != '\0' ) + { + int len; + len = strlen( ( char * ) pszName ); + pszName[ len ] = hb_set.HB_SET_DIRSEPARATOR; + pszName[ len + 1 ] = '\0'; + } + + if ( pszPrefix != NULL ) + { + strcat( ( char * ) pszName, ( char * ) pszPrefix ); + } + + iLen = strlen( ( char * ) pszName ); + if ( iLen > _POSIX_PATH_MAX - 6 ) + return FS_ERROR; + +#if !defined(__WATCOMC__) && ( defined( HB_OS_LINUX ) || defined( HB_OS_BSD ) ) + if( hb_set.HB_SET_FILECASE == HB_SET_CASE_LOWER || + hb_set.HB_SET_FILECASE == HB_SET_CASE_UPPER || + hb_set.HB_SET_DIRCASE == HB_SET_CASE_LOWER || + hb_set.HB_SET_DIRCASE == HB_SET_CASE_UPPER ) +#endif + { + int i, n; + double d = hb_random_num(), x; + + for ( i = 0; i < 6; i++ ) + { + d = d * 36; + n = ( int ) d; + d = modf( d, &x ); + pszName[ iLen++ ] = n + ( n > 9 ? 'a' - 10 : '0' ); + } + hb_fileNameConv( ( char * ) pszName ); + fd = hb_fsCreateEx( pszName, uiAttr, FO_EXCLUSIVE | FO_EXCL ); + } +#if !defined(__WATCOMC__) && ( defined( HB_OS_LINUX ) || defined( HB_OS_BSD ) ) + else + { + strcat( ( char * ) pszName, "XXXXXX" ); + fd = (FHANDLE) mkstemp( ( char * ) pszName ); + hb_fsSetIOError( fd != (FHANDLE) -1, 0 ); + } +#endif + if ( fd != (FHANDLE) -1 ) + { + return fd; + } + } + while( --iAttemptLeft ); - hb_fsSetError( ( USHORT ) FS_ERROR ); return FS_ERROR; } +#endif + #ifdef HB_EXTENSION + HB_FUNC( HB_FTEMPCREATE ) { BYTE szName[ _POSIX_PATH_MAX + 1 ]; diff --git a/harbour/source/rtl/strings.c b/harbour/source/rtl/strings.c index e122b0a5c5..1b0076576d 100644 --- a/harbour/source/rtl/strings.c +++ b/harbour/source/rtl/strings.c @@ -54,7 +54,7 @@ #include "hbapi.h" -BOOL hb_strEmpty( const char * szText, ULONG ulLen ) +HB_EXPORT BOOL hb_strEmpty( const char * szText, ULONG ulLen ) { HB_TRACE(HB_TR_DEBUG, ("hb_strEmpty(%s, %lu)", szText, ulLen)); @@ -71,18 +71,26 @@ BOOL hb_strEmpty( const char * szText, ULONG ulLen ) /* warning: It is not case sensitive */ -int hb_strnicmp( const char * s1, const char * s2, size_t count ) +HB_EXPORT int hb_strnicmp( const char * s1, const char * s2, ULONG count ) { + ULONG ulCount; + int rc = 0; + HB_TRACE(HB_TR_DEBUG, ("hb_strnicmp(%s, %s, %lu)", s1, s2, count)); - while( count > 0 && - *s1 != '\0' && - toupper( *s1 ) == toupper( *s2 ) ) + for( ulCount = 0; ulCount < count; ulCount++ ) { - s1++; - s2++; - count--; + unsigned char c1 = toupper( (unsigned char) s1[ ulCount ] ); + unsigned char c2 = toupper( (unsigned char) s2[ ulCount ] ); + + if( c1 != c2 ) + { + rc = ( c1 < c2 ? -1 : 1 ); + break; + } + else if ( !c1 ) + break; } - return ( count == 0 ) ? 0 : toupper( *s1 ) - toupper( *s2 ); + return rc; }