See ChangeLog entry 19990518-17:30 EDT David G. Holm <dholm@jsd-llc.com>

This commit is contained in:
David G. Holm
1999-05-18 22:30:43 +00:00
parent b2e09396ed
commit 3919c6b914
7 changed files with 173 additions and 82 deletions

View File

@@ -1,3 +1,26 @@
19990518-17:30 EDT David G. Holm <dholm@jsd-llc.com>
* source/rtl/console.c
- Use pItem->wLength and pItem->wDec when printing numbers.
* source/rtl/dates.c
- Moved date validation to hb_dateEncode function.
- hb_dtoc now puts date separators in an empty date.
- DAY function now sets stack.Return.wLength to 3.
- MONTH function now sets stack.Return.wLength to 3.
- YEAR function now sets stack.Return.wLength to 5.
* source/rtl/extend.c
- Set stack.Return.wLength and stack.Return.wDec for numbers.
- _retds() now returns 8 spaces for invalid dates.
* source/rtl/math.c
- ABS returns same numeric type as parameter.
- INT returns same numeric type as parameter, but for IT_DOUBLE, the
value is truncated, wLength is set to 10, and wDec is set to 0.
* tests/working/dates.prg
- Removed trailing spaces in strings in OUTSDT calls with multiple items,
because OUTSTD provides a leading space for all items but the first.
* tests/working/mathtest.prg
- Added QOUT(454.14) and QOUT(INT(454)) to debug INT problem with
Borland C++ 3.1, which lead to change to INT in source/rtl/math.c
19990518-15:20 EDT David G. Holm <dholm@jsd-llc.com>
* source/rtl/set.c
- Fixed memory leak in HB_SETCENTURY

View File

@@ -35,6 +35,7 @@ HARBOUR __ACCEPT( void ) /* Internal Clipper function used in ACCEPT command */
static void hb_outstd( WORD wParam )
{
char * szText;
PITEM pItem = _param( wParam, IT_ANY );
ULONG ulLenText;
char szBuffer [11];
@@ -45,7 +46,7 @@ static void hb_outstd( WORD wParam )
break;
case IT_INTEGER:
printf( "%10i", _parni( wParam ) );
printf( "%*i", pItem->wLength, pItem->value.iNumber );
break;
case IT_NIL:
@@ -60,7 +61,7 @@ static void hb_outstd( WORD wParam )
break;
case IT_LONG:
printf( "%10li", _parnl( wParam ) );
printf( "%*li", pItem->wLength, pItem->value.iNumber );
break;
case IT_STRING:
@@ -75,7 +76,10 @@ static void hb_outstd( WORD wParam )
break;
case IT_DOUBLE:
printf( "%14.4f", _parnd( wParam ) );
if( pItem->wDec )
printf( "%*.*f", pItem->wLength, pItem->wDec, pItem->value.dNumber );
else
printf( "%*ld", pItem->wLength, (long)pItem->value.dNumber );
break;
default:

View File

@@ -11,14 +11,41 @@
#define _OPTIMIZE_DTOS
#endif
extern STACK stack;
long hb_dateEncode( long lDay, long lMonth, long lYear )
{
BOOL bValid = FALSE;
long lFactor = ( lMonth < 3 ) ? -1: 0;
return ( 1461 * ( lFactor + 4800 + lYear ) / 4 ) +
( ( lMonth - 2 - ( lFactor * 12 ) ) * 367 ) / 12 -
( 3 * ( ( lYear + 4900 + lFactor ) / 100 ) / 4 ) +
lDay - 32075;
/* Perform date validation */
if (lMonth >= 1 && lMonth <= 12 && lDay >= 1
&& lYear >= 1 & lYear <= 2999)
{
/* Month, year, and lower day limits are simple,
but upper day limit is dependent upon month and leap year */
BOOL bLeapYear = FALSE;
int aiDayLimit [12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
if( lYear % 4 == 0 )
{
/* Check for leap year (every year that is evenly divisible by 4,
except for centuries, which must be evenly divisible by 400 */
if( lYear % 100 == 0 )
{
if( lYear % 400 == 0) bLeapYear = TRUE; /* Leap century */
}
else bLeapYear = TRUE; /* Leap year */
if( bLeapYear ) aiDayLimit[ 1 ] = 29;
}
if( lDay <= (long)aiDayLimit[ (int)lMonth - 1 ] ) bValid = TRUE;
}
if( bValid )
return ( 1461 * ( lFactor + 4800 + lYear ) / 4 ) +
( ( lMonth - 2 - ( lFactor * 12 ) ) * 367 ) / 12 -
( 3 * ( ( lYear + 4900 + lFactor ) / 100 ) / 4 ) +
lDay - 32075;
else return ( 0 );
}
void hb_dateDecode( long julian, long * plDay, long * plMonth, long * plYear )
@@ -32,14 +59,13 @@ void hb_dateDecode( long julian, long * plDay, long * plMonth, long * plYear )
julian -= ( ( 1461 * X ) / 4 ) - 31;
V = 80 * julian / 2447;
U = V / 11;
* plDay = julian - ( 2447 * V / 80 );
* plMonth = V + 2 - ( U * 12 );
* plYear = X + U + ( W - 49 ) * 100;
if( plDay ) * plDay = julian - ( 2447 * V / 80 );
if( plMonth ) * plMonth = V + 2 - ( U * 12 );
if( plYear ) * plYear = X + U + ( W - 49 ) * 100;
}
HARBOUR CTOD( void )
{
BOOL bValid = FALSE;
char * szDate = _parc( 1 );
int d_value = 0, m_value = 0, y_value = 0;
int d_pos = 0, m_pos = 0, y_pos = 0;
@@ -114,34 +140,8 @@ HARBOUR CTOD( void )
else y_value += ((digit * 100) + 100);
}
}
/* Perform date validation before converting to date */
if (szDate && m_value >= 1 && m_value <= 12 && d_value >= 1
&& y_value >= 0 & y_value <= 2999)
{
/* Month, year, and lower day limits are easy,
but upper day limit is dependent upon month and leap year */
BOOL bLeapYear = FALSE;
int d_limit [12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
if( y_value % 4 == 0 )
{
/* Check for leap year (every year that is evenly divisible by 4,
except for centuries, which must be evenly divisible by 400 */
if( y_value % 100 == 0 )
{
if( y_value % 400 == 0) bLeapYear = TRUE; /* Leap century */
}
else bLeapYear = TRUE; /* Leap year */
if( bLeapYear ) d_limit[ 1 ] = 29;
}
if( d_value <= d_limit[ m_value - 1 ] ) bValid = TRUE;
}
if( bValid )
{
sprintf (szDateFormat, "%04i%02i%02i", y_value, m_value, d_value);
_retds( szDateFormat );
}
else _retds( "" );
sprintf (szDateFormat, "%04i%02i%02i", y_value, m_value, d_value);
_retds( szDateFormat );
}
char * hb_dtoc (char * szDate, char * szDateFormat)
@@ -276,9 +276,20 @@ char * hb_dtoc (char * szDate, char * szDateFormat)
}
else
{
/* Not a valid date string, so return a blank date */
format_count = size;
strncpy( szDateFormat, " ", format_count );
/* Not a valid date string, so return a blank date with separators */
format_count = size; /* size is either 8 or 10 */
strncpy( szDateFormat, hb_set.HB_SET_DATEFORMAT, size );
for (digit_count = 0; digit_count < size; digit_count++)
switch (szDateFormat [digit_count])
{
case 'D':
case 'd':
case 'M':
case 'm':
case 'Y':
case 'y':
szDateFormat [digit_count] = ' ';
}
}
szDateFormat [format_count] = 0;
return (szDateFormat);
@@ -339,6 +350,7 @@ HARBOUR DAY( void )
{
hb_dateDecode( pDate->value.lDate, &lDay, &lMonth, &lYear );
_retni( lDay );
stack.Return.wLength = 3;
}
else
{
@@ -358,6 +370,7 @@ HARBOUR MONTH( void )
{
hb_dateDecode( pDate->value.lDate, &lDay, &lMonth, &lYear );
_retni( lMonth );
stack.Return.wLength = 3;
}
else
{
@@ -377,6 +390,7 @@ HARBOUR YEAR( void )
{
hb_dateDecode( pDate->value.lDate, &lDay, &lMonth, &lYear );
_retni( lYear );
stack.Return.wLength = 5;
}
else
{

View File

@@ -106,7 +106,7 @@ char * _pards( WORD wParam, ... )
if( IS_ARRAY( pItem ) && wArrayIndex )
/* TODO: implement wArrayIndex use when retrieving an array element */
return "";
return " ";
else if( IS_DATE( pItem ) && pItem->value.lDate > 0 )
{
@@ -127,9 +127,9 @@ char * _pards( WORD wParam, ... )
return stack.szDate; /* this guaranties good behavior when multithreading */
}
else
return "";
return " ";
}
return "";
return " ";
}
int _parl( WORD wParam, ... )
@@ -326,10 +326,16 @@ void _retds( char * szDate ) /* szDate must have yyyymmdd format */
{
long lDay, lMonth, lYear;
lDay = ( ( szDate[ 6 ] - '0' ) * 10 ) + ( szDate[ 7 ] - '0' );
lMonth = ( ( szDate[ 4 ] - '0' ) * 10 ) + ( szDate[ 5 ] - '0' );
lYear = ( ( szDate[ 0 ] - '0' ) * 1000 ) + ( ( szDate[ 1 ] - '0' ) * 100 ) +
( ( szDate[ 2 ] - '0' ) * 10 ) + ( szDate[ 3 ] - '0' );
if( szDate && strlen( szDate ) == 8 )
{
/* Date string has correct length, so attempt to convert */
lDay = ( ( szDate[ 6 ] - '0' ) * 10 ) + ( szDate[ 7 ] - '0' );
lMonth = ( ( szDate[ 4 ] - '0' ) * 10 ) + ( szDate[ 5 ] - '0' );
lYear = ( ( szDate[ 0 ] - '0' ) * 1000 ) + ( ( szDate[ 1 ] - '0' ) * 100 ) +
( ( szDate[ 2 ] - '0' ) * 10 ) + ( szDate[ 3 ] - '0' );
}
else lDay = lMonth = lYear = 0; /* Date string missing or bad length,
so force an empty date */
ItemRelease( &stack.Return );
@@ -338,17 +344,15 @@ void _retds( char * szDate ) /* szDate must have yyyymmdd format */
/* QUESTION: Is this ok ? we are going to use a long to store the date */
/* QUESTION: What happens if we use sizeof( LONG ) instead ? */
/* QUESTION: Would it break Clipper language code ? */
if( szDate && strlen( szDate ) == 8 )
stack.Return.value.lDate = hb_dateEncode( lDay, lMonth, lYear );
else
stack.Return.value.lDate = 0;
stack.Return.value.lDate = hb_dateEncode( lDay, lMonth, lYear );
}
void _retnd( double dNumber )
{
ItemRelease( &stack.Return );
stack.Return.wType = IT_DOUBLE;
stack.Return.wLength = sizeof( double ); /* QUESTION: Is this correct ? */
stack.Return.wLength = 13;
stack.Return.wDec = 2;
stack.Return.value.dNumber = dNumber;
}
@@ -356,7 +360,8 @@ void _retni( int iNumber )
{
ItemRelease( &stack.Return );
stack.Return.wType = IT_INTEGER;
stack.Return.wLength = sizeof( int ); /* QUESTION: Is this correct ? */
stack.Return.wLength = 10;
stack.Return.wDec = 0;
stack.Return.value.iNumber = iNumber;
}
@@ -364,7 +369,7 @@ void _retl( int iTrueFalse )
{
ItemRelease( &stack.Return );
stack.Return.wType = IT_LOGICAL;
stack.Return.wLength = 1; /* QUESTION: Is this correct ? */
stack.Return.wLength = 3;
stack.Return.value.iLogical = iTrueFalse;
}
@@ -372,7 +377,8 @@ void _retnl( long lNumber )
{
ItemRelease( &stack.Return );
stack.Return.wType = IT_LONG;
stack.Return.wLength = sizeof( LONG ); /* QUESTION: Is this correct ? */
stack.Return.wLength = 10;
stack.Return.wDec = 0;
stack.Return.value.lNumber = lNumber;
}
@@ -446,10 +452,16 @@ void _stords( char * szDate, WORD wParam, ... ) /* szDate must have yyyymmdd for
WORD wArrayIndex = 0;
long lDay, lMonth, lYear;
lDay = ( ( szDate[ 6 ] - '0' ) * 10 ) + ( szDate[ 7 ] - '0' );
lMonth = ( ( szDate[ 4 ] - '0' ) * 10 ) + ( szDate[ 5 ] - '0' );
lYear = ( ( szDate[ 0 ] - '0' ) * 1000 ) + ( ( szDate[ 1 ] - '0' ) * 100 ) +
( ( szDate[ 2 ] - '0' ) * 10 ) + ( szDate[ 3 ] - '0' );
if( szDate && strlen( szDate ) == 8 )
{
/* Date string is valid length, so attempt conversion */
lDay = ( ( szDate[ 6 ] - '0' ) * 10 ) + ( szDate[ 7 ] - '0' );
lMonth = ( ( szDate[ 4 ] - '0' ) * 10 ) + ( szDate[ 5 ] - '0' );
lYear = ( ( szDate[ 0 ] - '0' ) * 1000 ) + ( ( szDate[ 1 ] - '0' ) * 100 ) +
( ( szDate[ 2 ] - '0' ) * 10 ) + ( szDate[ 3 ] - '0' );
}
else lDay = lMonth = lYear = 0; /* Date string missing or bad length,
so force an empty date */
va_start( va, wParam );
wArrayIndex = va_arg( va, int );
@@ -496,6 +508,7 @@ void _storl( int iLogical, WORD wParam, ... )
pItemRef = stack.pItems + pItem->value.wItem;
ItemRelease( pItemRef );
pItemRef->wType = IT_LOGICAL;
pItemRef->wLength = 3;
pItemRef->value.iLogical = iLogical;
}
}
@@ -523,7 +536,9 @@ void _storni( int iValue, WORD wParam, ... )
{
pItemRef = stack.pItems + pItem->value.wItem;
ItemRelease( pItemRef );
pItemRef->wType = IT_INTEGER;
pItemRef->wType = IT_INTEGER;
pItemRef->wLength = 10;
pItemRef->wDec = 0;
pItemRef->value.iNumber = iValue;
}
}
@@ -551,7 +566,9 @@ void _stornl( long lValue, WORD wParam, ... )
{
pItemRef = stack.pItems + pItem->value.wItem;
ItemRelease( pItemRef );
pItemRef->wType = IT_LONG;
pItemRef->wType = IT_LONG;
pItemRef->wLength = 10;
pItemRef->wDec = 0;
pItemRef->value.lNumber = lValue;
}
}
@@ -579,7 +596,9 @@ void _stornd( double dValue, WORD wParam, ... )
{
pItemRef = stack.pItems + pItem->value.wItem;
ItemRelease( pItemRef );
pItemRef->wType = IT_DOUBLE;
pItemRef->wType = IT_DOUBLE;
pItemRef->wLength = 13;
pItemRef->wDec = 2;
pItemRef->value.dNumber = dValue;
}
}

View File

@@ -5,20 +5,35 @@
#include <extend.h>
#include <math.h>
extern STACK stack;
HARBOUR ABS( void )
{
if( _pcount() == 1 )
{
PITEM pNumber = _param(1, IT_NUMERIC);
if( pNumber )
if( pNumber ) switch( pNumber->wType )
{
double dNumber = _parnd(1);
if( dNumber >= 0 )
_retnd( dNumber );
else
_retnd( -dNumber );
case IT_INTEGER:
if( pNumber->value.iNumber >= 0 )
_retni( pNumber->value.iNumber );
else
_retni( -pNumber->value.iNumber );
break;
case IT_LONG:
if( pNumber->value.lNumber >= 0 )
_retnl( pNumber->value.lNumber );
else
_retnl( -pNumber->value.lNumber );
break;
case IT_DOUBLE:
if( pNumber->value.dNumber >= 0.0 )
_retnd( pNumber->value.dNumber );
else
_retnd( -pNumber->value.dNumber );
}
else
{
@@ -71,10 +86,24 @@ HARBOUR INT( void )
if( _pcount() == 1 )
{
PITEM pNumber = _param(1, IT_NUMERIC);
double dTemp;
if( pNumber )
if( pNumber ) switch( pNumber->wType )
{
_retnl( _parnd(1) );
case IT_INTEGER:
_retni( pNumber->value.iNumber );
break;
case IT_LONG:
_retnl( pNumber->value.lNumber );
break;
case IT_DOUBLE:
modf( pNumber->value.dNumber, &dTemp );
_retnd( dTemp ); /* Return integer part of double value */
stack.Return.wLength = 10; /* Set return length same as int or long */
stack.Return.wDec = 0; /* Set zero decimal places */
/* Because _retnl( _parnd( 1 ) ); doesn't work in Borland Turbo C++ 3.1 */
}
else
{

View File

@@ -22,18 +22,18 @@ local cNewLine := CHR( 10 )
OUTSTD (HB_SETCENTURY ())
OUTSTD (cNewLine, "")
OUTSTD (cNewLine, "dDate = CToD( '02/04/1999' ) => ", dDate := CToD( "02/04/1999" ))
OUTSTD (cNewLine, "dDate = CToD( '02/04/1999' ) =>", dDate := CToD( "02/04/1999" ))
OUTSTD (cNewLine, "ValType( dDate ) = ", ValType( dDate ))
OUTSTD (cNewLine, "ValType( dDate ) =", ValType( dDate ))
OUTSTD (cNewLine, "Day( dDate ) = ", Day( dDate ))
OUTSTD (cNewLine, "Month( dDate ) = ", Month( dDate ))
OUTSTD (cNewLine, "Year( dDate ) = ", Year( dDate ), cNewLine)
OUTSTD (cNewLine, "Day( dDate ) =", Day( dDate ))
OUTSTD (cNewLine, "Month( dDate ) =", Month( dDate ))
OUTSTD (cNewLine, "Year( dDate ) =", Year( dDate ), cNewLine)
OUTSTD (cNewLine, "dDate + 5 = ", dDate2 := dDate + 5)
OUTSTD (cNewLine, "dDate - 5 = ", dDate - 5, cNewLine )
OUTSTD (cNewLine, "dDate + 5 =", dDate2 := dDate + 5)
OUTSTD (cNewLine, "dDate - 5 =", dDate - 5, cNewLine )
OUTSTD (cNewLine, "dDate2 - dDate = ", dDate2 - dDate)
OUTSTD (cNewLine, "dDate2 - dDate =", dDate2 - dDate)
OUTSTD (cNewLine, "")
OUTSTD (cNewLine, dDate, DTOS (dDate))

View File

@@ -10,5 +10,7 @@ qout(acos(43) )
qout(atan(54))
qout(abs(10))
qout(exp(15))
qout(454.14)
qout(int(454.14))
qout(int(454))
return nil