public inbox for cygwin-cvs@sourceware.org
help / color / mirror / Atom feed
* [newlib-cygwin] localtime 1.81
@ 2020-05-04  9:21 Corinna Vinschen
  0 siblings, 0 replies; only message in thread
From: Corinna Vinschen @ 2020-05-04  9:21 UTC (permalink / raw)
  To: cygwin-cvs

https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=3003c3dacd157c11f5e035bc18bdd30631800720

commit 3003c3dacd157c11f5e035bc18bdd30631800720
Author: Corinna Vinschen <corinna@vinschen.de>
Date:   Tue Apr 28 21:26:45 2020 +0200

    localtime 1.81

Diff:
---
 winsup/cygwin/localtime.cc | 205 ++++++++++++++++++++++-----------------------
 1 file changed, 101 insertions(+), 104 deletions(-)

diff --git a/winsup/cygwin/localtime.cc b/winsup/cygwin/localtime.cc
index b0a1a4f2d..7324fbd98 100644
--- a/winsup/cygwin/localtime.cc
+++ b/winsup/cygwin/localtime.cc
@@ -1,4 +1,4 @@
-/*	$NetBSD: localtime.c,v 1.80 2013/12/13 10:37:24 christos Exp $	*/
+/*	$NetBSD: localtime.c,v 1.81 2013/12/26 18:34:28 christos Exp $	*/
 
 /*
 ** This file is in the public domain, so clarified as of
@@ -88,7 +88,7 @@ static char	privatehid[] = "@(#)private.h	7.48";
 #if 0
 static char	elsieid[] = "@(#)localtime.cc	8.17";
 #else
-__RCSID("$NetBSD: localtime.c,v 1.80 2013/12/13 10:37:24 christos Exp $");
+__RCSID("$NetBSD: localtime.c,v 1.81 2013/12/26 18:34:28 christos Exp $");
 #endif
 
 /*
@@ -480,7 +480,7 @@ typedef struct tm *(*subfun_t)(const timezone_t sp, const time_t *timep,
 */
 
 static int_fast32_t	detzcode(const char * codep);
-static time_t		detzcode64(const char * codep);
+static int_fast64_t	detzcode64(const char * codep);
 static int		differ_by_repeat(time_t t1, time_t t0);
 static const char *	getzname(const char * strp) ATTRIBUTE_PURE;
 static const char *	getqzname(const char * strp, const int delim) ATTRIBUTE_PURE;
@@ -496,6 +496,7 @@ static struct tm *	localsub(const timezone_t sp, const time_t *timep,
 				const int_fast32_t offset, struct tm *tmp);
 static int		increment_overflow(int * number, int delta);
 static int		increment_overflow32(int_fast32_t * number, int delta);
+static int		increment_overflow_time(time_t *t, int_fast32_t delta);
 static int		leaps_thru_end_of(int y) ATTRIBUTE_PURE;
 static int		normalize_overflow(int * tensptr, int * unitsptr,
 				int base);
@@ -514,9 +515,9 @@ static struct tm *	timesub(const timezone_t sp, const time_t * timep,
 				const int_fast32_t offset, struct tm * tmp);
 static int		tmcomp(const struct tm * atmp,
 				const struct tm * btmp);
-static time_t		transtime(time_t janfirst, int year,
-				const struct rule * rulep,
-				const int_fast32_t offset) ATTRIBUTE_PURE;
+static int_fast32_t	transtime(int year, const struct rule * rulep,
+				  int_fast32_t offset)
+  ATTRIBUTE_PURE;
 static int		typesequiv(const timezone_t sp, int a, int b);
 static int		tzload(timezone_t sp, const char * name,
 				int doextend);
@@ -578,7 +579,7 @@ int			daylight;
 #endif /* defined USG_COMPAT */
 
 #ifdef ALTZONE
-time_t			altzone = 0;
+long			altzone = 0;
 #endif /* defined ALTZONE */
 
 static int_fast32_t
@@ -593,15 +594,15 @@ detzcode(const char *const codep)
 	return result;
 }
 
-static time_t
+static int_fast64_t
 detzcode64(const char *const codep)
 {
-	time_t	result;
+	int_fast64_t	result;
 	int	i;
 
-	result = (time_t)((codep[0] & 0x80) ? (~(int_fast64_t) 0) : 0);
+	result = (codep[0] & 0x80) ? -1 : 0;
 	for (i = 0; i < 8; ++i)
-		result = result * 256 + (codep[i] & 0xff);
+		result = (result << 8) | (codep[i] & 0xff);
 	return result;
 }
 
@@ -742,6 +743,7 @@ tzload(timezone_t sp, const char *name, const int doextend)
 	for (stored = 4; stored <= 8; stored *= 2) {
 		int		ttisstdcnt;
 		int		ttisgmtcnt;
+		int		timecnt;
 
 		ttisstdcnt = (int) detzcode(up->tzhead.tzh_ttisstdcnt);
 		ttisgmtcnt = (int) detzcode(up->tzhead.tzh_ttisgmtcnt);
@@ -766,15 +768,36 @@ tzload(timezone_t sp, const char *name, const int doextend)
 			ttisstdcnt +			/* ttisstds */
 			ttisgmtcnt)			/* ttisgmts */
 				goto oops;
+		timecnt = 0;
 		for (i = 0; i < sp->timecnt; ++i) {
-			sp->ats[i] = (time_t)((stored == 4) ?
-				detzcode(p) : detzcode64(p));
+			int_fast64_t at
+			  = stored == 4 ? detzcode(p) : detzcode64(p);
+			sp->types[i] = ((TYPE_SIGNED(time_t)
+					 ? time_t_min <= at
+					 : 0 <= at)
+					&& at <= time_t_max);
+			if (sp->types[i]) {
+				if (i && !timecnt && at != time_t_min) {
+					/*
+					** Keep the earlier record, but tweak
+					** it so that it starts with the
+					** minimum time_t value.
+					*/
+					sp->types[i - 1] = 1;
+					sp->ats[timecnt++] = time_t_min;
+				}
+				//_DIAGASSERT(__type_fit(time_t, at));
+				sp->ats[timecnt++] = (time_t)at;
+			}
 			p += stored;
 		}
+		timecnt = 0;
 		for (i = 0; i < sp->timecnt; ++i) {
-			sp->types[i] = (unsigned char) *p++;
-			if (sp->types[i] >= sp->typecnt)
+			unsigned char typ = *p++;
+			if (sp->typecnt <= typ)
 				goto oops;
+			if (sp->types[i])
+				sp->types[timecnt++] = typ;
 		}
 		for (i = 0; i < sp->typecnt; ++i) {
 			struct ttinfo *	ttisp;
@@ -830,44 +853,6 @@ tzload(timezone_t sp, const char *name, const int doextend)
 			}
 		}
 		/*
-		** Out-of-sort ats should mean we're running on a
-		** signed time_t system but using a data file with
-		** unsigned values (or vice versa).
-		*/
-		for (i = 0; i < sp->timecnt; ++i)
-			if ((i < sp->timecnt - 1 &&
-			    sp->ats[i] > sp->ats[i + 1]) ||
-			    (i == sp->timecnt - 1 && !TYPE_SIGNED(time_t) &&
-			    sp->ats[i] >
-			    ((stored == 4) ? INT32_MAX : INT64_MAX))) {
-				if (TYPE_SIGNED(time_t)) {
-					/*
-					** Ignore the end (easy).
-					*/
-					sp->timecnt = i + 1;
-				} else {
-					/*
-					** Ignore the beginning (harder).
-					*/
-					int	j;
-
-					/*
-					** Keep the record right before the
-					** epoch boundary,
-					** but tweak it so that it starts
-					** right with the epoch
-					** (thanks to Doug Bailey).
-					*/
-					sp->ats[i] = 0;
-					for (j = 0; j + i < sp->timecnt; ++j) {
-						sp->ats[j] = sp->ats[j + i];
-						sp->types[j] = sp->types[j + i];
-					}
-					sp->timecnt = j;
-				}
-				break;
-			}
-		/*
 		** If this is an old file, we're done.
 		*/
 		if (up->tzhead.tzh_version[0] == '\0')
@@ -876,9 +861,9 @@ tzload(timezone_t sp, const char *name, const int doextend)
 		for (i = 0; i < nread; ++i)
 			up->buf[i] = p[i];
 		/*
-		** If this is a narrow time_t system, we're done.
+		** If this is a signed narrow time_t system, we're done.
 		*/
-		if (stored >= (int) sizeof(time_t))
+		if (TYPE_SIGNED(time_t) && stored >= (int) sizeof(time_t))
 			break;
 	}
 	if (doextend && nread > 2 &&
@@ -1207,17 +1192,16 @@ getrule(const char *strp, struct rule *const rulep)
 }
 
 /*
-** Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the
-** year, a rule, and the offset from UT at the time that rule takes effect,
-** calculate the Epoch-relative time that rule takes effect.
+** Given a year, a rule, and the offset from UT at the time that rule takes
+** effect, calculate the year-relative time that rule takes effect.
 */
 
-static time_t
-transtime(const time_t janfirst, const int year, const struct rule *const rulep,
-    const int_fast32_t offset)
+static int_fast32_t
+transtime(const int year, const struct rule *const rulep,
+	  const int_fast32_t offset)
 {
 	int	leapyear;
-	time_t	value;
+	int_fast32_t	value;
 	int	i;
 	int		d, m1, yy0, yy1, yy2, dow;
 
@@ -1233,7 +1217,7 @@ transtime(const time_t janfirst, const int year, const struct rule *const rulep,
 		** add SECSPERDAY times the day number-1 to the time of
 		** January 1, midnight, to get the day.
 		*/
-		value = (time_t)(janfirst + (rulep->r_day - 1) * SECSPERDAY);
+		value = (rulep->r_day - 1) * SECSPERDAY;
 		if (leapyear && rulep->r_day >= 60)
 			value += SECSPERDAY;
 		break;
@@ -1244,16 +1228,13 @@ transtime(const time_t janfirst, const int year, const struct rule *const rulep,
 		** Just add SECSPERDAY times the day number to the time of
 		** January 1, midnight, to get the day.
 		*/
-		value = (time_t)(janfirst + rulep->r_day * SECSPERDAY);
+		value = rulep->r_day * SECSPERDAY;
 		break;
 
 	case MONTH_NTH_DAY_OF_WEEK:
 		/*
 		** Mm.n.d - nth "dth day" of month m.
 		*/
-		value = janfirst;
-		for (i = 0; i < rulep->r_mon - 1; ++i)
-			value += (time_t)(mon_lengths[leapyear][i] * SECSPERDAY);
 
 		/*
 		** Use Zeller's Congruence to get day-of-week of first day of
@@ -1286,17 +1267,19 @@ transtime(const time_t janfirst, const int year, const struct rule *const rulep,
 		/*
 		** "d" is the day-of-month (zero-origin) of the day we want.
 		*/
-		value += (time_t)(d * SECSPERDAY);
+		value = d * SECSPERDAY;
+		for (i = 0; i < rulep->r_mon - 1; ++i)
+			value += mon_lengths[leapyear][i] * SECSPERDAY;
 		break;
 	}
 
 	/*
-	** "value" is the Epoch-relative time of 00:00:00 UT on the day in
-	** question. To get the Epoch-relative time of the specified local
+	** "value" is the year-relative time of 00:00:00 UT on the day in
+	** question. To get the year-relative time of the specified local
 	** time on that day, add the transition time and the current offset
 	** from UT.
 	*/
-	return (time_t)(value + rulep->r_time + offset);
+	return value + rulep->r_time + offset;
 }
 
 /*
@@ -1313,8 +1296,6 @@ tzparse(timezone_t sp, const char *name, const int lastditch)
 	size_t			dstlen;
 	int_fast32_t		stdoffset;
 	int_fast32_t		dstoffset;
-	time_t *		atp;
-	unsigned char *		typep;
 	char *			cp;
 	int			load_result;
 
@@ -1373,9 +1354,8 @@ tzparse(timezone_t sp, const char *name, const int lastditch)
 			struct rule	end;
 			int		year;
 			int		yearlim;
+			int		timecnt;
 			time_t		janfirst;
-			time_t		starttime;
-			time_t		endtime;
 
 			++name;
 			if ((name = getrule(name, &start)) == NULL)
@@ -1397,43 +1377,44 @@ tzparse(timezone_t sp, const char *name, const int lastditch)
 			sp->ttis[1].tt_gmtoff = -stdoffset;
 			sp->ttis[1].tt_isdst = 0;
 			sp->ttis[1].tt_abbrind = 0;
-			atp = sp->ats;
-			typep = sp->types;
+			timecnt = 0;
 			janfirst = 0;
 			sp->timecnt = 0;
 			yearlim = EPOCH_YEAR + YEARSPERREPEAT;
 			for (year = EPOCH_YEAR; year < yearlim; year++) {
-				int_fast32_t yearsecs;
-
-				starttime = transtime(janfirst, year, &start,
-					stdoffset);
-				endtime = transtime(janfirst, year, &end,
-					dstoffset);
-				yearsecs = (year_lengths[isleap(year)]
-					    * SECSPERDAY);
-				if (starttime > endtime
+				int_fast32_t
+				  starttime = transtime(year, &start, stdoffset),
+				  endtime = transtime(year, &end, dstoffset);
+				int_fast32_t
+				  yearsecs = (year_lengths[isleap(year)]
+					      * SECSPERDAY);
+				int reversed = endtime < starttime;
+				if (reversed) {
+					int_fast32_t swap = starttime;
+					starttime = endtime;
+					endtime = swap;
+				}
+				if (reversed
 				    || (starttime < endtime
 					&& (endtime - starttime
 					    < (yearsecs
 					       + (stdoffset - dstoffset))))) {
-					if (&sp->ats[TZ_MAX_TIMES - 2] < atp)
+					if (TZ_MAX_TIMES - 2 < timecnt)
 						break;
 					yearlim = year + YEARSPERREPEAT + 1;
-					if (starttime > endtime) {
-						*atp++ = endtime;
-						*typep++ = 1;	/* DST ends */
-						*atp++ = starttime;
-						*typep++ = 0;	/* DST begins */
-					} else {
-						*atp++ = starttime;
-						*typep++ = 0;	/* DST begins */
-						*atp++ = endtime;
-						*typep++ = 1;	/* DST ends */
-					}
+					sp->ats[timecnt] = janfirst;
+					if (increment_overflow_time
+					    (&sp->ats[timecnt], starttime))
+						break;
+					sp->types[timecnt++] = reversed;
+					sp->ats[timecnt] = janfirst;
+					if (increment_overflow_time
+					    (&sp->ats[timecnt], endtime))
+						break;
+					sp->types[timecnt++] = !reversed;
 				}
-				if (time_t_max - janfirst < yearsecs)
+				if (increment_overflow_time(&janfirst, yearsecs))
 					break;
-				janfirst += (time_t)yearsecs;
 			}
 			/*
 			** Get zone offsets into tzinfo (for newlib). . .
@@ -1445,9 +1426,8 @@ tzparse(timezone_t sp, const char *name, const int lastditch)
 			    __gettzinfo ()->__tzrule[1].offset
 						    = -sp->ttis[0].tt_gmtoff;
 			  }
-			//_DIAGASSERT(__type_fit(int, atp - sp->ats));
-			sp->timecnt = (int)(atp - sp->ats);
-			if (!sp->timecnt)
+			sp->timecnt = timecnt;
+			if (!timecnt)
 				sp->typecnt = 1;	/* Perpetual DST.  */
 		} else {
 			int_fast32_t	theirstdoffset;
@@ -2013,7 +1993,8 @@ timesub(const timezone_t sp, const time_t *const timep,
 		if (! ((! TYPE_SIGNED(time_t) || INT_MIN <= tdelta)
 		       && tdelta <= INT_MAX))
 			return NULL;
-		idelta = tdelta;
+		//_DIAGASSERT(__type_fit(int, tdelta));
+		idelta = (int)tdelta;
 		if (idelta == 0)
 			idelta = (tdays < 0) ? -1 : 1;
 		newy = y;
@@ -2162,6 +2143,22 @@ increment_overflow32(int_fast32_t *const lp, int const m)
 	return FALSE;
 }
 
+static int
+increment_overflow_time(time_t *tp, int_fast32_t j)
+{
+	/*
+	** This is like
+	** 'if (! (time_t_min <= *tp + j && *tp + j <= time_t_max)) ...',
+	** except that it does the right thing even if *tp + j would overflow.
+	*/
+	if (! (j < 0
+	       ? (TYPE_SIGNED(time_t) ? time_t_min - j <= *tp : -1 - j < *tp)
+	       : *tp <= time_t_max - j))
+		return TRUE;
+	*tp += j;
+	return FALSE;
+}
+
 static int
 normalize_overflow(int *const tensptr, int *const unitsptr, const int base)
 {


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2020-05-04  9:21 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-04  9:21 [newlib-cygwin] localtime 1.81 Corinna Vinschen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).