From 64d9b508939fb15d72fdfa825ee8938506764d66 Mon Sep 17 00:00:00 2001
From: "Thomas G. Lockhart" <lockhart@fourpalms.org>
Date: Sun, 11 May 1997 15:11:47 +0000
Subject: [PATCH] Fix timezone manipulation code to avoid crashes on some
 machines. Add type conversion functions for floating point numbers. Check for
 zero in unary minus floating point code (IEEE allows an  explicit negative
 zero which looks ugly in a query result!). Ensure circle type has
 non-negative radius.

---
 src/backend/utils/adt/datetime.c  |   5 +-
 src/backend/utils/adt/dt.c        | 234 ++++++++++++---------------
 src/backend/utils/adt/float.c     | 255 +++++++++++++++++++++++-------
 src/backend/utils/adt/geo_ops.c   |   6 +-
 src/backend/utils/adt/nabstime.c  |   6 +-
 src/backend/utils/adt/timestamp.c |   3 +-
 6 files changed, 308 insertions(+), 201 deletions(-)

diff --git a/src/backend/utils/adt/datetime.c b/src/backend/utils/adt/datetime.c
index 07113bd7cf2..3fa05b507fc 100644
--- a/src/backend/utils/adt/datetime.c
+++ b/src/backend/utils/adt/datetime.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.4 1997/04/17 13:50:34 scrappy Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.5 1997/05/11 15:11:31 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -558,7 +558,8 @@ abstime_date(AbsoluteTime abstime)
 #if FALSE
 	GetCurrentTime(tm);
 #endif
-	abstime = GetCurrentTransactionStartTime() + CTimeZone;
+	abstime = GetCurrentTransactionStartTime();
+	abstime2tm(abstime, &CTimeZone, tm);
 	date->year = tm->tm_year;
 	date->month = tm->tm_mon;
 	date->day = tm->tm_mday;
diff --git a/src/backend/utils/adt/dt.c b/src/backend/utils/adt/dt.c
index d700cbd6bd6..de0ec568544 100644
--- a/src/backend/utils/adt/dt.c
+++ b/src/backend/utils/adt/dt.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/dt.c,v 1.19 1997/04/27 19:20:10 thomas Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/dt.c,v 1.20 1997/05/11 15:11:34 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -32,7 +32,7 @@
 #include "utils/builtins.h"
 
 #define USE_DATE_CACHE 1
-
+#define ROUND_ALL 0
 
 #define isleap(y) (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0)))
 
@@ -78,7 +78,8 @@ datetime_in(char *str)
 
     switch (dtype) {
     case DTK_DATE:
-	*result = tm2datetime( tm, fsec, &tz);
+	if (tm2datetime( tm, fsec, &tz, result) != 0)
+	    elog(WARN,"Datetime out of range %s",str);
 
 #ifdef DATEDEBUG
 printf( "datetime_in- date is %f\n", *result);
@@ -123,6 +124,7 @@ datetime_out(DateTime *dt)
     int tz;
     struct tm tt, *tm = &tt;
     double fsec;
+    char *tzn;
     char buf[MAXDATELEN+1];
 
     if (!PointerIsValid(dt))
@@ -131,8 +133,8 @@ datetime_out(DateTime *dt)
     if (DATETIME_IS_RESERVED(*dt)) {
 	EncodeSpecialDateTime(*dt, buf);
 
-    } else if (datetime2tm( *dt, &tz, tm, &fsec) == 0) {
-	EncodeDateTime(tm, fsec, &tz, DateStyle, buf);
+    } else if (datetime2tm( *dt, &tz, tm, &fsec, &tzn) == 0) {
+	EncodeDateTime(tm, fsec, &tz, &tzn, DateStyle, buf);
 
     } else {
 	EncodeSpecialDateTime(DT_INVALID, buf);
@@ -179,7 +181,7 @@ timespan_in(char *str)
 
     if ((ParseDateTime( str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0)
       || (DecodeDateDelta( field, ftype, nf, &dtype, tm, &fsec) != 0))
-	elog(WARN,"Bad timespan external representation %s",str);
+	elog(WARN,"Bad timespan external representation '%s'",str);
 
     if (!PointerIsValid(span = PALLOCTYPE(TimeSpan)))
 	elog(WARN,"Memory allocation failed, can't input timespan '%s'",str);
@@ -190,6 +192,7 @@ timespan_in(char *str)
 #if FALSE
 	    TIMESPAN_INVALID(span);
 #endif
+	    elog(WARN,"Bad timespan external representation %s",str);
 	};
 	break;
 
@@ -292,14 +295,14 @@ SetDateTime( DateTime dt) {
 
     if (DATETIME_IS_CURRENT(dt)) {
 	GetCurrentTime(&tt);
-	dt = tm2datetime( &tt, 0, NULL);
+	tm2datetime( &tt, 0, NULL, &dt);
 
 #ifdef DATEDEBUG
 printf( "SetDateTime- current time is %f\n", dt);
 #endif
     } else { /* if (DATETIME_IS_EPOCH(dt1)) */
 	GetEpochTime(&tt);
-	dt = tm2datetime( &tt, 0, NULL);
+	tm2datetime( &tt, 0, NULL, &dt);
 #ifdef DATEDEBUG
 printf( "SetDateTime- epoch time is %f\n", dt);
 #endif
@@ -629,7 +632,7 @@ TimeSpan *datetime_sub(DateTime *datetime1, DateTime *datetime2)
 	DATETIME_INVALID( result->time);
 
     } else {
-	result->time = (dt1 - dt2);
+	result->time = JROUND(dt1 - dt2);
     };
     result->month = 0;
 
@@ -649,11 +652,6 @@ DateTime *datetime_add_span(DateTime *datetime, TimeSpan *span)
 {
     DateTime *result;
 
-#if FALSE
-    double date, time;
-    int year, mon, mday;
-#endif
-
     if ((!PointerIsValid(datetime)) || (!PointerIsValid(span)))
 	return NULL;
 
@@ -677,7 +675,7 @@ printf( "datetime_add_span- add %f to %d %f\n", *datetime, span->month, span->ti
 	    struct tm tt, *tm = &tt;
 	    double fsec;
 
-	    if (datetime2tm( *result, NULL, tm, &fsec) == 0) {
+	    if (datetime2tm( *result, NULL, tm, &fsec, NULL) == 0) {
 #ifdef DATEDEBUG
 printf( "datetime_add_span- date was %d.%02d.%02d\n", tm->tm_year, tm->tm_mon, tm->tm_mday);
 #endif
@@ -702,17 +700,18 @@ printf( "datetime_add_span- date was %d.%02d.%02d\n", tm->tm_year, tm->tm_mon, t
 #ifdef DATEDEBUG
 printf( "datetime_add_span- date becomes %d.%02d.%02d\n", tm->tm_year, tm->tm_mon, tm->tm_mday);
 #endif
-		*result = tm2datetime( tm, fsec, NULL);
+		tm2datetime( tm, fsec, NULL, result);
 
 	    } else {
 		DATETIME_INVALID(*result);
 	    };
 	};
 
-#if FALSE
+#ifdef ROUND_ALL
 	*result = JROUND(*result + span->time);
-#endif
+#else
 	*result += span->time;
+#endif
     };
 
     return(result);
@@ -1009,6 +1008,7 @@ datetime_part(text *units, DateTime *datetime)
     int i;
     char *up, *lp, lowunits[MAXDATELEN+1];
     double fsec;
+    char *tzn;
     struct tm tt, *tm = &tt;
 
     if ((!PointerIsValid(units)) || (!PointerIsValid(datetime)))
@@ -1039,7 +1039,7 @@ printf( "datetime_part- units %s type=%d value=%d\n", lowunits, type, val);
 
 	dt = (DATETIME_IS_RELATIVE(*datetime)? SetDateTime(*datetime): *datetime); 
 
-	if (datetime2tm( dt, &tz, tm, &fsec) == 0) {
+	if (datetime2tm( dt, &tz, tm, &fsec, &tzn) == 0) {
 	    switch (val) {
 	    case DTK_TZ:
 		*result = tz;
@@ -1473,40 +1473,51 @@ datetkn *deltacache[MAXDATEFIELDS] = {NULL};
  * Ref: Explanatory Supplement to the Astronomical Almanac, 1992.
  *  University Science Books, 20 Edgehill Rd. Mill Valley CA 94941.
  *
+ * Use the algorithm by Henry Fliegel, a former NASA/JPL colleague
+ *  now at Aerospace Corp. (hi, Henry!)
+ *
  * These routines will be used by other date/time packages - tgl 97/02/25
  */
 
-#define USE_FLIEGEL 1
+/* Set the minimum year to one greater than the year of the first valid day
+ *  to avoid having to check year and day both. - tgl 97/05/08
+ */
+
+#define UTIME_MINYEAR (1901)
+#define UTIME_MINMONTH (12)
+#define UTIME_MINDAY (14)
+#define UTIME_MAXYEAR (2038)
+#define UTIME_MAXMONTH (01)
+#define UTIME_MAXDAY (18)
+
+#define IS_VALID_UTIME(y,m,d) (((y > UTIME_MINYEAR) \
+ || ((y == UTIME_MINYEAR) && ((m > UTIME_MINMONTH) \
+  || ((m == UTIME_MINMONTH) && (d >= UTIME_MINDAY))))) \
+ && ((y < UTIME_MAXYEAR) \
+ || ((y == UTIME_MAXYEAR) && ((m < UTIME_MAXMONTH) \
+  || ((m == UTIME_MAXMONTH) && (d <= UTIME_MAXDAY))))))
+
+#define JULIAN_MINYEAR (-4713)
+#define JULIAN_MINMONTH (11)
+#define JULIAN_MINDAY (23)
+
+#define IS_VALID_JULIAN(y,m,d) ((y > JULIAN_MINYEAR) \
+ || ((y == JULIAN_MINYEAR) && ((m > JULIAN_MINMONTH) \
+  || ((m == JULIAN_MINMONTH) && (d >= JULIAN_MINDAY)))))
 
 int
 date2j(int y, int m, int d)
 {
-#if USE_FLIEGEL
     int m12 = (m-14)/12;
 
     return((1461*(y+4800+m12))/4 + (367*(m-2-12*(m12)))/12
      - (3*((y+4900+m12)/100))/4 + d - 32075);
-
-#else
-    int c, ya;
-
-    if (m > 2) {
-	m -= 3;
-    } else {
-	m += 9;
-	y--;
-    };
-    c = y/100;
-    ya = y - 100*c;
-    return((146097*c)/4+(1461*ya)/4+(153*m+2)/5+d+1721119);
-#endif
 } /* date2j() */
 
 void j2date( int jd, int *year, int *month, int *day)
 {
     int j, y, m, d;
 
-#if USE_FLIEGEL
     int i, l, n;
 
     l = jd + 68569;
@@ -1520,26 +1531,6 @@ void j2date( int jd, int *year, int *month, int *day)
     m = (j+2) - (12*l);
     y = 100*(n-49)+i+l;
 
-#else
-    j = jd - 1721119;
-    y = (4*j-1)/146097;
-    j = 4*j-1-146097*y;
-    d = j/4;
-    j = (4*d+3)/1461;
-    d = 4*d+3-1461*j;
-    d = (d+4)/4;
-    m = (5*d-3)/153;
-    d = 5*d-3-153*m;
-    d = (d+5)/5;
-    y = 100*y+j;
-    if (m < 10) {
-	m += 3;
-    } else {
-	m -= 9;
-	y++;
-    };
-#endif
-
     *year = y;
     *month = m;
     *day = d;
@@ -1560,25 +1551,34 @@ int j2day( int date)
  * Convert datetime data type to POSIX time structure.
  * Note that year is _not_ 1900-based, but is an explicit full value.
  * Also, month is one-based, _not_ zero-based.
+ * Returns:
+ *   0 on success
+ *  -1 on out of range
  */
 int
-datetime2tm( DateTime dt, int *tzp, struct tm *tm, double *fsec)
+datetime2tm( DateTime dt, int *tzp, struct tm *tm, double *fsec, char **tzn)
 {
-    double date, time, sec;
+    double date, date0, time, sec;
     time_t utime;
 #ifdef USE_POSIX_TIME
     struct tm *tx;
 #endif
 
+
+    date0 = date2j(2000,1,1);
     time = (modf( dt/86400, &date)*86400);
-    date += date2j(2000,1,1);
+
     if (time < 0) {
 	    time += 86400;
 	    date -= 1;
     };
 
     /* Julian day routine does not work for negative Julian days */
-    if (date < 0) return -1;
+    if (date < -date0)
+	return -1;
+
+    /* add offset to go from J2000 back to standard Julian date */
+    date += date0;
 
 #ifdef DATEDEBUG
 printf( "datetime2tm- date is %f (%f %f)\n", dt, date, time);
@@ -1601,8 +1601,9 @@ printf( "datetime2tm- time is %02d:%02d:%02d %.7f\n", tm->tm_hour, tm->tm_min, t
 
     if (tzp != NULL) {
 	/* XXX HACK to get time behavior compatible with Postgres v6.0 - tgl 97/04/07 */
-	if ((tm->tm_year >= 1902) && (tm->tm_year < 2038)) {
-	    utime = (dt + (date2j(2000,1,1)-date2j(1970,1,1))*86400);
+	if (IS_VALID_UTIME( tm->tm_year, tm->tm_mon, tm->tm_mday)) {
+	    utime = (dt + (date0-date2j(1970,1,1))*86400);
+
 #ifdef USE_POSIX_TIME
 	    tx = localtime(&utime);
 #ifdef DATEDEBUG
@@ -1617,32 +1618,31 @@ printf( "datetime2tm- (localtime) %d.%02d.%02d %02d:%02d:%02.0f %s %s dst=%d\n",
 	    tm->tm_min = tx->tm_min;
 	    tm->tm_sec = tx->tm_sec;
 	    tm->tm_isdst = tx->tm_isdst;
+
 #ifdef HAVE_INT_TIMEZONE
 	    *tzp = (tm->tm_isdst? (timezone - 3600): timezone);
+	    if (tzn != NULL) *tzn = tzname[(tm->tm_isdst > 0)];
+
 #else /* !HAVE_INT_TIMEZONE */
 	    *tzp = (tm->tm_isdst? (tm->tm_gmtoff - 3600): tm->tm_gmtoff); /* tm_gmtoff is Sun/DEC-ism */
+	    if (tzn != NULL) *tzn = tm->tm_zone;
 #endif
+
 #else /* !USE_POSIX_TIME */
 	    *tzp = CTimeZone;	/* V7 conventions; don't know timezone? */
+	    if (tzn != NULL) *tzn = CTZName;
 #endif
 	} else {
 	    *tzp = 0;
 	    tm->tm_isdst = 0;
-#ifdef USE_POSIX_TIME
-#ifdef HAVE_INT_TIMEZONE
-	    tzname[0] = "GMT";
-#else /* !HAVE_INT_TIMEZONE */
-	    tm->tm_zone = "GMT";
-#endif
-#else /* !USE_POSIX_TIME */
-	    strcpy( CTZName, "GMT");
-#endif
+	    if (tzn != NULL) *tzn = NULL;
 	};
 
 	dt = dt2local( dt, *tzp);
 
     } else {
 	tm->tm_isdst = 0;
+	if (tzn != NULL) *tzn = NULL;
     };
 
 #ifdef DATEDEBUG
@@ -1666,26 +1666,25 @@ printf( "datetime2tm- timezone is %s; offset is %d (%d); daylight is %d\n",
  * Note that year is _not_ 1900-based, but is an explicit full value.
  * Also, month is one-based, _not_ zero-based.
  */
-DateTime
-tm2datetime( struct tm *tm, double fsec, int *tzp) {
+int
+tm2datetime( struct tm *tm, double fsec, int *tzp, DateTime *result) {
 
-    DateTime result;
     double date, time;
 
     /* Julian day routines are not correct for negative Julian days */
-    if ((date = date2j(tm->tm_year,tm->tm_mon,tm->tm_mday)) < 0)
+    if (! IS_VALID_JULIAN( tm->tm_year, tm->tm_mon, tm->tm_mday))
 	return(DT_INVALID);
 
-    date -= date2j(2000,1,1);
+    date = date2j(tm->tm_year,tm->tm_mon,tm->tm_mday) - date2j(2000,1,1);
     time = time2t(tm->tm_hour,tm->tm_min,(tm->tm_sec + fsec));
-    result = (date*86400+time);
+    *result = (date*86400+time);
 #ifdef DATEDEBUG
-printf( "tm2datetime- date is %f (%f %f %d)\n", result, date, time, (((tm->tm_hour*60)+tm->tm_min)*60+tm->tm_sec));
+printf( "tm2datetime- date is %f (%f %f %d)\n", *result, date, time, (((tm->tm_hour*60)+tm->tm_min)*60+tm->tm_sec));
 printf( "tm2datetime- time is %f %02d:%02d:%02d %f\n", time, tm->tm_hour, tm->tm_min, tm->tm_sec, fsec);
 #endif
-    if (tzp != NULL) result = dt2local(result, -(*tzp));
+    if (tzp != NULL) *result = dt2local(*result, -(*tzp));
 
-    return(result);
+    return 0;
 } /* tm2datetime() */
 
 
@@ -1703,10 +1702,11 @@ timespan2tm(TimeSpan span, struct tm *tm, float8 *fsec)
 	tm->tm_mon = 0;
     };
 
-#if FALSE
+#ifdef ROUND_ALL
     time = JROUND(span.time);
-#endif
+#else
     time = span.time;
+#endif
 
     funit = modf( (time / 86400), &iunit);
     tm->tm_mday = iunit;
@@ -1743,7 +1743,7 @@ printf( "tm2timespan- %d %f = %04d-%02d-%02d %02d:%02d:%02d %.2f\n", span->month
  tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, fsec);
 #endif
 
-    return 1;
+    return 0;
 } /* tm2timespan() */
 
 
@@ -2092,7 +2092,7 @@ printf( " %02d:%02d:%02d\n", tm->tm_hour, tm->tm_min, tm->tm_sec);
     if ((*dtype == DTK_DATE) && ((fmask & DTK_DATE_M) == DTK_DATE_M)
       && (tzp != NULL) && (! (fmask & DTK_M(TZ)))) {
 
-	if ((tm->tm_year >= 1902) && (tm->tm_year < 2038)) {
+	if (IS_VALID_UTIME( tm->tm_year, tm->tm_mon, tm->tm_mday)) {
 #ifdef USE_POSIX_TIME
 	    tm->tm_year -= 1900;
 	    tm->tm_mon -= 1;
@@ -2667,6 +2667,7 @@ printf( "DecodeDateDelta- field[%d] is %s (type %d)\n", i, field[i], ftype[i]);
 #endif
 	switch (ftype[i]) {
 	case DTK_TIME:
+	    /* already read in forward-scan above so return error */
 #if FALSE
 	    if (DecodeTime(field[i], fmask, &tmask, tm, fsec) != 0) return -1;
 #endif
@@ -2916,47 +2917,27 @@ printf( "EncodeSpecialDateTime- unrecognized date\n");
 /* EncodeDateTime()
  * Encode date and time interpreted as local time.
  */
-int EncodeDateTime(struct tm *tm, double fsec, int *tzp, int style, char *str)
+int EncodeDateTime(struct tm *tm, double fsec, int *tzp, char **tzn, int style, char *str)
 {
     char mabbrev[4], dabbrev[4];
     int day, hour, min;
     double sec;
-#if defined(DATEDEBUG) && FALSE
-    char buf[MAXDATELEN+1];
-#endif
 
     sec = (tm->tm_sec + fsec);
 
-#if FALSE
-    tm->tm_isdst = -1;
-#endif
-
 #ifdef DATEDEBUG
 #ifdef USE_POSIX_TIME
 #ifdef HAVE_INT_TIMEZONE
 printf( "EncodeDateTime- timezone is %s (%s); offset is %d (%d); daylight is %d (%d)\n",
- tzname[0], CTZName, *tzp, CTimeZone, tm->tm_isdst, CDayLight);
+ *tzn, tzname[0], *tzp, CTimeZone, tm->tm_isdst, CDayLight);
 #else
 printf( "EncodeDateTime- timezone is %s (%s); offset is %ld (%d); daylight is %d (%d)\n",
- tm->tm_zone, CTZName, (- tm->tm_gmtoff), CTimeZone, tm->tm_isdst, CDayLight);
+ *tzn, tm->tm_zone, (- tm->tm_gmtoff), CTimeZone, tm->tm_isdst, CDayLight);
 #endif
 #else
-printf( "EncodeDateTime- timezone is %s; offset is %d; daylight is %d\n",
- CTZName, CTimeZone, CDayLight);
-#endif
+printf( "EncodeDateTime- timezone is %s (%s); offset is %d; daylight is %d\n",
+ *tzn, CTZName, CTimeZone, CDayLight);
 #endif
-
-#ifdef USE_POSIX_TIME
-    /* XXX HACK to get time behavior compatible with Postgres v6.0 - tgl 97/04/07 */
-    if ((tm->tm_year >= 1902) && (tm->tm_year < 2038)) {
-	tm->tm_year -= 1900;
-	tm->tm_mon -= 1;
-	mktime(tm);
-	tm->tm_year += 1900;
-	tm->tm_mon += 1;
-    } else {
-	tm->tm_isdst = -1;
-    };
 #endif
 
     day = date2j( tm->tm_year, tm->tm_mon, tm->tm_mday);
@@ -2980,7 +2961,7 @@ printf( "EncodeDateTime- day is %d\n", day);
 	      tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min);
 	    sprintf( (str+17), ((fsec != 0)? "%05.2f": "%02.0f"), sec);
 
-	    if (tm->tm_isdst >= 0) {
+	    if ((*tzn != NULL) && (tm->tm_isdst >= 0)) {
 		if (tzp != NULL) {
 		    hour = -(*tzp / 3600);
 		    min = ((abs(*tzp) / 60) % 60);
@@ -3012,16 +2993,9 @@ printf( "EncodeDateTime- day is %d\n", day);
 	    sprintf( (str+5), "/%04d %02d:%02d:%05.2f",
 	      tm->tm_year, tm->tm_hour, tm->tm_min, sec);
 
-	    if (tm->tm_isdst >= 0) {
-#ifdef USE_POSIX_TIME
-#ifdef HAVE_INT_TIMEZONE
-		sprintf( (str+22), " %s", tzname[(tm->tm_isdst > 0)]);
-#else /* !HAVE_INT_TIMEZONE */
-		sprintf( (str+22), " %s", tm->tm_zone);
-#endif
-#else /* !USE_POSIX_TIME */
-		sprintf( (str+22), " %s", CTZName);
-#endif
+	    if ((*tzn != NULL) && (tm->tm_isdst >= 0)) {
+		strcpy( (str+22), " ");
+		strcpy( (str+23), *tzn);
 	    };
 
 	} else {
@@ -3041,16 +3015,9 @@ printf( "EncodeDateTime- day is %d\n", day);
 	    sprintf( (str+10), " %02d:%02d:%05.2f %04d",
 	      tm->tm_hour, tm->tm_min, sec, tm->tm_year);
 
-	    if (tm->tm_isdst >= 0) {
-#ifdef USE_POSIX_TIME
-#ifdef HAVE_INT_TIMEZONE
-		sprintf( (str+27), " %s", tzname[(tm->tm_isdst > 0)]);
-#else
-		sprintf( (str+27), " %s", tm->tm_zone);
-#endif
-#else
-		sprintf( (str+27), " %s", CTZName);
-#endif
+	    if ((*tzn != NULL) && (tm->tm_isdst >= 0)) {
+		strcpy( (str+27), " ");
+		strcpy( (str+28), *tzn);
 	    };
 
 	} else {
@@ -3061,13 +3028,6 @@ printf( "EncodeDateTime- day is %d\n", day);
 
 #ifdef DATEDEBUG
 printf( "EncodeDateTime- date result is %s\n", str);
-#endif
-
-#if defined(DATEDEBUG) && FALSE
-    if (tm->tm_year >= 1000) tm->tm_year -= 1900;
-    tm->tm_mon -= 1;
-    strftime( buf, sizeof(buf), "%y.%m.%d %H:%M:%S %Z", tm);
-printf( "EncodeDateTime- strftime result is %s\n", buf);
 #endif
 
     return(TRUE);
diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c
index 509ce6ce6d4..aece1cdc5ba 100644
--- a/src/backend/utils/adt/float.c
+++ b/src/backend/utils/adt/float.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/utils/adt/float.c,v 1.13 1997/03/12 21:09:11 scrappy Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/utils/adt/float.c,v 1.14 1997/05/11 15:11:38 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -24,7 +24,7 @@
  *	 float4eq, float4ne, float4lt, float4le, float4gt, float4ge
  *	 float8eq, float8ne, float8lt, float8le, float8gt, float8ge
  *	Conversion routines:
- *	 ftod, dtof
+ *	 ftod, dtof, itod, dtoi, i2tod, dtoi2, itof, ftoi, i2tof, ftoi2
  *
  *	Random float8 ops:
  * 	 dround, dtrunc, dsqrt, dcbrt, dpow, dexp, dlog1
@@ -39,6 +39,11 @@
  *	 routines, but then you pay the overhead of converting...)
  *
  * XXX GLUESOME STUFF. FIX IT! -AY '94
+ *
+ *	Added some additional conversion routines and cleaned up
+ *	 a bit of the existing code. Need to change the error checking
+ *	 for calls to pow(), exp() since on some machines (my Linux box
+ *	 included) these routines do not set errno. - tgl 97/05/10
  */
 #include <stdio.h>		/* for sprintf() */
 #include <string.h>
@@ -51,11 +56,21 @@
 #include <math.h>
 
 #include "postgres.h"
+#ifdef HAVE_LIMITS_H
+# include <limits.h>
+#endif
 #include "fmgr.h"
 #include "utils/builtins.h"	/* for ftod() prototype */
 #include "utils/palloc.h"
 
 
+#ifndef SHRT_MAX
+#define SHRT_MAX 32767
+#endif
+#ifndef SHRT_MIN
+#define SHRT_MIN (-32768)
+#endif
+
 #define FORMAT 		'g'	/* use "g" output format as standard format */
 /* not sure what the following should be, but better to make it over-sufficient */
 #define	MAXFLOATWIDTH 	64
@@ -289,7 +304,7 @@ float32 float4um(float32 arg1)
     if (!arg1)
 	return (float32)NULL;
     
-    val = -(*arg1);
+    val = ((*arg1 != 0) ? -(*arg1): *arg1);
     CheckFloat4Val(val);
 
     result = (float32) palloc(sizeof(float32data));
@@ -360,7 +375,7 @@ float64 float8um(float64 arg1)
     if (!arg1)
 	return (float64)NULL;
     
-    val = -(*arg1);
+    val = ((*arg1 != 0)? -(*arg1): *arg1);
     
     CheckFloat8Val(val);
     result = (float64) palloc(sizeof(float64data));
@@ -585,50 +600,50 @@ float64 float8inc(float64 arg1)
 /*
  *	float4{eq,ne,lt,le,gt,ge}	- float4/float4 comparison operations
  */
-long float4eq(float32 arg1, float32 arg2)
+bool float4eq(float32 arg1, float32 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
-    
+	return 0;
+
     return(*arg1 == *arg2);
 }
 
-long float4ne(float32 arg1, float32 arg2)
+bool float4ne(float32 arg1, float32 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
+	return 0;
     
     return(*arg1 != *arg2);
 }
 
-long float4lt(float32 arg1, float32 arg2)
+bool float4lt(float32 arg1, float32 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
+	return 0;
     
     return(*arg1 < *arg2);
 }
 
-long float4le(float32 arg1, float32 arg2)
+bool float4le(float32 arg1, float32 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
+	return 0;
     
     return(*arg1 <= *arg2);
 }
 
-long float4gt(float32 arg1, float32 arg2)
+bool float4gt(float32 arg1, float32 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
+	return 0;
     
     return(*arg1 > *arg2);
 }
 
-long float4ge(float32 arg1, float32 arg2)
+bool float4ge(float32 arg1, float32 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
+	return 0;
     
     return(*arg1 >= *arg2);
 }
@@ -636,50 +651,50 @@ long float4ge(float32 arg1, float32 arg2)
 /*
  *	float8{eq,ne,lt,le,gt,ge}	- float8/float8 comparison operations
  */
-long float8eq(float64 arg1, float64 arg2)
+bool float8eq(float64 arg1, float64 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
+	return 0;
     
     return(*arg1 == *arg2);
 }
 
-long float8ne(float64 arg1, float64 arg2)
+bool float8ne(float64 arg1, float64 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
+	return 0;
     
     return(*arg1 != *arg2);
 }
 
-long float8lt(float64 arg1, float64 arg2)
+bool float8lt(float64 arg1, float64 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
+	return 0;
     
     return(*arg1 < *arg2);
 }
 
-long float8le(float64 arg1, float64 arg2)
+bool float8le(float64 arg1, float64 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
+	return 0;
     
     return(*arg1 <= *arg2);
 }
 
-long float8gt(float64 arg1, float64 arg2)
+bool float8gt(float64 arg1, float64 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
+	return 0;
     
     return(*arg1 > *arg2);
 }
 
-long float8ge(float64 arg1, float64 arg2)
+bool float8ge(float64 arg1, float64 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
+	return 0;
     
     return(*arg1 >= *arg2);
 }
@@ -700,7 +715,7 @@ float64 ftod(float32 num)
     
     if (!num)
 	return (float64)NULL;
-    
+
     result = (float64) palloc(sizeof(float64data));
     
     *result = *num;
@@ -717,10 +732,140 @@ float32 dtof(float64 num)
     
     if (!num)
 	return (float32)NULL;
+
+    CheckFloat4Val(*num);
+
+    result = (float32) palloc(sizeof(float32data));
+
+    *result = *num;
+    return(result);
+}
+
+
+/*
+ *	dtoi		- converts a float8 number to an int4 number
+ */
+int32 dtoi(float64 num)
+{
+    int32	result;
+    
+    if (!num)
+	elog(WARN,"dtoi:  unable to convert null",NULL);
+
+    if ((*num < INT_MIN) || (*num > INT_MAX))
+	elog(WARN,"dtoi:  integer out of range",NULL);
+
+    result = rint(*num);
+    return(result);
+}
+
+
+/*
+ *	dtoi2		- converts a float8 number to an int2 number
+ */
+int16 dtoi2(float64 num)
+{
+    int16	result;
+    
+    if (!num)
+	elog(WARN,"dtoi2:  unable to convert null",NULL);
+
+    if ((*num < SHRT_MIN) || (*num > SHRT_MAX))
+	elog(WARN,"dtoi2:  integer out of range",NULL);
+
+    result = rint(*num);
+    return(result);
+}
+
+
+/*
+ *	itod		- converts an int4 number to a float8 number
+ */
+float64 itod(int32 num)
+{
+    float64	result;
+    
+    result = (float64) palloc(sizeof(float64data));
+    
+    *result = num;
+    return(result);
+}
+
+
+/*
+ *	i2tod		- converts an int2 number to a float8 number
+ */
+float64 i2tod(int16 num)
+{
+    float64	result;
+    
+    result = (float64) palloc(sizeof(float64data));
+    
+    *result = num;
+    return(result);
+}
+
+
+/*
+ *	ftoi		- converts a float8 number to an int4 number
+ */
+int32 ftoi(float32 num)
+{
+    int32	result;
+    
+    if (!num)
+	elog(WARN,"ftoi:  unable to convert null",NULL);
+
+    if ((*num < INT_MIN) || (*num > INT_MAX))
+	elog(WARN,"ftoi:  integer out of range",NULL);
+
+    result = rint(*num);
+    return(result);
+}
+
+
+/*
+ *	ftoi2		- converts a float8 number to an int2 number
+ */
+int16 ftoi2(float32 num)
+{
+    int16	result;
+    
+    if (!num)
+	elog(WARN,"ftoi2:  unable to convert null",NULL);
+
+    if ((*num < SHRT_MIN) || (*num > SHRT_MAX))
+	elog(WARN,"ftoi2:  integer out of range",NULL);
+
+    result = rint(*num);
+    return(result);
+}
+
+
+/*
+ *	itof		- converts an int4 number to a float8 number
+ */
+float32 itof(int32 num)
+{
+    float32	result;
     
     result = (float32) palloc(sizeof(float32data));
     
-    *result = *num;
+    *result = num;
+    return(result);
+}
+
+
+/*
+ *	i2tof		- converts an int2 number to a float8 number
+ */
+float32 i2tof(int16 num)
+{
+    float32	result;
+    
+    result = (float32) palloc(sizeof(float32data));
+    
+    *result = num;
     return(result);
 }
 
@@ -1035,50 +1180,50 @@ float64 float84div(float64 arg1, float32 arg2)
 /*
  *	float48{eq,ne,lt,le,gt,ge}	- float4/float8 comparison operations
  */
-long float48eq(float32 arg1, float64 arg2)
+bool float48eq(float32 arg1, float64 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
+	return 0;
     
     return(*arg1 == (float)*arg2);
 }
 
-long float48ne(float32 arg1, float64 arg2)
+bool float48ne(float32 arg1, float64 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
+	return 0;
     
     return(*arg1 != (float)*arg2);
 }
 
-long float48lt(float32 arg1, float64 arg2)
+bool float48lt(float32 arg1, float64 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
+	return 0;
     
     return(*arg1 < (float)*arg2);
 }
 
-long float48le(float32 arg1, float64 arg2)
+bool float48le(float32 arg1, float64 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
+	return 0;
     
     return(*arg1 <= (float)*arg2);
 }
 
-long float48gt(float32 arg1, float64 arg2)
+bool float48gt(float32 arg1, float64 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
+	return 0;
     
     return(*arg1 > (float)*arg2);
 }
 
-long float48ge(float32 arg1, float64 arg2)
+bool float48ge(float32 arg1, float64 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
+	return 0;
     
     return(*arg1 >= (float)*arg2);
 }
@@ -1086,50 +1231,50 @@ long float48ge(float32 arg1, float64 arg2)
 /*
  *	float84{eq,ne,lt,le,gt,ge}	- float4/float8 comparison operations
  */
-long float84eq(float64 arg1, float32 arg2)
+bool float84eq(float64 arg1, float32 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
+	return 0;
     
     return((float)*arg1 == *arg2);
 }
 
-long float84ne(float64 arg1, float32 arg2)
+bool float84ne(float64 arg1, float32 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
+	return 0;
     
     return((float)*arg1 != *arg2);
 }
 
-long float84lt(float64 arg1, float32 arg2)
+bool float84lt(float64 arg1, float32 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
+	return 0;
     
     return((float)*arg1 < *arg2);
 }
 
-long float84le(float64 arg1, float32 arg2)
+bool float84le(float64 arg1, float32 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
+	return 0;
     
     return((float)*arg1 <= *arg2);
 }
 
-long float84gt(float64 arg1, float32 arg2)
+bool float84gt(float64 arg1, float32 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
+	return 0;
     
     return((float)*arg1 > *arg2);
 }
 
-long float84ge(float64 arg1, float32 arg2)
+bool float84ge(float64 arg1, float32 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
+	return 0;
     
     return((float)*arg1 >= *arg2);
 }
diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c
index 3489f6cf2b5..0b485007ee3 100644
--- a/src/backend/utils/adt/geo_ops.c
+++ b/src/backend/utils/adt/geo_ops.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/utils/adt/geo_ops.c,v 1.5 1997/05/06 07:27:51 thomas Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/utils/adt/geo_ops.c,v 1.6 1997/05/11 15:11:41 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2639,7 +2639,7 @@ poly_path(POLYGON *poly)
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/utils/adt/geo_ops.c,v 1.5 1997/05/06 07:27:51 thomas Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/utils/adt/geo_ops.c,v 1.6 1997/05/11 15:11:41 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2722,7 +2722,7 @@ CIRCLE *circle_in(char *str)
     if (*s == DELIM) s++;
     while (isspace( *s)) s++;
 
-    if (! single_decode( s, &circle->radius, &s))
+    if ((! single_decode( s, &circle->radius, &s)) || (circle->radius < 0))
       elog (WARN, "Bad circle external representation '%s'",str);
 
     while (depth > 0) {
diff --git a/src/backend/utils/adt/nabstime.c b/src/backend/utils/adt/nabstime.c
index 881206fc59f..f091932074e 100644
--- a/src/backend/utils/adt/nabstime.c
+++ b/src/backend/utils/adt/nabstime.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/utils/adt/nabstime.c,v 1.25 1997/04/25 18:40:33 scrappy Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/utils/adt/nabstime.c,v 1.26 1997/05/11 15:11:45 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -519,10 +519,10 @@ datetime_abstime(DateTime *datetime)
 
     } else {
 	if (DATETIME_IS_RELATIVE(*datetime)) {
-	    datetime2tm( SetDateTime(*datetime), NULL, tm, &fsec);
+	    datetime2tm( SetDateTime(*datetime), NULL, tm, &fsec, NULL);
 	    result = tm2abstime( tm, 0);
 
-	} else if (datetime2tm( *datetime, NULL, tm, &fsec) == 0) {
+	} else if (datetime2tm( *datetime, NULL, tm, &fsec, NULL) == 0) {
 	    result = tm2abstime( tm, 0);
 
 	} else {
diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c
index d4fb0759644..e884f7eb08c 100644
--- a/src/backend/utils/adt/timestamp.c
+++ b/src/backend/utils/adt/timestamp.c
@@ -184,7 +184,8 @@ timestamp_datetime(time_t timestamp)
     tm->tm_year += 1900;
     tm->tm_mon += 1;
 
-    *result = tm2datetime(tm, fsec, NULL);
+    if (tm2datetime(tm, fsec, NULL, result) != 0)
+	elog(WARN,"Unable to convert timestamp to datetime",timestamp_out(timestamp));
 
     return(result);
 } /* timestamp_datetime() */
-- 
GitLab