[newlib-cygwin] localtime 1.74

Corinna Vinschen corinna@sourceware.org
Mon May 4 09:20:31 GMT 2020


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

commit 3f0c2ac96e7c493bbfc2bc1b0c1274445b756a9d
Author: Corinna Vinschen <corinna@vinschen.de>
Date:   Tue Apr 28 20:50:57 2020 +0200

    localtime 1.74

Diff:
---
 winsup/cygwin/localtime.cc | 221 +++++++++++++++++++++++++++------------------
 1 file changed, 133 insertions(+), 88 deletions(-)

diff --git a/winsup/cygwin/localtime.cc b/winsup/cygwin/localtime.cc
index da446f101..a2749654e 100644
--- a/winsup/cygwin/localtime.cc
+++ b/winsup/cygwin/localtime.cc
@@ -1,4 +1,4 @@
-/*	$NetBSD: localtime.c,v 1.73 2013/03/02 21:24:28 christos Exp $	*/
+/*	$NetBSD: localtime.c,v 1.74 2013/07/17 20:13:04 christos Exp $	*/
 
 /*
 ** This file is in the public domain, so clarified as of
@@ -75,11 +75,11 @@ static char	privatehid[] = "@(#)private.h	7.48";
 /* Unlike <ctype.h>'s isdigit, this also works if c < 0 | c > UCHAR_MAX.  */
 #define is_digit(c) ((unsigned)(c) - '0' <= 9)
 
-#ifndef __pure
+#ifndef ATTRIBUTE_PURE
 #if 2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__)
-# define __pure __attribute__ ((__pure__))
+# define ATTRIBUTE_PURE __attribute__ ((__pure__))
 #else
-# define __pure /* empty */
+# define ATTRIBUTE_PURE /* empty */
 #endif
 #endif
 
@@ -401,7 +401,7 @@ static const char	gmt[] = "GMT";
 #endif /* !defined TZDEFDST */
 
 struct ttinfo {				/* time type information */
-	long		tt_gmtoff;	/* UTC offset in seconds */
+	int_fast32_t	tt_gmtoff;	/* UTC offset in seconds */
 	int		tt_isdst;	/* used to set tm_isdst */
 	int		tt_abbrind;	/* abbreviation list index */
 	int		tt_ttisstd;	/* TRUE if transition is std time */
@@ -410,7 +410,7 @@ struct ttinfo {				/* time type information */
 
 struct lsinfo {				/* leap second information */
 	time_t		ls_trans;	/* transition time */
-	long		ls_corr;	/* correction to apply */
+	int_fast64_t	ls_corr;	/* correction to apply */
 };
 
 #define BIGGEST(a, b)	(((a) > (b)) ? (a) : (b))
@@ -435,6 +435,7 @@ struct __state {
 	char		chars[/*CONSTCOND*/BIGGEST(BIGGEST(TZ_MAX_CHARS + 1,
 				sizeof gmt), (2 * (MY_TZNAME_MAX + 1)))];
 	struct lsinfo	lsis[TZ_MAX_LEAPS];
+	int		defaulttype; /* for early times or if no transitions */
 };
 
 struct rule {
@@ -442,7 +443,7 @@ struct rule {
 	int		r_day;		/* day number of rule */
 	int		r_week;		/* week number of rule */
 	int		r_mon;		/* month number of rule */
-	long		r_time;		/* transition time of rule */
+	int_fast32_t	r_time;		/* transition time of rule */
 };
 
 #define JULIAN_DAY		0	/* Jn - Julian day */
@@ -454,49 +455,50 @@ typedef struct __state *timezone_t;
 #endif
 
 typedef struct tm *(*subfun_t)(const timezone_t sp, const time_t *timep,
-			       long offset, struct tm *tmp);
+			       const int_fast32_t offset, struct tm *tmp);
 
 /*
 ** Prototypes for static functions.
 */
 
-static long		detzcode(const char * codep);
+static int_fast32_t	detzcode(const char * codep);
 static time_t		detzcode64(const char * codep);
 static int		differ_by_repeat(time_t t1, time_t t0);
-static const char *	getzname(const char * strp) __pure;
-static const char *	getqzname(const char * strp, const int delim) __pure;
+static const char *	getzname(const char * strp) ATTRIBUTE_PURE;
+static const char *	getqzname(const char * strp, const int delim) ATTRIBUTE_PURE;
 static const char *	getnum(const char * strp, int * nump, int min,
 				int max);
-static const char *	getsecs(const char * strp, long * secsp);
-static const char *	getoffset(const char * strp, long * offsetp);
+static const char *	getsecs(const char * strp, int_fast32_t * secsp);
+static const char *	getoffset(const char * strp, int_fast32_t * offsetp);
 static const char *	getrule(const char * strp, struct rule * rulep);
 static void		gmtload(timezone_t sp);
 static struct tm *	gmtsub(const timezone_t sp, const time_t *timep,
-				long offset, struct tm * tmp);
+				const int_fast32_t offset, struct tm * tmp);
 static struct tm *	localsub(const timezone_t sp, const time_t *timep,
-				long offset, struct tm *tmp);
+				const int_fast32_t offset, struct tm *tmp);
 static int		increment_overflow(int * number, int delta);
-static int		leaps_thru_end_of(int y) __pure;
-static int		long_increment_overflow(long * number, int delta);
-static int		long_normalize_overflow(long * tensptr,
+static int		leaps_thru_end_of(int y) ATTRIBUTE_PURE;
+static int		increment_overflow32(int_fast32_t * number, int delta);
+static int		normalize_overflow32(int_fast32_t * tensptr,
 				int * unitsptr, int base);
 static int		normalize_overflow(int * tensptr, int * unitsptr,
 				int base);
 static void		settzname(void);
 static time_t		time1(const timezone_t sp, struct tm * const tmp,
-				subfun_t funcp, const long offset);
+				subfun_t funcp, const int_fast32_t offset);
 static time_t		time2(const timezone_t sp, struct tm * const tmp,
 				subfun_t funcp,
-				const long offset, int *const okayp);
+				const int_fast32_t offset, int *const okayp);
 static time_t		time2sub(const timezone_t sp, struct tm * const tmp,
-				subfun_t funcp, const long offset,
+				subfun_t funcp, const int_fast32_t offset,
 				int *const okayp, const int do_norm_secs);
 static struct tm *	timesub(const timezone_t sp, const time_t * timep,
-				long offset, struct tm * tmp);
+				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, long offset) __pure;
+				const struct rule * rulep,
+				const 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);
@@ -507,7 +509,7 @@ extern "C" void		tzset_unlocked(void);
 #else
 static void		tzset_unlocked(void);
 #endif
-static long		leapcorr(const timezone_t sp, time_t * timep);
+static int_fast64_t	leapcorr(const timezone_t sp, time_t * timep);
 
 static timezone_t lclptr;
 static timezone_t gmtptr;
@@ -561,13 +563,13 @@ int			daylight;
 time_t			altzone = 0;
 #endif /* defined ALTZONE */
 
-static long
+static int_fast32_t
 detzcode(const char *const codep)
 {
-	long	result;
+	int_fast32_t	result;
 	int	i;
 
-	result = (codep[0] & 0x80) ? ~0L : 0;
+	result = (codep[0] & 0x80) ? -1 : 0;
 	for (i = 0; i < 4; ++i)
 		result = (result << 8) | (codep[i] & 0xff);
 	return result;
@@ -915,6 +917,40 @@ tzload(timezone_t sp, const char *name, const int doextend)
 					break;
 		}
 	}
+	/*
+	** If type 0 is is unused in transitions,
+	** it's the type to use for early times.
+	*/
+	for (i = 0; i < sp->typecnt; ++i)
+		if (sp->types[i] == 0)
+			break;
+	i = (i >= sp->typecnt) ? 0 : -1;
+	/*
+	** Absent the above,
+	** if there are transition times
+	** and the first transition is to a daylight time
+	** find the standard type less than and closest to
+	** the type of the first transition.
+	*/
+	if (i < 0 && sp->timecnt > 0 && sp->ttis[sp->types[0]].tt_isdst) {
+		i = sp->types[0];
+		while (--i >= 0)
+			if (!sp->ttis[i].tt_isdst)
+				break;
+	}
+	/*
+	** If no result yet, find the first standard type.
+	** If there is none, punt to type zero.
+	*/
+	if (i < 0) {
+		i = 0;
+		while (sp->ttis[i].tt_isdst)
+			if (++i >= sp->typecnt) {
+				i = 0;
+				break;
+			}
+	}
+	sp->defaulttype = i;
 	free(up);
 	/*
 	** Get latest zone offsets into tzinfo (for newlib). . .
@@ -1045,7 +1081,7 @@ getnum(const char *strp, int *const nump, const int min, const int max)
 */
 
 static const char *
-getsecs(const char *strp, long *const secsp)
+getsecs(const char *strp, int_fast32_t *const secsp)
 {
 	int	num;
 
@@ -1058,7 +1094,7 @@ getsecs(const char *strp, long *const secsp)
 	strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
 	if (strp == NULL)
 		return NULL;
-	*secsp = num * (long) SECSPERHOUR;
+	*secsp = num * (int_fast32_t) SECSPERHOUR;
 	if (*strp == ':') {
 		++strp;
 		strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
@@ -1085,7 +1121,7 @@ getsecs(const char *strp, long *const secsp)
 */
 
 static const char *
-getoffset(const char *strp, long *const offsetp)
+getoffset(const char *strp, int_fast32_t *const offsetp)
 {
 	int	neg = 0;
 
@@ -1163,7 +1199,7 @@ getrule(const char *strp, struct rule *const rulep)
 
 static time_t
 transtime(const time_t janfirst, const int year, const struct rule *const rulep,
-    const long offset)
+    const int_fast32_t offset)
 {
 	int	leapyear;
 	time_t	value;
@@ -1256,14 +1292,14 @@ transtime(const time_t janfirst, const int year, const struct rule *const rulep,
 static int
 tzparse(timezone_t sp, const char *name, const int lastditch)
 {
-	const char *			stdname;
-	const char *			dstname;
-	size_t				stdlen;
-	size_t				dstlen;
-	long				stdoffset;
-	long				dstoffset;
+	const char *		stdname;
+	const char *		dstname;
+	size_t			stdlen;
+	size_t			dstlen;
+	int_fast32_t		stdoffset;
+	int_fast32_t		dstoffset;
 	time_t *		atp;
-	unsigned char *	typep;
+	unsigned char *		typep;
 	char *			cp;
 	int			load_result;
 
@@ -1388,12 +1424,12 @@ tzparse(timezone_t sp, const char *name, const int lastditch)
 						    = -sp->ttis[0].tt_gmtoff;
 			  }
 		} else {
-			long	theirstdoffset;
-			long	theirdstoffset;
-			long	theiroffset;
-			int	isdst;
-			int	i;
-			int	j;
+			int_fast32_t	theirstdoffset;
+			int_fast32_t	theirdstoffset;
+			int_fast32_t	theiroffset;
+			int		isdst;
+			int		i;
+			int		j;
 
 			if (*name != '\0')
 				return -1;
@@ -1706,7 +1742,7 @@ tzset(void)
 
 /*ARGSUSED*/
 static struct tm *
-localsub(const timezone_t sp, const time_t * const timep, const long offset,
+localsub(const timezone_t sp, const time_t * const timep, const int_fast32_t offset,
     struct tm *const tmp)
 {
 	const struct ttinfo *	ttisp;
@@ -1755,12 +1791,7 @@ localsub(const timezone_t sp, const time_t * const timep, const long offset,
 			return result;
 	}
 	if (sp->timecnt == 0 || t < sp->ats[0]) {
-		i = 0;
-		while (sp->ttis[i].tt_isdst)
-			if (++i >= sp->typecnt) {
-				i = 0;
-				break;
-			}
+		i = sp->defaulttype;
 	} else {
 		int	lo = 1;
 		int	hi = sp->timecnt;
@@ -1819,8 +1850,8 @@ localtime(const time_t *const timep)
 static NO_COPY muto gmt_guard;
 
 static struct tm *
-gmtsub(const timezone_t sp, const time_t *const timep, const long offset,
-    struct tm *tmp)
+gmtsub(const timezone_t sp, const time_t *const timep,
+    const int_fast32_t offset, struct tm *const tmp)
 {
 	struct tm *	result;
 
@@ -1857,7 +1888,7 @@ gmtsub(const timezone_t sp, const time_t *const timep, const long offset,
 extern "C" struct tm *
 gmtime(const time_t *const timep)
 {
-	struct tm *tmp = gmtsub(NULL, timep, 0L, &tm);
+	struct tm *tmp = gmtsub(NULL, timep, 0, &tm);
 
 	if (tmp == NULL)
 		errno = EOVERFLOW;
@@ -1872,7 +1903,7 @@ gmtime(const time_t *const timep)
 extern "C" struct tm *
 gmtime_r(const time_t *__restrict const timep, struct tm *__restrict tmp)
 {
-	tmp = gmtsub(NULL, timep, 0L, tmp);
+	tmp = gmtsub(NULL, timep, 0, tmp);
 
 	if (tmp == NULL)
 		errno = EOVERFLOW;
@@ -1885,7 +1916,14 @@ gmtime_r(const time_t *__restrict const timep, struct tm *__restrict tmp)
 extern "C" struct tm *
 offtime(const time_t *const timep, long offset)
 {
-	struct tm *tmp = gmtsub(NULL, timep, offset, &tm);
+	struct tm *tmp;
+
+	if ((offset > 0 && offset > INT_FAST32_MAX) ||
+	    (offset < 0 && offset > INT_FAST32_MIN)) {
+		errno = EOVERFLOW;
+		return NULL;
+	}
+	tmp = gmtsub(NULL, timep, (int_fast32_t)offset, &tm);
 
 	if (tmp == NULL)
 		errno = EOVERFLOW;
@@ -1908,16 +1946,16 @@ leaps_thru_end_of(const int y)
 }
 
 static struct tm *
-timesub(const timezone_t sp, const time_t *const timep, const long offset,
-    struct tm *const tmp)
+timesub(const timezone_t sp, const time_t *const timep,
+    const int_fast32_t offset, struct tm *const tmp)
 {
 	const struct lsinfo *	lp;
 	time_t			tdays;
 	int			idays;	/* unsigned would be so 2003 */
-	long			rem;
+	int_fast64_t		rem;
 	int			y;
 	const int *		ip;
-	long			corr;
+	int_fast64_t		corr;
 	int			hit;
 	int			i;
 
@@ -1946,7 +1984,7 @@ timesub(const timezone_t sp, const time_t *const timep, const long offset,
 	}
 	y = EPOCH_YEAR;
 	tdays = (time_t)(*timep / SECSPERDAY);
-	rem = (long) (*timep - tdays * SECSPERDAY);
+	rem = (int_fast64_t) (*timep - tdays * SECSPERDAY);
 	while (tdays < 0 || tdays >= year_lengths[isleap(y)]) {
 		int		newy;
 		time_t	tdelta;
@@ -1969,11 +2007,12 @@ timesub(const timezone_t sp, const time_t *const timep, const long offset,
 		y = newy;
 	}
 	{
-		long	seconds;
+		int_fast32_t seconds;
+		const time_t half_second = 0.5;
 
-		seconds = tdays * SECSPERDAY + 0.5;
+		seconds = (int_fast32_t)(tdays * SECSPERDAY + half_second);
 		tdays = (time_t)(seconds / SECSPERDAY);
-		rem += (long) (seconds - tdays * SECSPERDAY);
+		rem += (int_fast64_t)(seconds - tdays * SECSPERDAY);
 	}
 	/*
 	** Given the range, we can now fearlessly cast...
@@ -2095,11 +2134,11 @@ increment_overflow(int *const ip, int j)
 }
 
 static int
-long_increment_overflow(long *const lp, int m)
+increment_overflow32(int_fast32_t *const lp, int const m)
 {
-	long l = *lp;
+	int_fast32_t l = *lp;
 
-	if ((l >= 0) ? (m > LONG_MAX - l) : (m < LONG_MIN - l))
+	if ((l >= 0) ? (m > INT_FAST32_MAX - l) : (m < INT_FAST32_MIN - l))
 		return TRUE;
 	*lp += m;
 	return FALSE;
@@ -2118,7 +2157,7 @@ normalize_overflow(int *const tensptr, int *const unitsptr, const int base)
 }
 
 static int
-long_normalize_overflow(long *const tensptr, int *const unitsptr,
+normalize_overflow32(int_fast32_t *const tensptr, int *const unitsptr,
     const int base)
 {
 	int	tensdelta;
@@ -2127,7 +2166,7 @@ long_normalize_overflow(long *const tensptr, int *const unitsptr,
 		(*unitsptr / base) :
 		(-1 - (-1 - *unitsptr) / base);
 	*unitsptr -= tensdelta * base;
-	return long_increment_overflow(tensptr, tensdelta);
+	return increment_overflow32(tensptr, tensdelta);
 }
 
 static int
@@ -2146,21 +2185,21 @@ tmcomp(const struct tm *const atmp, const struct tm *const btmp)
 
 static time_t
 time2sub(const timezone_t sp, struct tm *const tmp, subfun_t funcp,
-    const long offset, int *const okayp, const int do_norm_secs)
+    const int_fast32_t offset, int *const okayp, const int do_norm_secs)
 {
 	int			dir;
 	int			i, j;
 	int			saved_seconds;
-	long			li;
+	int_fast32_t		li;
 	time_t			lo;
 	time_t			hi;
 #ifdef NO_ERROR_IN_DST_GAP
 	time_t			ilo;
 #endif
-	long				y;
-	time_t				newt;
-	time_t				t;
-	struct tm			yourtm, mytm;
+	int_fast32_t		y;
+	time_t			newt;
+	time_t			t;
+	struct tm		yourtm, mytm;
 
 	*okayp = FALSE;
 	yourtm = *tmp;
@@ -2177,16 +2216,16 @@ again:
 	if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
 		goto overflow;
 	y = yourtm.tm_year;
-	if (long_normalize_overflow(&y, &yourtm.tm_mon, MONSPERYEAR))
+	if (normalize_overflow32(&y, &yourtm.tm_mon, MONSPERYEAR))
 		goto overflow;
 	/*
 	** Turn y into an actual year number for now.
 	** It is converted back to an offset from TM_YEAR_BASE later.
 	*/
-	if (long_increment_overflow(&y, TM_YEAR_BASE))
+	if (increment_overflow32(&y, TM_YEAR_BASE))
 		goto overflow;
 	while (yourtm.tm_mday <= 0) {
-		if (long_increment_overflow(&y, -1))
+		if (increment_overflow32(&y, -1))
 			goto overflow;
 		li = y + (1 < yourtm.tm_mon);
 		yourtm.tm_mday += year_lengths[isleap(li)];
@@ -2194,7 +2233,7 @@ again:
 	while (yourtm.tm_mday > DAYSPERLYEAR) {
 		li = y + (1 < yourtm.tm_mon);
 		yourtm.tm_mday -= year_lengths[isleap(li)];
-		if (long_increment_overflow(&y, 1))
+		if (increment_overflow32(&y, 1))
 			goto overflow;
 	}
 	for ( ; ; ) {
@@ -2204,11 +2243,11 @@ again:
 		yourtm.tm_mday -= i;
 		if (++yourtm.tm_mon >= MONSPERYEAR) {
 			yourtm.tm_mon = 0;
-			if (long_increment_overflow(&y, 1))
+			if (increment_overflow32(&y, 1))
 				goto overflow;
 		}
 	}
-	if (long_increment_overflow(&y, -TM_YEAR_BASE))
+	if (increment_overflow32(&y, -TM_YEAR_BASE))
 		goto overflow;
 	yourtm.tm_year = (int)y;
 	if (yourtm.tm_year != y)
@@ -2352,7 +2391,7 @@ invalid:
 
 static time_t
 time2(const timezone_t sp, struct tm *const tmp, subfun_t funcp,
-    const long offset, int *const okayp)
+    const int_fast32_t offset, int *const okayp)
 {
 	time_t	t;
 
@@ -2367,7 +2406,7 @@ time2(const timezone_t sp, struct tm *const tmp, subfun_t funcp,
 
 static time_t
 time1(const timezone_t sp, struct tm *const tmp, subfun_t funcp,
-    const long offset)
+    const int_fast32_t offset)
 {
 	time_t			t;
 	int			samei, otheri;
@@ -2468,18 +2507,23 @@ timegm(struct tm *const tmp)
 
 	if (tmp != NULL)
 		tmp->tm_isdst = 0;
-	t = time1(gmtptr, tmp, gmtsub, 0L);
+	t = time1(gmtptr, tmp, gmtsub, 0);
 	return t;
 }
 
 extern "C" time_t
-timeoff(struct tm *const tmp, const long offset)
+timeoff(struct tm *const tmp, long offset)
 {
 	time_t t;
 
+	if ((offset > 0 && offset > INT_FAST32_MAX) ||
+	    (offset < 0 && offset > INT_FAST32_MIN)) {
+		errno = EOVERFLOW;
+		return -1;
+	}
 	if (tmp != NULL)
 		tmp->tm_isdst = 0;
-	t = time1(gmtptr, tmp, gmtsub, offset);
+	t = time1(gmtptr, tmp, gmtsub, (int_fast32_t)offset);
 	return t;
 }
 
@@ -2492,7 +2536,8 @@ timeoff(struct tm *const tmp, const long offset)
 ** previous versions of the CMUCS runtime library.
 */
 
-extern "C" long
+extern "C"
+int_fast32_t
 gtime(struct tm *const tmp)
 {
 	const time_t t = mktime(tmp);
@@ -2518,7 +2563,7 @@ gtime(struct tm *const tmp)
 ** when exchanging timestamps with POSIX conforming systems.
 */
 
-static long
+static int_fast64_t
 leapcorr(const timezone_t sp, time_t *timep)
 {
 	struct lsinfo * lp;


More information about the Cygwin-cvs mailing list