From 6f9daae0560e974ff51b21542c1bfcd3a9e52653 Mon Sep 17 00:00:00 2001 From: Viktor Szakats Date: Fri, 20 Aug 1999 11:00:47 +0000 Subject: [PATCH] *** empty log message *** --- harbour/ChangeLog | 23 +++ harbour/include/filesys.h | 54 ++++--- harbour/source/rdd/dbcmd.c | 2 +- harbour/source/rtl/arrays.c | 2 +- harbour/source/rtl/dates.c | 8 +- harbour/source/rtl/filesys.c | 113 ++++++++++++++ harbour/source/rtl/math.c | 16 +- harbour/source/rtl/strings.c | 30 ++-- harbour/source/rtl/transfrm.c | 114 +++++++------- harbour/tests/working/rtl_test.prg | 234 +++++++++++++++++++++++++++-- 10 files changed, 477 insertions(+), 119 deletions(-) diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 645a2498a7..d28dc18f6a 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -1,3 +1,26 @@ +19990820-12:40 GMT+1 Victor Szel + * source/rtl/filesys.c + include/filesys.h + + hb_fsFNameSplit() + hb_fsFNameMerge() + filename handling functions and structure added to the Harbour RTL. + These function were originated from MakeFilename() and SplitFileName() + * tests/working/rtl_test.prg + + rtl_test now shows the compiler version, os, date and time, other + improvements. + * All TRANSFORM() tests moved to rtl_test to allow automatic regression + testing. + * source/rtl/transfrm.c + * PicFlags type changed to WORD + * Some length and pos variable types changed to ULONG. + * TOFIX: added about an unreachable code segment. + * Some zero changed to '\0'. + * source/rtl/strings.c + source/rtl/maths.c + source/rtl/dates.c + source/rtl/arrays.c + * QUESTION:s changed to NOTE: regarding the parameter checking + 19990820-12:28 GMT+1 Antonio Linares * source/debug/debugger.prg * improved debugger functionality. F8 and F4 already operative. diff --git a/harbour/include/filesys.h b/harbour/include/filesys.h index 56656e9273..186445a0b2 100644 --- a/harbour/include/filesys.h +++ b/harbour/include/filesys.h @@ -52,26 +52,38 @@ typedef int FHANDLE; -extern BOOL hb_fsChDir ( BYTE * fpDirName ); -extern USHORT hb_fsChDrv ( BYTE * nDrive ); -extern void hb_fsClose ( FHANDLE hFileHandle ); -extern void hb_fsCommit ( FHANDLE hFileHandle ); -extern FHANDLE hb_fsCreate ( BYTE * fpFilename, USHORT uiAttribute ); -extern BYTE * hb_fsCurDir ( USHORT uiDrive ); -extern BYTE hb_fsCurDrv ( void ); -extern void hb_fsDelete ( BYTE * fpFilename ); -extern USHORT hb_fsError ( void ); -extern FHANDLE hb_fsExtOpen ( BYTE * fpFilename, BYTE * fpDefExt, - USHORT uiFlags, BYTE * fpPaths, PHB_ITEM pError ); -extern USHORT hb_fsIsDrv ( BYTE nDrive ); -extern BOOL hb_fsLock ( FHANDLE hFileHandle, ULONG ulStart, - ULONG ulLength, USHORT uiMode ); -extern BOOL hb_fsMkDir ( BYTE * fpDirName ); -extern FHANDLE hb_fsOpen ( BYTE * fpFilename, USHORT uiFlags ); -extern USHORT hb_fsRead ( FHANDLE hFileHandle, BYTE * fpBuff, USHORT uiCount ); -extern BOOL hb_fsRmDir ( BYTE * fpDirName ); -extern void hb_fsRename ( BYTE * fpOldName, BYTE * fpNewName ); -extern ULONG hb_fsSeek ( FHANDLE hFileHandle, LONG lOffset, USHORT uiMode ); -extern USHORT hb_fsWrite ( FHANDLE hFileHandle, BYTE * fpBuff, USHORT uiCount ); +/* Filename support */ +typedef struct +{ + char szBuffer[ _POSIX_PATH_MAX + 3 ]; + char * szPath; + char * szName; + char * szExtension; +} HB_FNAME, * PHB_FNAME, * HB_FNAME_PTR; + +extern BOOL hb_fsChDir ( BYTE * fpDirName ); +extern USHORT hb_fsChDrv ( BYTE * nDrive ); +extern void hb_fsClose ( FHANDLE hFileHandle ); +extern void hb_fsCommit ( FHANDLE hFileHandle ); +extern FHANDLE hb_fsCreate ( BYTE * fpFilename, USHORT uiAttribute ); +extern BYTE * hb_fsCurDir ( USHORT uiDrive ); +extern BYTE hb_fsCurDrv ( void ); +extern void hb_fsDelete ( BYTE * fpFilename ); +extern USHORT hb_fsError ( void ); +extern FHANDLE hb_fsExtOpen ( BYTE * fpFilename, BYTE * fpDefExt, + USHORT uiFlags, BYTE * fpPaths, PHB_ITEM pError ); +extern USHORT hb_fsIsDrv ( BYTE nDrive ); +extern BOOL hb_fsLock ( FHANDLE hFileHandle, ULONG ulStart, + ULONG ulLength, USHORT uiMode ); +extern BOOL hb_fsMkDir ( BYTE * fpDirName ); +extern FHANDLE hb_fsOpen ( BYTE * fpFilename, USHORT uiFlags ); +extern USHORT hb_fsRead ( FHANDLE hFileHandle, BYTE * fpBuff, USHORT uiCount ); +extern BOOL hb_fsRmDir ( BYTE * fpDirName ); +extern void hb_fsRename ( BYTE * fpOldName, BYTE * fpNewName ); +extern ULONG hb_fsSeek ( FHANDLE hFileHandle, LONG lOffset, USHORT uiMode ); +extern USHORT hb_fsWrite ( FHANDLE hFileHandle, BYTE * fpBuff, USHORT uiCount ); + +extern PHB_FNAME hb_fsFNameSplit ( char * szFilename ); /* Split given filename into path, name and extension */ +extern char * hb_fsFNameMerge ( char * szFileName, PHB_FNAME pFileName ); /* This function joins path, name and extension into a string with a filename */ #endif /* HB_FILESYS_H_ */ diff --git a/harbour/source/rdd/dbcmd.c b/harbour/source/rdd/dbcmd.c index 56fa10d990..6c358db633 100644 --- a/harbour/source/rdd/dbcmd.c +++ b/harbour/source/rdd/dbcmd.c @@ -1094,7 +1094,7 @@ HARBOUR HB_DELETED( void ) BOOL bDeleted = FALSE; if( pCurrArea && ( ( AREAP ) pCurrArea->pArea )->lprfsHost ) - SELF_DELETE( ( AREAP ) pCurrArea->pArea, &bDeleted ); + SELF_DELETED( ( AREAP ) pCurrArea->pArea, &bDeleted ); hb_retl( bDeleted ); } diff --git a/harbour/source/rtl/arrays.c b/harbour/source/rtl/arrays.c index 23ba3db3ea..bd8fff8d12 100644 --- a/harbour/source/rtl/arrays.c +++ b/harbour/source/rtl/arrays.c @@ -698,7 +698,7 @@ HARBOUR HB_AADD( void ) hb_errRT_BASE( EG_ARG, 1123, NULL, "AADD" ); } else - /* QUESTION: Clipper catches this at compile time! */ + /* NOTE: Clipper catches this at compile time! */ hb_errRT_BASE( EG_ARGCOUNT, 3000, NULL, "AADD" ); } diff --git a/harbour/source/rtl/dates.c b/harbour/source/rtl/dates.c index a4be242070..095faebc90 100644 --- a/harbour/source/rtl/dates.c +++ b/harbour/source/rtl/dates.c @@ -470,7 +470,7 @@ HARBOUR HB_DTOS( void ) } else { - /* QUESTION: Clipper catches this at compile time! */ + /* NOTE: Clipper catches this at compile time! */ hb_errRT_BASE(EG_ARGCOUNT, 3000, NULL, "DTOS"); } #endif @@ -599,7 +599,7 @@ HARBOUR HB_DATE( void ) } else { - /* QUESTION: Clipper catches this at compile time! */ + /* NOTE: Clipper catches this at compile time! */ hb_errRT_BASE(EG_ARGCOUNT, 3000, NULL, "DATE"); } } @@ -672,7 +672,7 @@ HARBOUR HB_CMONTH( void ) } else { - /* QUESTION: Clipper catches this at compile time! */ + /* NOTE: Clipper catches this at compile time! */ hb_errRT_BASE(EG_ARGCOUNT, 3000, NULL, "CMONTH"); } } @@ -696,7 +696,7 @@ HARBOUR HB_CDOW( void ) } else { - /* QUESTION: Clipper catches this at compile time! */ + /* NOTE: Clipper catches this at compile time! */ hb_errRT_BASE(EG_ARGCOUNT, 3000, NULL, "CDOW"); } } diff --git a/harbour/source/rtl/filesys.c b/harbour/source/rtl/filesys.c index f024d41b10..9c75cd1932 100644 --- a/harbour/source/rtl/filesys.c +++ b/harbour/source/rtl/filesys.c @@ -895,3 +895,116 @@ HARBOUR HB_W2BIN( void ) HB_I2BIN(); } +#define IS_PATH_SEP( c ) (c == OS_PATH_DELIMITER) + +/* Split given filename into path, name and extension */ +PHB_FNAME hb_fsFNameSplit( char *szFilename ) +{ + PHB_FNAME pName = (PHB_FNAME) hb_xgrab( sizeof(HB_FNAME) ); + int iLen = strlen(szFilename); + int iSlashPos; + int iDotPos; + int iPos; + + pName->szPath = pName->szName = pName->szExtension = NULL; + + iSlashPos = iLen-1; + iPos = 0; + + while( iSlashPos >= 0 && !IS_PATH_SEP(szFilename[ iSlashPos ]) ) + --iSlashPos; + + if( iSlashPos == 0 ) + { + /* root path -> \filename */ + pName->szBuffer[ 0 ] = OS_PATH_DELIMITER; + pName->szBuffer[ 1 ] = '\x0'; + pName->szPath = pName->szBuffer; + iPos = 2; /* first free position after the slash */ + } + else if( iSlashPos > 0 ) + { + /* path with separator -> path\filename */ + memcpy( pName->szBuffer, szFilename, iSlashPos ); + pName->szBuffer[ iSlashPos ] = '\x0'; + pName->szPath = pName->szBuffer; + iPos = iSlashPos + 1; /* first free position after the slash */ + } + + iDotPos = iLen-1; + while( iDotPos > iSlashPos && szFilename[ iDotPos ] != '.' ) + --iDotPos; + if( (iDotPos-iSlashPos) > 1 ) + { + /* the dot was found + * and there is at least one character between a slash and a dot + */ + if( iDotPos == iLen-1 ) + { + /* the dot is the last character -use it as extension name */ + pName->szExtension = pName->szBuffer+iPos; + pName->szBuffer[ iPos++ ] = '.'; + pName->szBuffer[ iPos++ ] = '\x0'; + } + else + { + pName->szExtension = pName->szBuffer+iPos; + /* copy rest of the string with terminating ZERO character */ + memcpy( pName->szExtension, szFilename+iDotPos+1, iLen-iDotPos ); + iPos += iLen-iDotPos; + } + } + else + /* there is no dot in the filename or it is '.filename' */ + iDotPos = iLen; + + pName->szName = pName->szBuffer + iPos; + memcpy( pName->szName, szFilename + iSlashPos + 1, iDotPos - iSlashPos - 1 ); + pName->szName[ iDotPos - iSlashPos - 1 ] = '\x0'; + + return pName; +} + +/* This function joins path, name and extension into a string with a filename */ +char * hb_fsFNameMerge( char *szFileName, PHB_FNAME pFileName ) +{ + if( pFileName->szPath && pFileName->szPath[ 0 ] ) + { + /* we have not empty path specified */ + int iLen = strlen(pFileName->szPath); + + strcpy( szFileName, pFileName->szPath ); + + /* if the path is a root directory then we don't need to add path separator */ + if( !(IS_PATH_SEP(pFileName->szPath[ 0 ]) && pFileName->szPath[ 0 ] == '\x0') ) + { + /* add the path separator only in cases: + * when a name doesn't start with it + * when the path doesn't end with it + */ + if( !( IS_PATH_SEP(pFileName->szName[ 0 ]) || IS_PATH_SEP(pFileName->szPath[ iLen-1 ]) ) ) + { + szFileName[ iLen++ ] = OS_PATH_DELIMITER; + szFileName[ iLen ] = '\x0'; + } + } + strcpy( szFileName+iLen, pFileName->szName ); + } + else + strcpy( szFileName, pFileName->szName ); + + if( pFileName->szExtension ) + { + int iLen = strlen(szFileName); + + if( !(pFileName->szExtension[ 0 ] == '.' || szFileName[ iLen-1 ] == '.') ) + { + /* add extension separator only when extansion doesn't contain it */ + szFileName[ iLen++ ] = '.'; + szFileName[ iLen ] = '\x0'; + } + strcpy( szFileName+iLen, pFileName->szExtension ); + } + + return szFileName; +} diff --git a/harbour/source/rtl/math.c b/harbour/source/rtl/math.c index f1ce77d75d..2fa738056b 100644 --- a/harbour/source/rtl/math.c +++ b/harbour/source/rtl/math.c @@ -79,7 +79,7 @@ HARBOUR HB_ABS( void ) } else { - /* QUESTION: Clipper catches this at compile time! */ + /* NOTE: Clipper catches this at compile time! */ hb_errRT_BASE(EG_ARGCOUNT, 3000, NULL, "ABS"); } } @@ -103,7 +103,7 @@ HARBOUR HB_EXP( void ) } else { - /* QUESTION: Clipper catches this at compile time! */ + /* NOTE: Clipper catches this at compile time! */ hb_errRT_BASE(EG_ARGCOUNT, 3000, NULL, "EXP"); } } @@ -121,7 +121,7 @@ HARBOUR HB_INT( void ) } else { - /* QUESTION: Clipper catches this at compile time! */ + /* NOTE: Clipper catches this at compile time! */ hb_errRT_BASE(EG_ARGCOUNT, 3000, NULL, "INT"); } } @@ -149,7 +149,7 @@ HARBOUR HB_LOG( void ) } else { - /* QUESTION: Clipper catches this at compile time! */ + /* NOTE: Clipper catches this at compile time! */ hb_errRT_BASE(EG_ARGCOUNT, 3000, NULL, "LOG"); } } @@ -182,7 +182,7 @@ HARBOUR HB_MAX( void ) } else { - /* QUESTION: Clipper catches this at compile time! */ + /* NOTE: Clipper catches this at compile time! */ hb_errRT_BASE(EG_ARGCOUNT, 3000, NULL, "MAX"); } } @@ -215,7 +215,7 @@ HARBOUR HB_MIN( void ) } else { - /* QUESTION: Clipper catches this at compile time! */ + /* NOTE: Clipper catches this at compile time! */ hb_errRT_BASE(EG_ARGCOUNT, 3000, NULL, "MIN"); } } @@ -303,7 +303,7 @@ HARBOUR HB_ROUND( void ) } else { - /* QUESTION: Clipper catches this at compile time! */ + /* NOTE: Clipper catches this at compile time! */ hb_errRT_BASE(EG_ARGCOUNT, 3000, NULL, "ROUND"); } } @@ -335,7 +335,7 @@ HARBOUR HB_SQRT( void ) } else { - /* QUESTION: Clipper catches this at compile time! */ + /* NOTE: Clipper catches this at compile time! */ hb_errRT_BASE(EG_ARGCOUNT, 3000, NULL, "SQRT"); } } diff --git a/harbour/source/rtl/strings.c b/harbour/source/rtl/strings.c index bd7fb6dd26..eea4d6aa11 100644 --- a/harbour/source/rtl/strings.c +++ b/harbour/source/rtl/strings.c @@ -288,7 +288,7 @@ HARBOUR HB_LTRIM( void ) } else { - /* QUESTION: Clipper catches this at compile time! */ + /* NOTE: Clipper catches this at compile time! */ hb_errRT_BASE(EG_ARGCOUNT, 3000, NULL, "LTRIM"); } } @@ -334,7 +334,7 @@ HARBOUR HB_RTRIM( void ) } else { - /* QUESTION: Clipper catches this at compile time! */ + /* NOTE: Clipper catches this at compile time! */ hb_errRT_BASE(EG_ARGCOUNT, 3000, NULL, "RTRIM"); } } @@ -357,7 +357,7 @@ HARBOUR HB_TRIM( void ) } else { - /* QUESTION: Clipper catches this at compile time! */ + /* NOTE: Clipper catches this at compile time! */ hb_errRT_BASE(EG_ARGCOUNT, 3000, NULL, "TRIM"); } } @@ -604,7 +604,7 @@ HARBOUR HB_AT( void ) } else { - /* QUESTION: Clipper catches this at compile time! */ + /* NOTE: Clipper catches this at compile time! */ hb_errRT_BASE(EG_ARGCOUNT, 3000, NULL, "AT"); } } @@ -663,7 +663,7 @@ HARBOUR HB_CHR( void ) } else { - /* QUESTION: Clipper catches this at compile time! */ + /* NOTE: Clipper catches this at compile time! */ hb_errRT_BASE(EG_ARGCOUNT, 3000, NULL, "CHR"); } } @@ -689,7 +689,7 @@ HARBOUR HB_ASC(void) } else { - /* QUESTION: Clipper catches this at compile time! */ + /* NOTE: Clipper catches this at compile time! */ hb_errRT_BASE(EG_ARGCOUNT, 3000, NULL, "ASC"); } } @@ -729,7 +729,7 @@ HARBOUR HB_LEFT( void ) } else { - /* QUESTION: Clipper catches this at compile time! */ + /* NOTE: Clipper catches this at compile time! */ hb_errRT_BASE(EG_ARGCOUNT, 3000, NULL, "LEFT"); } } @@ -771,7 +771,7 @@ HARBOUR HB_RIGHT( void ) } else { - /* QUESTION: Clipper catches this at compile time! */ + /* NOTE: Clipper catches this at compile time! */ /* Clipper doesn't error */ hb_retc(""); } @@ -830,7 +830,7 @@ HARBOUR HB_SUBSTR( void ) } else { - /* QUESTION: Clipper catches this at compile time! */ + /* NOTE: Clipper catches this at compile time! */ hb_errRT_BASE(EG_ARGCOUNT, 3000, NULL, "SUBSTR"); } } @@ -864,7 +864,7 @@ HARBOUR HB_LOWER( void ) } else { - /* QUESTION: Clipper catches this at compile time! */ + /* NOTE: Clipper catches this at compile time! */ hb_errRT_BASE(EG_ARGCOUNT, 3000, NULL, "LOWER"); } } @@ -906,7 +906,7 @@ HARBOUR HB_UPPER( void ) } else { - /* QUESTION: Clipper catches this at compile time! */ + /* NOTE: Clipper catches this at compile time! */ hb_errRT_BASE(EG_ARGCOUNT, 3000, NULL, "UPPER"); } } @@ -954,7 +954,7 @@ HARBOUR HB_REPLICATE( void ) } else { - /* QUESTION: Clipper catches this at compile time! */ + /* NOTE: Clipper catches this at compile time! */ hb_errRT_BASE(EG_ARGCOUNT, 3000, NULL, "REPLICATE"); } } @@ -994,7 +994,7 @@ HARBOUR HB_SPACE( void ) } else { - /* QUESTION: Clipper catches this at compile time! */ + /* NOTE: Clipper catches this at compile time! */ hb_errRT_BASE(EG_ARGCOUNT, 3000, NULL, "SPACE"); } } @@ -1208,7 +1208,7 @@ HARBOUR HB_VAL( void ) } else { - /* QUESTION: Clipper catches this at compile time! */ + /* NOTE: Clipper catches this at compile time! */ hb_errRT_BASE(EG_ARGCOUNT, 3000, NULL, "VAL"); } } @@ -1383,7 +1383,7 @@ HARBOUR HB_STR( void ) } else { - /* QUESTION: Clipper catches this at compile time! */ + /* NOTE: Clipper catches this at compile time! */ hb_errRT_BASE(EG_ARGCOUNT, 3000, NULL, "STR"); } } diff --git a/harbour/source/rtl/transfrm.c b/harbour/source/rtl/transfrm.c index 0db951b88e..89e445e8ca 100644 --- a/harbour/source/rtl/transfrm.c +++ b/harbour/source/rtl/transfrm.c @@ -93,18 +93,18 @@ static char *szBritish[] = { "DD/MM/YY", "DD/MM/YYYY" }; /* For @E PictFunc -> Analyze function flags and return binary flags bits szPict : Pointer to the picture - lPicLen : Pointer to the length. Changed during execution. + ulPicLen : Pointer to the length. Changed during execution. */ -static int PictFunc( char **szPict, long *lPicLen ) +static WORD PictFunc( char **szPict, ULONG *pulPicLen ) { BOOL bDone = FALSE; - int iPicFlags = 0; + WORD wPicFlags = 0; char *szPic = *szPict; szPic++; - (*lPicLen)--; - while( *lPicLen && !bDone ) + (*pulPicLen)--; + while( *pulPicLen && !bDone ) { switch( toupper(*szPic) ) { @@ -112,40 +112,40 @@ static int PictFunc( char **szPict, long *lPicLen ) bDone = TRUE; break; case '!': - iPicFlags |= PF_UPPER; + wPicFlags |= PF_UPPER; break; case '(': - iPicFlags |= PF_PARNEG; + wPicFlags |= PF_PARNEG; break; case '0': - iPicFlags |= PF_ZERO; + wPicFlags |= PF_ZERO; break; case 'B': - iPicFlags |= PF_LEFT; + wPicFlags |= PF_LEFT; break; case 'C': - iPicFlags |= PF_CREDIT; + wPicFlags |= PF_CREDIT; break; case 'D': - iPicFlags |= PF_DATE; + wPicFlags |= PF_DATE; break; case 'E': - iPicFlags |= PF_BRITISH; + wPicFlags |= PF_BRITISH; break; case 'R': - iPicFlags |= PF_REMAIN; + wPicFlags |= PF_REMAIN; break; case 'X': - iPicFlags |= PF_DEBIT; + wPicFlags |= PF_DEBIT; break; case 'Z': - iPicFlags |= PF_EMPTY; + wPicFlags |= PF_EMPTY; break; } szPic++; - (*lPicLen)--; + (*pulPicLen)--; } - return( iPicFlags ); + return( wPicFlags ); } /* @@ -153,18 +153,18 @@ static int PictFunc( char **szPict, long *lPicLen ) szPic : Picture lPic : Length of picture - iPicFlags : Function flags. NUM_DATE tells whether its a number or date + wPicFlags : Function flags. NUM_DATE tells whether its a number or date dValue : Number to picture lRetSize : The size of the returned string is passed here ! iOrigWidth : Original width iOrigDec : Original decimals */ -static char *NumPicture( char *szPic, long lPic, int iPicFlags, double dValue, - long *lRetSize, int iOrigWidth, int iOrigDec ) +static char *NumPicture( char *szPic, ULONG ulPic, WORD wPicFlags, double dValue, + ULONG *pulRetSize, int iOrigWidth, int iOrigDec ) { int iWidth; /* Width of string */ int iDecimals; /* Number of decimals */ - int i; + ULONG i; int iCount = 0; char *szRet; @@ -178,12 +178,12 @@ static char *NumPicture( char *szPic, long lPic, int iPicFlags, double dValue, double dPush; - szRet = (char *) hb_xgrab( lPic+4 ); /* Grab enough */ - *szRet = 0; - for( i=0; i < lPic && !bFound; i++ ) /* Count number in front */ + szRet = (char *) hb_xgrab( ulPic+4 ); /* Grab enough */ + *szRet = '\0'; + for( i=0; i < ulPic && !bFound; i++ ) /* Count number in front */ { if( szPic[i] == '.' ) - bFound = !( iPicFlags & PF_NUMDATE ); /* Exit when numeric */ + bFound = !( wPicFlags & PF_NUMDATE ); /* Exit when numeric */ else if( szPic[i] == '9' || szPic[i] == '#' || szPic[i] == '$' || szPic[i] == '*' ) iCount++; @@ -194,7 +194,7 @@ static char *NumPicture( char *szPic, long lPic, int iPicFlags, double dValue, { iDecimals = 0; iWidth++; /* Also adjust iWidth */ - for( ; ipSymbol ); /* Push STR function */ hb_vmPushNil (); /* Function call. No object */ - hb_vmPushDouble ( dPush, iDecimals ); /* Push value to transform */ if( !iWidth ) /* Width calculated ?? */ { @@ -232,7 +231,7 @@ static char *NumPicture( char *szPic, long lPic, int iPicFlags, double dValue, szStr = pItem->item.asString.value; iCount = 0; - if( iPicFlags & PF_ZERO ) /* Pad with Zero's */ + if( wPicFlags & PF_ZERO ) /* Pad with Zero's */ { for( i=0; szStr[i] == ' ' && i < iWidth; i++ ) szStr[i] = '0'; @@ -243,7 +242,7 @@ static char *NumPicture( char *szPic, long lPic, int iPicFlags, double dValue, szStr[pItem->item.asString.length - 1] = ' '; } - if( iPicFlags & PF_LEFT ) /* Left align */ + if( wPicFlags & PF_LEFT ) /* Left align */ { for( i=0; szStr[i] == ' ' && i <= iWidth; i++ ); /* Find first non-space */ @@ -256,6 +255,8 @@ static char *NumPicture( char *szPic, long lPic, int iPicFlags, double dValue, } } + /* TOFIX: iCount seem to always be zero at this point */ + if( !iCount ) /* No real picture */ { hb_xfree( szRet ); @@ -266,18 +267,18 @@ static char *NumPicture( char *szPic, long lPic, int iPicFlags, double dValue, } else { - for( i=0; i < lPic; i++ ) + for( i=0; i < ulPic; i++ ) { cPic = szPic[i]; if( cPic == '9' || cPic == '#' ) szRet[ i ] = szStr[ iCount++ ]; /* Just copy */ else if( cPic == '.' ) { - if( iPicFlags & PF_NUMDATE ) /* Dot in date */ + if( wPicFlags & PF_NUMDATE ) /* Dot in date */ szRet[ i ] = cPic; else /* Dot in number */ { - if( iPicFlags & PF_EXCHANG ) /* Exchange . and , */ + if( wPicFlags & PF_EXCHANG ) /* Exchange . and , */ { szRet[ i ] = ','; iCount++; @@ -300,7 +301,7 @@ static char *NumPicture( char *szPic, long lPic, int iPicFlags, double dValue, { if( iCount && isdigit( szStr[ iCount - 1 ] ) ) { /* May we place it */ - if( iPicFlags & PF_EXCHANG ) + if( wPicFlags & PF_EXCHANG ) szRet[i] = '.'; else szRet[i] = ','; @@ -312,21 +313,21 @@ static char *NumPicture( char *szPic, long lPic, int iPicFlags, double dValue, szRet[i] = cPic; } } - if( ( iPicFlags & PF_CREDIT ) && ( dValue >= 0 ) ) + if( ( wPicFlags & PF_CREDIT ) && ( dValue >= 0 ) ) { szRet[i++] = ' '; szRet[i++] = 'C'; szRet[i++] = 'R'; } - if( ( iPicFlags & PF_DEBIT ) && ( dValue < 0 ) ) + if( ( wPicFlags & PF_DEBIT ) && ( dValue < 0 ) ) { szRet[i++] = ' '; szRet[i++] = 'D'; szRet[i++] = 'B'; } - if( ( iPicFlags & PF_PARNEG ) && ( dValue < 0 ) ) + if( ( wPicFlags & PF_PARNEG ) && ( dValue < 0 ) ) { if( isdigit(*szRet) ) /* Overflow */ { @@ -340,8 +341,8 @@ static char *NumPicture( char *szPic, long lPic, int iPicFlags, double dValue, szRet[i++] = ')'; } - *lRetSize = i; - szRet[i] = 0; + *pulRetSize = i; + szRet[i] = '\0'; } else { @@ -354,13 +355,12 @@ static char *NumPicture( char *szPic, long lPic, int iPicFlags, double dValue, DatePicture -> Handle dates. szDate : Date to handle - iPicFlags : Function flags + wPicFlags : Function flags szResult : Buffer of at least size 11 to hold formatted date - lRetSize : The size of the returned string is passed here ! */ -static char *DatePicture( char * szDate, int iPicFlags, char * szResult ) +static char *DatePicture( char * szDate, WORD wPicFlags, char * szResult ) { - if( iPicFlags & PF_BRITISH ) + if( wPicFlags & PF_BRITISH ) hb_dtoc( szDate, szResult, szBritish[ ( hb_set_century ? 1 : 0 ) ] ); else hb_dtoc( szDate, szResult, hb_set.HB_SET_DATEFORMAT ); @@ -371,9 +371,7 @@ static char *DatePicture( char * szDate, int iPicFlags, char * szResult ) HARBOUR HB_TRANSFORM( void ) { - PHB_ITEM pExp = hb_param( 1, IT_ANY ); /* Input parameter */ - - BOOL bDone = FALSE; + PHB_ITEM pExp = hb_param( 1, IT_ANY ); /* Input parameter */ if( ISCHAR( 2 ) && hb_parclen( 2 ) > 0 ) { @@ -389,12 +387,12 @@ HARBOUR HB_TRANSFORM( void ) long lExpPos = 0; long lResultPos = 0; - int iPicFlags = 0; /* Function flags */ + WORD wPicFlags = 0; /* Function flags */ int n; if( *szPic == '@' ) /* Function marker found */ { - iPicFlags = PictFunc( &szPic, &lPic ); /* Get length of function */ + wPicFlags = PictFunc( &szPic, &lPic ); /* Get length of function */ lPicStart = pPic->item.asString.length - lPic; /* Get start of template */ } @@ -410,7 +408,7 @@ HARBOUR HB_TRANSFORM( void ) /* Grab enough */ szPic += lPicStart; /* Skip functions */ - if( iPicFlags & PF_UPPER ) /* Function : @! */ + if( wPicFlags & PF_UPPER ) /* Function : @! */ { szTemp = szExp; /* Convert to upper */ for( n = pExp->item.asString.length; n ; n--) @@ -460,13 +458,13 @@ HARBOUR HB_TRANSFORM( void ) lPic--; } } - else if( iPicFlags & (PF_UPPER + PF_REMAIN) ) + else if( wPicFlags & (PF_UPPER + PF_REMAIN) ) { /* Without template */ for( n = pExp->item.asString.length; n; n--) szResult[lResultPos++] = *szExp++; } - if( ( iPicFlags & PF_REMAIN ) && lPic ) + if( ( wPicFlags & PF_REMAIN ) && lPic ) { /* Any chars left */ for( n = lPic; n; n--) szResult[lResultPos++] = *szPic; @@ -479,6 +477,8 @@ HARBOUR HB_TRANSFORM( void ) case IT_LOGICAL: { + BOOL bDone = FALSE; + szResult = (char *) hb_xgrab( lPic + 1 ); /* That's all folks */ szPic += lPicStart; /* Skip functions */ @@ -514,7 +514,7 @@ HARBOUR HB_TRANSFORM( void ) } } } - if( ( iPicFlags & PF_REMAIN ) && lPic ) + if( ( wPicFlags & PF_REMAIN ) && lPic ) { /* Any chars left */ for( n = lPic; n; n--) /* Copy remainder */ szResult[lResultPos++] = *szPic++; @@ -527,7 +527,7 @@ HARBOUR HB_TRANSFORM( void ) } case IT_INTEGER: { - szResult = NumPicture( szPic + lPicStart, lPic, iPicFlags, + szResult = NumPicture( szPic + lPicStart, lPic, wPicFlags, (double) pExp->item.asInteger.value, &lResultPos, pExp->item.asInteger.length, 0 ); hb_retclen( szResult, lResultPos ); @@ -536,7 +536,7 @@ HARBOUR HB_TRANSFORM( void ) } case IT_LONG: { - szResult = NumPicture( szPic + lPicStart, lPic, iPicFlags, + szResult = NumPicture( szPic + lPicStart, lPic, wPicFlags, (double) pExp->item.asLong.value, &lResultPos, pExp->item.asLong.length, 0 ); hb_retclen( szResult, lResultPos ); @@ -545,7 +545,7 @@ HARBOUR HB_TRANSFORM( void ) } case IT_DOUBLE: { - szResult = NumPicture( szPic + lPicStart, lPic, iPicFlags, + szResult = NumPicture( szPic + lPicStart, lPic, wPicFlags, (double) pExp->item.asDouble.value, &lResultPos, pExp->item.asDouble.length, pExp->item.asDouble.decimal ); hb_retclen( szResult, lResultPos); @@ -555,7 +555,7 @@ HARBOUR HB_TRANSFORM( void ) case IT_DATE: { char szResult[ 11 ]; - DatePicture( hb_pards( 1 ), iPicFlags, szResult ); + DatePicture( hb_pards( 1 ), wPicFlags, szResult ); hb_retc( szResult ); break; } diff --git a/harbour/tests/working/rtl_test.prg b/harbour/tests/working/rtl_test.prg index 7180914352..7d65a97a8e 100644 --- a/harbour/tests/working/rtl_test.prg +++ b/harbour/tests/working/rtl_test.prg @@ -34,17 +34,28 @@ their web site at http://www.gnu.org/). */ +/* TRANSFORM() tests written by Eddie Runia */ + +/* NOTE: Always compile with /n /w switches */ /* TODO: Add checks for string parameters with embedded NUL character */ /* TODO: Add test cases for other string functions */ /* TODO: Incorporate tests from test/working/string*.prg */ #translate TEST_LINE(, ) => TEST_CALL(<(x)>, {|| }, ) -STATIC snPass := 0 -STATIC snFail := 0 +STATIC snPass +STATIC snFail +STATIC scFileName +STATIC snFhnd +STATIC scNewLine +STATIC snCount FUNCTION Main() + /* Initialize test */ + + TEST_BEGIN() + /* AT() */ TEST_LINE( At("", "") , 1 ) @@ -225,35 +236,213 @@ FUNCTION Main() #endif + /* TRANSFORM() */ + + TEST_LINE( Transform( "Hallo ", "!!!!!" ) , "HALLO" ) + TEST_LINE( Transform( "Hallo ", "!!A!!" ) , "HAlLO" ) + TEST_LINE( Transform( "Hallo ", "!!A9!" ) , "HAllO" ) + TEST_LINE( Transform( "Hallo ", "!QA9!" ) , "HQllO" ) + TEST_LINE( Transform( "Hallo ", "ZQA9!" ) , "ZQllO" ) + TEST_LINE( Transform( "Hall" , "ZQA9!" ) , "ZQll" ) + TEST_LINE( Transform( "Hallo ", "!AAA" ) , "Hall" ) + TEST_LINE( Transform( "Hallo ", "@!" ) , "HALLO " ) + TEST_LINE( Transform( "Hallo ", "@! AA" ) , "HA" ) + TEST_LINE( Transform( "Hallo ", "@R" ) , "Hallo " ) + TEST_LINE( Transform( "Hallo ", "@Z" ) , " " ) + TEST_LINE( Transform( "Hallo ", "@R !!" ) , "HA" ) + TEST_LINE( Transform( "Hi" , "@R !!!" ) , "HI " ) + TEST_LINE( Transform( "Hallo ", "" ) , "Hallo " ) + + TEST_LINE( Transform( .T. , "" ) , "T" ) + TEST_LINE( Transform( .F. , "" ) , "F" ) + TEST_LINE( Transform( .T. , "L" ) , "T" ) + TEST_LINE( Transform( .F. , "L" ) , "F" ) + TEST_LINE( Transform( .T. , "Y" ) , "Y" ) + TEST_LINE( Transform( .F. , "Y" ) , "N" ) + TEST_LINE( Transform( .T. , "X" ) , "X" ) + TEST_LINE( Transform( .F. , "#" ) , "F" ) + TEST_LINE( Transform( .T. , "X!" ) , "X" ) + TEST_LINE( Transform( .F. , "@R Y" ) , "N" ) + TEST_LINE( Transform( .T. , "@R X!" ) , "X!T" ) + + SET DATE ANSI + SET CENTURY ON + + TEST_LINE( Transform( SToD("19901214") , "99/99/9999" ) , "1990.12.14" ) + TEST_LINE( Transform( SToD("19901202") , "99.99.9999" ) , "1990.12.02" ) + TEST_LINE( Transform( SToD("") , "99/99/9999" ) , " . . " ) + TEST_LINE( Transform( SToD("19901202") , "99/99/99" ) , "1990.12.02" ) + TEST_LINE( Transform( SToD("19901214") , "99-99-99" ) , "1990.12.14" ) + TEST_LINE( Transform( SToD("20040430") , "99.99.99" ) , "2004.04.30" ) + TEST_LINE( Transform( SToD("") , "99/99/99" ) , " . . " ) + TEST_LINE( Transform( SToD("19920101") , "THISWRNG" ) , "1992.01.01" ) + TEST_LINE( Transform( SToD("19350605") , "999/99/9" ) , "1935.06.05" ) + TEST_LINE( Transform( SToD("19101112") , "9#-9#/##" ) , "1910.11.12" ) + TEST_LINE( Transform( SToD("19920101") , "" ) , "1992.01.01" ) + TEST_LINE( Transform( SToD("19920101") , "DO THIS " ) , "1992.01.01" ) + TEST_LINE( Transform( SToD("19920102") , "@E" ) , "2.91901.02" ) /* BUG in Clipper */ + TEST_LINE( Transform( 1234 , "@D 9999" ) , "1234.00.0 " ) + TEST_LINE( Transform( 1234 , "@BD 9999" ) , "1234.00.0 " ) + + SET CENTURY OFF + + TEST_LINE( Transform( SToD("19901214") , "99/99/9999" ) , "90.12.14" ) + TEST_LINE( Transform( SToD("19901202") , "99.99.9999" ) , "90.12.02" ) + TEST_LINE( Transform( SToD("") , "99/99/9999" ) , " . . " ) + TEST_LINE( Transform( SToD("19901202") , "99/99/99" ) , "90.12.02" ) + TEST_LINE( Transform( SToD("19901214") , "99-99-99" ) , "90.12.14" ) + TEST_LINE( Transform( SToD("20040430") , "99.99.99" ) , "04.04.30" ) + TEST_LINE( Transform( SToD("") , "99/99/99" ) , " . . " ) + TEST_LINE( Transform( SToD("19920101") , "THISWRNG" ) , "92.01.01" ) + TEST_LINE( Transform( SToD("19350605") , "999/99/9" ) , "35.06.05" ) + TEST_LINE( Transform( SToD("19101112") , "9#-9#/##" ) , "10.11.12" ) + TEST_LINE( Transform( SToD("19920101") , "" ) , "92.01.01" ) + TEST_LINE( Transform( SToD("19920101") , "DO THIS " ) , "92.01.01" ) + TEST_LINE( Transform( SToD("19920102") , "@E" ) , "01.92.02" ) /* BUG in Clipper */ + TEST_LINE( Transform( 1234 , "@D 9999" ) , "**.**.* " ) + TEST_LINE( Transform( 1234 , "@BD 9999" ) , "**.**.* " ) + + TEST_LINE( Transform( 15 , "9999" ) , " 15" ) + TEST_LINE( Transform( 1.5 , "99.99" ) , " 1.50" ) + TEST_LINE( Transform( 1.5 , "9999" ) , " 2" ) + TEST_LINE( Transform( 15 , "####" ) , " 15" ) + TEST_LINE( Transform( 1.5 , "##.##" ) , " 1.50" ) + TEST_LINE( Transform( 1.5 , "####" ) , " 2" ) + TEST_LINE( Transform( 15 , " AX##" ) , " AX15" ) + TEST_LINE( Transform( 1.5 , "!9XPA.9" ) , "!1XPA.5" ) + TEST_LINE( Transform( -15 , "9999" ) , " -15" ) + TEST_LINE( Transform( -1.5 , "99.99" ) , "-1.50" ) + TEST_LINE( Transform( -15 , "$999" ) , "$-15" ) + TEST_LINE( Transform( -1.5 , "*9.99" ) , "-1.50" ) + TEST_LINE( Transform( 41 , "$$$9" ) , "$$41" ) + TEST_LINE( Transform( 41 , "***9" ) , "**41" ) + TEST_LINE( Transform( 15000 , "9999" ) , "****" ) + TEST_LINE( Transform( 15000 , "99,999" ) , "15,000" ) + TEST_LINE( Transform( 1500 , "99,999" ) , " 1,500" ) + TEST_LINE( Transform( 150 , "99,999" ) , " 150" ) + TEST_LINE( Transform( 150 , "99,99" ) , " 1,50" ) + TEST_LINE( Transform( 41 , "@Z 9999" ) , " 41" ) + TEST_LINE( Transform( 0 , "@Z 9999" ) , " " ) + TEST_LINE( Transform( 41 , "@0 9999" ) , " 41" ) + TEST_LINE( Transform( 0 , "@0 9999" ) , " 0" ) + TEST_LINE( Transform( 41 , "@B 9999" ) , "41 " ) + TEST_LINE( Transform( 41 , "@B 99.9" ) , "41.0" ) + TEST_LINE( Transform( 7 , "@B 99.9" ) , "7.0 " ) + TEST_LINE( Transform( 7 , "@C 99.9" ) , " 7.0 CR" ) + TEST_LINE( Transform( -7 , "@C 99.9" ) , "-7.0" ) + TEST_LINE( Transform( 7 , "@X 99.9" ) , " 7.0" ) + TEST_LINE( Transform( -7 , "@X 99.9" ) , " 7.0 DB" ) + TEST_LINE( Transform( 7 , "@( 99.9" ) , " 7.0" ) + TEST_LINE( Transform( -7 , "@( 99.9" ) , "(7.0)" ) + TEST_LINE( Transform( 7 , "9X9Z5.9" ) , " X7Z5.0" ) + TEST_LINE( Transform( -7 , "@R 9X9^" ) , "-X7^" ) + TEST_LINE( Transform( -7 , "9X9^" ) , "-X7^" ) + TEST_LINE( Transform( 1 , "@R 9HI!" ) , "1HI!" ) + TEST_LINE( Transform( 1 , "9HI!" ) , "1HI!" ) + TEST_LINE( Transform( -12 , "@( 99" ) , "(2)" ) /* BUG Fix */ + TEST_LINE( Transform( 12 , "@( 99" ) , "12" ) + TEST_LINE( Transform( 1 , "" ) , " 1" ) + TEST_LINE( Transform( 32768 , "" ) , " 32768" ) + TEST_LINE( Transform( -20 , "" ) , " -20" ) + TEST_LINE( Transform( 1048576 , "" ) , " 1048576" ) + TEST_LINE( Transform( 21.65 , "" ) , " 21.65" ) + TEST_LINE( Transform( -3.33 , "" ) , " -3.33" ) + TEST_LINE( Transform( -1234 , "@( 9999" ) , "(234)" ) /* BUG Fix */ + TEST_LINE( Transform( -1234 , "@B 9999" ) , "****" ) + TEST_LINE( Transform( -1234 , "@B( 9999" ) , "(234)" ) +// TEST_LINE( Transform( 1234 , "@E 9,999.99" ) , "1.234,00" ) +// TEST_LINE( Transform( 12.2 , "@E 9,999.99" ) , " 12,20" ) + TEST_LINE( Transform( -1234 , "@X 9999" ) , "1234 DB" ) + TEST_LINE( Transform( -1234 , "@BX 9999" ) , "1234 DB" ) + TEST_LINE( Transform( 1234 , "@B 9999" ) , "1234" ) + TEST_LINE( Transform( 1234 , "@BX 9999" ) , "1234" ) + TEST_LINE( Transform( 0 , "@Z 9999" ) , " " ) + TEST_LINE( Transform( 0 , "@BZ 9999" ) , " " ) + /* Show results, return ERRORLEVEL and exit */ - TEST_STAT() + TEST_END() + + RETURN NIL + +STATIC FUNCTION TEST_BEGIN() + LOCAL cOs := OS() + + IF "OS/2" $ cOs .OR. ; + "DOS" $ cOs + scNewLine := Chr(13) + Chr(10) + ELSE + scNewLine := Chr(10) + ENDIF + +/* +#ifdef __HARBOUR__ + scFileName := "rtl_test.hb" +#else + scFileName := "rtl_test.cl" +#endif +*/ + + snFhnd := 1 /* FHND_STDOUT */ + scFileName := "(stdout)" + + snCount := 0 + snPass := 0 + snFail := 0 + + fWrite(snFhnd, " Version: " + Version() + scNewLine +; + " OS: " + OS() + scNewLine +; + "Date, Time: " + DToS(Date()) + " " + Time() + scNewLine +; + " Output: " + scFileName + scNewLine +; + "===========================================================================" + scNewLine +; + scNewLine) + + fWrite(snFhnd, PadL("No", 4) + ". " +; + PadR("TestCall()", 35) + " -> " +; + PadR("Result", 15) + " | " +; + PadR("Expected", 15) +; + " [! *FAIL* !]" + scNewLine) + fWrite(snFhnd, "---------------------------------------------------------------------------" + scNewLine) RETURN NIL STATIC FUNCTION TEST_CALL(cBlock, bBlock, xResultExpected) LOCAL xResult := Eval(bBlock) - fWrite(1, PadR(StrTran(cBlock, Chr(0), "."), 40) + " -> " +; - PadR('"' + StrTran(XToStr(xResult), Chr(0), ".") + '"', 15) + " " +; - PadR('"' + StrTran(XToStr(xResultExpected), Chr(0), ".") + '"', 15)) + snCount++ + + fWrite(snFhnd, Str(snCount, 4) + ". " +; + PadR(StrTran(cBlock, Chr(0), "."), 35) + " -> " +; + PadR('"' + StrTran(XToStr(xResult), Chr(0), ".") + '"', 15) + " | " +; + PadR('"' + StrTran(XToStr(xResultExpected), Chr(0), ".") + '"', 15)) IF xResult == xResultExpected snPass++ ELSE - fWrite(1, "! *FAIL* !") + fWrite(snFhnd, " ! *FAIL* !") snFail++ ENDIF - fWrite(1, Chr(13) + Chr(10)) + fWrite(snFhnd, scNewLine) RETURN NIL -STATIC FUNCTION TEST_STAT() +STATIC FUNCTION TEST_END() - fWrite(1, Chr(13) + Chr(10) +; - "Test calls passed: " + Str(snPass) + Chr(13) + Chr(10) +; - "Test calls failed: " + Str(snFail) + Chr(13) + Chr(10)) + fWrite(snFhnd, scNewLine +; + "===========================================================================" + scNewLine +; + "Test calls passed: " + Str(snPass) + scNewLine +; + "Test calls failed: " + Str(snFail) + scNewLine +; + scNewLine) + + IF snFail != 0 + IF "CLIPPER" $ Upper(Version()) + fWrite(snFhnd, "WARNING ! Failures detected using Clipper." + scNewLine +; + "Please fix the expected result list, if this is not a bug in Clipper itself." + scNewLine) + ELSE + fWrite(snFhnd, "WARNING ! Failures detected" + scNewLine) + ENDIF + ENDIF ErrorLevel(iif(snFail != 0, 1, 0)) @@ -275,3 +464,24 @@ STATIC FUNCTION XToStr(xValue) ENDCASE RETURN "" + +#ifndef __HARBOUR__ +#ifndef __XPP__ + +FUNCTION SToD( cDate ) + LOCAL cOldDateFormat := Set(_SET_DATEFORMAT, "dd/mm/yyyy") + LOCAL dDate + + Set(_SET_DATEFORMAT, "yyyy/mm/dd") + + dDate := CToD( SubStr( cDate, 1, 4 ) + "/" +; + SubStr( cDate, 5, 2 ) + "/" +; + SubStr( cDate, 7, 2 ) ) + + Set(_SET_DATEFORMAT, cOldDateFormat) + + RETURN dDate + +#endif +#endif +