See ChangeLog entry 19990518-17:30 EDT David G. Holm <dholm@jsd-llc.com>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user