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

commit 72865dc2a34903f88615f4282f157a1b62973770
Author: Corinna Vinschen <[email protected]>
Date:   Mon May 4 11:22:54 2020 +0200

    Revert "localtime define _DIAGASSERT" and followups affecting localtime.cc
    
    This reverts commits 453b6d17bf0581e55258c5eb6dc7afbad1927cab,
                         489a47d6036660a6cbab1addfb2b7678c0de8bf2,
                         3003c3dacd157c11f5e035bc18bdd30631800720,
                         9e29639ca01208a4a8bac5b9d0f6491b34b1017e,
                         a40701c7dc9970457a19728e371c71e7501057e7,
                         0a41de2725dbf2f325e55016d85d76560845ff8d,
                         b8aa5f7a0fe70a9a53fe4019227271a78758ae67,
                         0f4bda879283eaf013f86dd80e5588721a811ea0,
                         65bf580752db7ac01ecae19dc56aa26ea34f5e47,
                         3f0c2ac96e7c493bbfc2bc1b0c1274445b756a9d,
                         76d4d40b8b23d046473a5946cf6b83faa36ae7be,
                         f2e06d8af5f390d81b64375a69ca834ca19d6029.

Diff:
---
 winsup/cygwin/localtime.cc | 538 ++++++++++++++++++++-------------------------
 1 file changed, 236 insertions(+), 302 deletions(-)

diff --git a/winsup/cygwin/localtime.cc b/winsup/cygwin/localtime.cc
index ebb2d42f0..010376637 100644
--- a/winsup/cygwin/localtime.cc
+++ b/winsup/cygwin/localtime.cc
@@ -1,10 +1,4 @@
-/*     $NetBSD: localtime.c,v 1.82 2014/05/13 16:33:56 christos Exp $  */
-
-/*
-** This file is in the public domain, so clarified as of
-** 1996-06-05 by Arthur David Olson.
-*/
-/* Temporarily merged private.h and tzfile.h for ease of management - DJ */
+/*     $NetBSD: localtime.c,v 1.72 2012/10/28 19:02:29 christos Exp $  */
 
 /* Don't reformat the code arbitrarily.
 
@@ -12,6 +6,12 @@
    versions.  The purpose is to simplify subsequent diffs to the NetBSD
    version, should the need arise again at one point. */
 
+/*
+** This file is in the public domain, so clarified as of
+** 1996-06-05 by Arthur David Olson.
+*/
+/* Temporarily merged private.h and tzfile.h for ease of management - DJ */
+
 #include "winsup.h"
 #include "cygerrno.h"
 #include "sync.h"
@@ -71,26 +71,16 @@ static char privatehid[] = "@(#)private.h   7.48";
 #include "limits.h"    /* for CHAR_BIT */
 #include "stdlib.h"
 #include "unistd.h"    /* for F_OK and R_OK */
-#if 0
-#include <assert.h>
-#else
-#define _DIAGASSERT(e)
-#endif
 
 /* Unlike <ctype.h>'s isdigit, this also works if c < 0 | c > UCHAR_MAX.  */
 #define is_digit(c) ((unsigned)(c) - '0' <= 9)
 
-#ifndef ATTRIBUTE_PURE
+#ifndef __pure
 #if 2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__)
-# define ATTRIBUTE_PURE __attribute__ ((__pure__))
+# define __pure __attribute__ ((__pure__))
 #else
-# define ATTRIBUTE_PURE /* empty */
-#endif
+# define __pure /* empty */
 #endif
-#if 0
-static char    elsieid[] = "@(#)localtime.cc   8.17";
-#else
-__RCSID("$NetBSD: localtime.c,v 1.82 2014/05/13 16:33:56 christos Exp $");
 #endif
 
 /*
@@ -361,16 +351,6 @@ struct tzhead {
 # define TM_ZONE __TM_ZONE
 #endif
 
-/* The minimum and maximum finite time values.  */
-static time_t const time_t_min =
-  (TYPE_SIGNED(time_t)
-   ? (time_t) -1 << (int)(CHAR_BIT * sizeof (time_t) - 1)
-   : 0);
-static time_t const time_t_max =
-  (TYPE_SIGNED(time_t)
-   ? - (~ 0 < 0) - ((time_t) -1 << (int)(CHAR_BIT * sizeof (time_t) - 1))
-   : -1);
-
 /*
 ** SunOS 4.1.1 headers lack O_BINARY.
 */
@@ -421,16 +401,16 @@ static const char gmt[] = "GMT";
 #endif /* !defined TZDEFDST */
 
 struct ttinfo {                                /* time type information */
-       int_fast32_t    tt_gmtoff;      /* UT offset in seconds */
+       long            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 */
-       int             tt_ttisgmt;     /* TRUE if transition is UT */
+       int             tt_ttisgmt;     /* TRUE if transition is UTC */
 };
 
 struct lsinfo {                                /* leap second information */
        time_t          ls_trans;       /* transition time */
-       int_fast64_t    ls_corr;        /* correction to apply */
+       long            ls_corr;        /* correction to apply */
 };
 
 #define BIGGEST(a, b)  (((a) > (b)) ? (a) : (b))
@@ -455,71 +435,66 @@ 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 */
 };
 
+typedef struct __state *timezone_t;
+
 struct rule {
        int             r_type;         /* type of rule--see below */
        int             r_day;          /* day number of rule */
        int             r_week;         /* week number of rule */
        int             r_mon;          /* month number of rule */
-       int_fast32_t    r_time;         /* transition time of rule */
+       long            r_time;         /* transition time of rule */
 };
 
 #define JULIAN_DAY             0       /* Jn - Julian day */
 #define DAY_OF_YEAR            1       /* n - day of year */
 #define MONTH_NTH_DAY_OF_WEEK  2       /* Mm.n.d - month, week, day of week */
 
-#ifdef __CYGWIN__
-typedef struct __state *timezone_t;
-#endif
-
 typedef struct tm *(*subfun_t)(const timezone_t sp, const time_t *timep,
-                              const int_fast32_t offset, struct tm *tmp);
+                              long offset, struct tm *tmp);
 
 /*
 ** Prototypes for static functions.
 */
 
-static int_fast32_t    detzcode(const char * codep);
-static int_fast64_t    detzcode64(const char * codep);
+static long            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) ATTRIBUTE_PURE;
-static const char *    getqzname(const char * strp, const int delim) 
ATTRIBUTE_PURE;
+static const char *    getzname(const char * strp) __pure;
+static const char *    getqzname(const char * strp, const int delim) __pure;
 static const char *    getnum(const char * strp, int * nump, int min,
                                int max);
-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 *    getsecs(const char * strp, long * secsp);
+static const char *    getoffset(const char * strp, long * 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,
-                               const int_fast32_t offset, struct tm * tmp);
+                               long offset, struct tm * tmp);
 static struct tm *     localsub(const timezone_t sp, const time_t *timep,
-                               const int_fast32_t offset, struct tm *tmp);
+                               long 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             leaps_thru_end_of(int y) __pure;
+static int             long_increment_overflow(long * number, int delta);
+static int             long_normalize_overflow(long * tensptr,
+                               int * unitsptr, int base);
 static int             normalize_overflow(int * tensptr, int * unitsptr,
                                int base);
-static int             normalize_overflow32(int_fast32_t * 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 int_fast32_t offset);
+                               subfun_t funcp, const long offset);
 static time_t          time2(const timezone_t sp, struct tm * const tmp,
                                subfun_t funcp,
-                               const int_fast32_t offset, int *const okayp);
+                               const long offset, int *const okayp);
 static time_t          time2sub(const timezone_t sp, struct tm * const tmp,
-                               subfun_t funcp, const int_fast32_t offset,
+                               subfun_t funcp, const long offset,
                                int *const okayp, const int do_norm_secs);
 static struct tm *     timesub(const timezone_t sp, const time_t * timep,
-                               const int_fast32_t offset, struct tm * tmp);
+                               long offset, struct tm * tmp);
 static int             tmcomp(const struct tm * atmp,
                                const struct tm * btmp);
-static int_fast32_t    transtime(int year, const struct rule * rulep,
-                                 int_fast32_t offset)
-  ATTRIBUTE_PURE;
+static time_t          transtime(time_t janfirst, int year,
+                               const struct rule * rulep, long offset) __pure;
 static int             typesequiv(const timezone_t sp, int a, int b);
 static int             tzload(timezone_t sp, const char * name,
                                int doextend);
@@ -530,7 +505,7 @@ extern "C" void             tzset_unlocked(void);
 #else
 static void            tzset_unlocked(void);
 #endif
-static int_fast64_t    leapcorr(const timezone_t sp, time_t * timep);
+static long            leapcorr(const timezone_t sp, time_t * timep);
 
 static timezone_t lclptr;
 static timezone_t gmtptr;
@@ -581,30 +556,30 @@ int                       daylight;
 #endif /* defined USG_COMPAT */
 
 #ifdef ALTZONE
-long                   altzone = 0;
+time_t                 altzone = 0;
 #endif /* defined ALTZONE */
 
-static int_fast32_t
+static long
 detzcode(const char *const codep)
 {
-       int_fast32_t    result;
+       long    result;
        int     i;
 
-       result = (codep[0] & 0x80) ? -1 : 0;
+       result = (codep[0] & 0x80) ? ~0L : 0;
        for (i = 0; i < 4; ++i)
                result = (result << 8) | (codep[i] & 0xff);
        return result;
 }
 
-static int_fast64_t
+static time_t
 detzcode64(const char *const codep)
 {
-       int_fast64_t    result;
+       time_t  result;
        int     i;
 
-       result = (codep[0] & 0x80) ? -1 : 0;
+       result = (time_t)((codep[0] & 0x80) ? (~(int_fast64_t) 0) : 0);
        for (i = 0; i < 8; ++i)
-               result = (result << 8) | (codep[i] & 0xff);
+               result = result * 256 + (codep[i] & 0xff);
        return result;
 }
 
@@ -630,7 +605,8 @@ settzname (void)
        for (i = 0; i < sp->typecnt; ++i) {
                const struct ttinfo * const     ttisp = &sp->ttis[i];
 
-               tzname[ttisp->tt_isdst] = &sp->chars[ttisp->tt_abbrind];
+               tzname[ttisp->tt_isdst] =
+                       &sp->chars[ttisp->tt_abbrind];
 #ifdef USG_COMPAT
                if (ttisp->tt_isdst)
                        daylight = 1;
@@ -658,8 +634,9 @@ settzname (void)
 static int
 differ_by_repeat(const time_t t1, const time_t t0)
 {
-       if (TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS)
-               return 0;
+       if (TYPE_INTEGRAL(time_t) &&
+               TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS)
+                       return 0;
        return (int_fast64_t)t1 - (int_fast64_t)t0 == SECSPERREPEAT;
 }
 
@@ -680,7 +657,7 @@ tzload(timezone_t sp, const char *name, const int doextend)
        u_t *                   up;
        save_errno              save;
 
-       up = (u_t *) malloc(sizeof *up);
+       up = (u_t *) calloc(1, sizeof *up);
        if (up == NULL)
                return -1;
 
@@ -745,7 +722,6 @@ 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);
@@ -770,36 +746,15 @@ 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) {
-                       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;
-                       }
+                       sp->ats[i] = (time_t)((stored == 4) ?
+                               detzcode(p) : detzcode64(p));
                        p += stored;
                }
-               timecnt = 0;
                for (i = 0; i < sp->timecnt; ++i) {
-                       unsigned char typ = *p++;
-                       if (sp->typecnt <= typ)
+                       sp->types[i] = (unsigned char) *p++;
+                       if (sp->types[i] >= sp->typecnt)
                                goto oops;
-                       if (sp->types[i])
-                               sp->types[timecnt++] = typ;
                }
                for (i = 0; i < sp->typecnt; ++i) {
                        struct ttinfo * ttisp;
@@ -855,6 +810,33 @@ 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 - 2; ++i)
+                       if (sp->ats[i] > sp->ats[i + 1]) {
+                               ++i;
+                               if (TYPE_SIGNED(time_t)) {
+                                       /*
+                                       ** Ignore the end (easy).
+                                       */
+                                       sp->timecnt = i;
+                               } else {
+                                       /*
+                                       ** Ignore the beginning (harder).
+                                       */
+                                       int     j;
+
+                                       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')
@@ -863,9 +845,11 @@ 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 signed narrow time_t system, we're done.
+               ** If this is a narrow integer time_t system, we're done.
                */
-               if (TYPE_SIGNED(time_t) && stored >= (int) sizeof(time_t))
+               if (stored >= (int) sizeof(time_t)
+/* CONSTCOND */
+                               && TYPE_INTEGRAL(time_t))
                        break;
        }
        if (doextend && nread > 2 &&
@@ -919,40 +903,6 @@ 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). . .
@@ -1083,7 +1033,7 @@ getnum(const char *strp, int *const nump, const int min, 
const int max)
 */
 
 static const char *
-getsecs(const char *strp, int_fast32_t *const secsp)
+getsecs(const char *strp, long *const secsp)
 {
        int     num;
 
@@ -1096,7 +1046,7 @@ getsecs(const char *strp, int_fast32_t *const secsp)
        strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
        if (strp == NULL)
                return NULL;
-       *secsp = num * (int_fast32_t) SECSPERHOUR;
+       *secsp = num * (long) SECSPERHOUR;
        if (*strp == ':') {
                ++strp;
                strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
@@ -1123,7 +1073,7 @@ getsecs(const char *strp, int_fast32_t *const secsp)
 */
 
 static const char *
-getoffset(const char *strp, int_fast32_t *const offsetp)
+getoffset(const char *strp, long *const offsetp)
 {
        int     neg = 0;
 
@@ -1188,22 +1138,23 @@ getrule(const char *strp, struct rule *const rulep)
                ** Time specified.
                */
                ++strp;
-               strp = getoffset(strp, &rulep->r_time);
+               strp = getsecs(strp, &rulep->r_time);
        } else  rulep->r_time = 2 * SECSPERHOUR;        /* default = 2:00:00 */
        return strp;
 }
 
 /*
-** 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.
+** Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the
+** year, a rule, and the offset from UTC at the time that rule takes effect,
+** calculate the Epoch-relative time that rule takes effect.
 */
 
-static int_fast32_t
-transtime(const int year, const struct rule *const rulep,
-         const int_fast32_t offset)
+static time_t
+transtime(const time_t janfirst, const int year, const struct rule *const 
rulep,
+    const long offset)
 {
        int     leapyear;
-       int_fast32_t    value;
+       time_t  value;
        int     i;
        int             d, m1, yy0, yy1, yy2, dow;
 
@@ -1219,7 +1170,7 @@ transtime(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 = (rulep->r_day - 1) * SECSPERDAY;
+               value = (time_t)(janfirst + (rulep->r_day - 1) * SECSPERDAY);
                if (leapyear && rulep->r_day >= 60)
                        value += SECSPERDAY;
                break;
@@ -1230,13 +1181,16 @@ transtime(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 = rulep->r_day * SECSPERDAY;
+               value = (time_t)(janfirst + 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
@@ -1269,19 +1223,17 @@ transtime(const int year, const struct rule *const 
rulep,
                /*
                ** "d" is the day-of-month (zero-origin) of the day we want.
                */
-               value = d * SECSPERDAY;
-               for (i = 0; i < rulep->r_mon - 1; ++i)
-                       value += mon_lengths[leapyear][i] * SECSPERDAY;
+               value += (time_t)(d * SECSPERDAY);
                break;
        }
 
        /*
-       ** "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
+       ** "value" is the Epoch-relative time of 00:00:00 UTC on the day in
+       ** question. To get the Epoch-relative time of the specified local
        ** time on that day, add the transition time and the current offset
-       ** from UT.
+       ** from UTC.
        */
-       return value + rulep->r_time + offset;
+       return (time_t)(value + rulep->r_time + offset);
 }
 
 /*
@@ -1292,12 +1244,14 @@ transtime(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;
-       int_fast32_t            stdoffset;
-       int_fast32_t            dstoffset;
+       const char *                    stdname;
+       const char *                    dstname;
+       size_t                          stdlen;
+       size_t                          dstlen;
+       long                            stdoffset;
+       long                            dstoffset;
+       time_t *                atp;
+       unsigned char * typep;
        char *                  cp;
        int                     load_result;
 
@@ -1354,10 +1308,10 @@ tzparse(timezone_t sp, const char *name, const int 
lastditch)
                if (*name == ',' || *name == ';') {
                        struct rule     start;
                        struct rule     end;
-                       int             year;
-                       int             yearlim;
-                       int             timecnt;
-                       time_t          janfirst;
+                       int     year;
+                       time_t  janfirst;
+                       time_t          starttime;
+                       time_t          endtime;
 
                        ++name;
                        if ((name = getrule(name, &start)) == NULL)
@@ -1379,45 +1333,37 @@ 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;
-                       sp->defaulttype = 0;
-                       timecnt = 0;
+                       atp = sp->ats;
+                       typep = sp->types;
                        janfirst = 0;
                        sp->timecnt = 0;
-                       yearlim = EPOCH_YEAR + YEARSPERREPEAT;
-                       for (year = EPOCH_YEAR; year < yearlim; year++) {
-                               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 (TZ_MAX_TIMES - 2 < timecnt)
-                                               break;
-                                       yearlim = year + YEARSPERREPEAT + 1;
-                                       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;
+                       for (year = EPOCH_YEAR;
+                           sp->timecnt + 2 <= TZ_MAX_TIMES;
+                           ++year) {
+                               time_t  newfirst;
+
+                               starttime = transtime(janfirst, year, &start,
+                                       stdoffset);
+                               endtime = transtime(janfirst, year, &end,
+                                       dstoffset);
+                               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 */
                                }
-                               if (increment_overflow_time(&janfirst, 
yearsecs))
+                               sp->timecnt += 2;
+                               newfirst = janfirst;
+                               newfirst += (time_t)
+                                   (year_lengths[isleap(year)] * SECSPERDAY);
+                               if (newfirst <= janfirst)
                                        break;
+                               janfirst = newfirst;
                        }
                        /*
                        ** Get zone offsets into tzinfo (for newlib). . .
@@ -1429,16 +1375,13 @@ tzparse(timezone_t sp, const char *name, const int 
lastditch)
                            __gettzinfo ()->__tzrule[1].offset
                                                    = -sp->ttis[0].tt_gmtoff;
                          }
-                       sp->timecnt = timecnt;
-                       if (!timecnt)
-                               sp->typecnt = 1;        /* Perpetual DST.  */
                } else {
-                       int_fast32_t    theirstdoffset;
-                       int_fast32_t    theirdstoffset;
-                       int_fast32_t    theiroffset;
-                       int             isdst;
-                       int             i;
-                       int             j;
+                       long    theirstdoffset;
+                       long    theirdstoffset;
+                       long    theiroffset;
+                       int     isdst;
+                       int     i;
+                       int     j;
 
                        if (*name != '\0')
                                return -1;
@@ -1517,7 +1460,6 @@ tzparse(timezone_t sp, const char *name, const int 
lastditch)
                        sp->ttis[1].tt_isdst = TRUE;
                        sp->ttis[1].tt_abbrind = (int)(stdlen + 1);
                        sp->typecnt = 2;
-                       sp->defaulttype = 0;
                        /*
                        ** Get zone offsets into tzinfo (for newlib). . .
                        */
@@ -1537,7 +1479,6 @@ tzparse(timezone_t sp, const char *name, const int 
lastditch)
                sp->ttis[0].tt_gmtoff = -stdoffset;
                sp->ttis[0].tt_isdst = 0;
                sp->ttis[0].tt_abbrind = 0;
-               sp->defaulttype = 0;
                /*
                ** Get zone offsets into tzinfo (for newlib). . .
                */
@@ -1586,7 +1527,7 @@ tzsetwall (void)
 
        if (lclptr == NULL) {
                save_errno save;
-               lclptr = (timezone_t) malloc(sizeof *lclptr);
+               lclptr = (timezone_t) calloc(1, sizeof *lclptr);
                if (lclptr == NULL) {
                        settzname();    /* all we can do */
                        return;
@@ -1709,7 +1650,7 @@ tzset_unlocked(void)
 
        if (lclptr == NULL) {
                save_errno save;
-               lclptr = (timezone_t) malloc(sizeof *lclptr);
+               lclptr = (timezone_t) calloc(1, sizeof *lclptr);
                if (lclptr == NULL) {
                        settzname();    /* all we can do */
                        return;
@@ -1753,7 +1694,7 @@ tzset(void)
 
 /*ARGSUSED*/
 static struct tm *
-localsub(const timezone_t sp, const time_t * const timep, const int_fast32_t 
offset,
+localsub(const timezone_t sp, const time_t * const timep, const long offset,
     struct tm *const tmp)
 {
        const struct ttinfo *   ttisp;
@@ -1765,14 +1706,22 @@ localsub(const timezone_t sp, const time_t * const 
timep, const int_fast32_t off
                (sp->goahead && t > sp->ats[sp->timecnt - 1])) {
                        time_t                  newt = t;
                        time_t          seconds;
-                       time_t          years;
+                       time_t          tcycles;
+                       int_fast64_t    icycles;
 
                        if (t < sp->ats[0])
                                seconds = sp->ats[0] - t;
                        else    seconds = t - sp->ats[sp->timecnt - 1];
                        --seconds;
-                       years = (time_t)((seconds / SECSPERREPEAT + 1) * 
YEARSPERREPEAT);
-                       seconds = (time_t)(years * AVGSECSPERYEAR);
+                       tcycles = (time_t)
+                           (seconds / YEARSPERREPEAT / AVGSECSPERYEAR);
+                       ++tcycles;
+                       icycles = tcycles;
+                       if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
+                               return NULL;
+                       seconds = (time_t) icycles;
+                       seconds *= YEARSPERREPEAT;
+                       seconds *= AVGSECSPERYEAR;
                        if (t < sp->ats[0])
                                newt += seconds;
                        else    newt -= seconds;
@@ -1785,8 +1734,8 @@ localsub(const timezone_t sp, const time_t * const timep, 
const int_fast32_t off
 
                                newy = tmp->tm_year;
                                if (t < sp->ats[0])
-                                       newy -= years;
-                               else    newy += years;
+                                       newy -= (time_t)icycles * 
YEARSPERREPEAT;
+                               else    newy += (time_t)icycles * 
YEARSPERREPEAT;
                                tmp->tm_year = (int)newy;
                                if (tmp->tm_year != newy)
                                        return NULL;
@@ -1794,7 +1743,12 @@ localsub(const timezone_t sp, const time_t * const 
timep, const int_fast32_t off
                        return result;
        }
        if (sp->timecnt == 0 || t < sp->ats[0]) {
-               i = sp->defaulttype;
+               i = 0;
+               while (sp->ttis[i].tt_isdst)
+                       if (++i >= sp->typecnt) {
+                               i = 0;
+                               break;
+                       }
        } else {
                int     lo = 1;
                int     hi = sp->timecnt;
@@ -1853,8 +1807,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 int_fast32_t offset, struct tm *const tmp)
+gmtsub(const timezone_t sp, const time_t *const timep, const long offset,
+    struct tm *tmp)
 {
        struct tm *     result;
 
@@ -1862,7 +1816,7 @@ gmtsub(const timezone_t sp, const time_t *const timep,
        if (!gmt_is_set) {
                save_errno save;
                gmt_is_set = TRUE;
-               gmtptr = (timezone_t) malloc(sizeof *gmtptr);
+               gmtptr = (timezone_t) calloc(1, sizeof *gmtptr);
                if (gmtptr != NULL)
                        gmtload(gmtptr);
        }
@@ -1871,11 +1825,19 @@ gmtsub(const timezone_t sp, const time_t *const timep,
 #ifdef TM_ZONE
        /*
        ** Could get fancy here and deliver something such as
-       ** "UT+xxxx" or "UT-xxxx" if offset is non-zero,
+       ** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero,
        ** but this is no time for a treasure hunt.
        */
        if (CYGWIN_VERSION_CHECK_FOR_EXTRA_TM_MEMBERS)
-         tmp->TM_ZONE = offset ? wildabbr : gmtptr ? gmtptr->chars : gmt;
+         {
+           if (offset != 0)
+                   tmp->TM_ZONE = wildabbr;
+           else {
+                   if (gmtptr == NULL)
+                           tmp->TM_ZONE = gmt;
+                   else        tmp->TM_ZONE = gmtptr->chars;
+           }
+         }
 #endif /* defined TM_ZONE */
        return result;
 }
@@ -1883,7 +1845,7 @@ gmtsub(const timezone_t sp, const time_t *const timep,
 extern "C" struct tm *
 gmtime(const time_t *const timep)
 {
-       struct tm *tmp = gmtsub(NULL, timep, 0, &tm);
+       struct tm *tmp = gmtsub(NULL, timep, 0L, &tm);
 
        if (tmp == NULL)
                errno = EOVERFLOW;
@@ -1898,7 +1860,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, 0, tmp);
+       tmp = gmtsub(NULL, timep, 0L, tmp);
 
        if (tmp == NULL)
                errno = EOVERFLOW;
@@ -1911,14 +1873,7 @@ 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;
-
-       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);
+       struct tm *tmp = gmtsub(NULL, timep, offset, &tm);
 
        if (tmp == NULL)
                errno = EOVERFLOW;
@@ -1941,16 +1896,16 @@ leaps_thru_end_of(const int y)
 }
 
 static struct tm *
-timesub(const timezone_t sp, const time_t *const timep,
-    const int_fast32_t offset, struct tm *const tmp)
+timesub(const timezone_t sp, const time_t *const timep, const long offset,
+    struct tm *const tmp)
 {
        const struct lsinfo *   lp;
        time_t                  tdays;
        int                     idays;  /* unsigned would be so 2003 */
-       int_fast64_t            rem;
+       long                    rem;
        int                     y;
        const int *             ip;
-       int_fast64_t            corr;
+       long                    corr;
        int                     hit;
        int                     i;
 
@@ -1979,7 +1934,7 @@ timesub(const timezone_t sp, const time_t *const timep,
        }
        y = EPOCH_YEAR;
        tdays = (time_t)(*timep / SECSPERDAY);
-       rem = (int_fast64_t) (*timep - tdays * SECSPERDAY);
+       rem = (long) (*timep - tdays * SECSPERDAY);
        while (tdays < 0 || tdays >= year_lengths[isleap(y)]) {
                int             newy;
                time_t  tdelta;
@@ -1987,11 +1942,9 @@ timesub(const timezone_t sp, const time_t *const timep,
                int     leapdays;
 
                tdelta = tdays / DAYSPERLYEAR;
-               if (! ((! TYPE_SIGNED(time_t) || INT_MIN <= tdelta)
-                      && tdelta <= INT_MAX))
+               idelta = (int) tdelta;
+               if (tdelta - idelta >= 1 || idelta - tdelta >= 1)
                        return NULL;
-               _DIAGASSERT(__type_fit(int, tdelta));
-               idelta = (int)tdelta;
                if (idelta == 0)
                        idelta = (tdays < 0) ? -1 : 1;
                newy = y;
@@ -2004,11 +1957,11 @@ timesub(const timezone_t sp, const time_t *const timep,
                y = newy;
        }
        {
-               int_fast32_t seconds;
+               long    seconds;
 
-               seconds = (int_fast32_t)(tdays * SECSPERDAY);
+               seconds = tdays * SECSPERDAY + 0.5;
                tdays = (time_t)(seconds / SECSPERDAY);
-               rem += (int_fast64_t)(seconds - tdays * SECSPERDAY);
+               rem += (long) (seconds - tdays * SECSPERDAY);
        }
        /*
        ** Given the range, we can now fearlessly cast...
@@ -2130,32 +2083,16 @@ increment_overflow(int *const ip, int j)
 }
 
 static int
-increment_overflow32(int_fast32_t *const lp, int const m)
+long_increment_overflow(long *const lp, int m)
 {
-       int_fast32_t l = *lp;
+       long l = *lp;
 
-       if ((l >= 0) ? (m > INT_FAST32_MAX - l) : (m < INT_FAST32_MIN - l))
+       if ((l >= 0) ? (m > LONG_MAX - l) : (m < LONG_MIN - l))
                return TRUE;
        *lp += 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)
 {
@@ -2169,7 +2106,7 @@ normalize_overflow(int *const tensptr, int *const 
unitsptr, const int base)
 }
 
 static int
-normalize_overflow32(int_fast32_t *const tensptr, int *const unitsptr,
+long_normalize_overflow(long *const tensptr, int *const unitsptr,
     const int base)
 {
        int     tensdelta;
@@ -2178,7 +2115,7 @@ normalize_overflow32(int_fast32_t *const tensptr, int 
*const unitsptr,
                (*unitsptr / base) :
                (-1 - (-1 - *unitsptr) / base);
        *unitsptr -= tensdelta * base;
-       return increment_overflow32(tensptr, tensdelta);
+       return long_increment_overflow(tensptr, tensdelta);
 }
 
 static int
@@ -2186,9 +2123,8 @@ tmcomp(const struct tm *const atmp, const struct tm 
*const btmp)
 {
        int     result;
 
-       if (atmp->tm_year != btmp->tm_year)
-               return atmp->tm_year < btmp->tm_year ? -1 : 1;
-       if ((result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
+       if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
+               (result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
                (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
                (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
                (result = (atmp->tm_min - btmp->tm_min)) == 0)
@@ -2198,21 +2134,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 int_fast32_t offset, int *const okayp, const int do_norm_secs)
+    const long offset, int *const okayp, const int do_norm_secs)
 {
        int                     dir;
        int                     i, j;
        int                     saved_seconds;
-       int_fast32_t            li;
+       long                    li;
        time_t                  lo;
        time_t                  hi;
 #ifdef NO_ERROR_IN_DST_GAP
        time_t                  ilo;
 #endif
-       int_fast32_t            y;
-       time_t                  newt;
-       time_t                  t;
-       struct tm               yourtm, mytm;
+       long                            y;
+       time_t                          newt;
+       time_t                          t;
+       struct tm                       yourtm, mytm;
 
        *okayp = FALSE;
        yourtm = *tmp;
@@ -2229,16 +2165,16 @@ again:
        if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
                goto overflow;
        y = yourtm.tm_year;
-       if (normalize_overflow32(&y, &yourtm.tm_mon, MONSPERYEAR))
+       if (long_normalize_overflow(&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 (increment_overflow32(&y, TM_YEAR_BASE))
+       if (long_increment_overflow(&y, TM_YEAR_BASE))
                goto overflow;
        while (yourtm.tm_mday <= 0) {
-               if (increment_overflow32(&y, -1))
+               if (long_increment_overflow(&y, -1))
                        goto overflow;
                li = y + (1 < yourtm.tm_mon);
                yourtm.tm_mday += year_lengths[isleap(li)];
@@ -2246,7 +2182,7 @@ again:
        while (yourtm.tm_mday > DAYSPERLYEAR) {
                li = y + (1 < yourtm.tm_mon);
                yourtm.tm_mday -= year_lengths[isleap(li)];
-               if (increment_overflow32(&y, 1))
+               if (long_increment_overflow(&y, 1))
                        goto overflow;
        }
        for ( ; ; ) {
@@ -2256,11 +2192,11 @@ again:
                yourtm.tm_mday -= i;
                if (++yourtm.tm_mon >= MONSPERYEAR) {
                        yourtm.tm_mon = 0;
-                       if (increment_overflow32(&y, 1))
+                       if (long_increment_overflow(&y, 1))
                                goto overflow;
                }
        }
-       if (increment_overflow32(&y, -TM_YEAR_BASE))
+       if (long_increment_overflow(&y, -TM_YEAR_BASE))
                goto overflow;
        yourtm.tm_year = (int)y;
        if (yourtm.tm_year != y)
@@ -2291,6 +2227,7 @@ again:
        if (!TYPE_SIGNED(time_t)) {
                lo = 0;
                hi = lo - 1;
+       /* LINTED const not */
        } else {
                lo = 1;
                for (i = 0; i < (int) TYPE_BIT(time_t) - 1; ++i)
@@ -2316,14 +2253,14 @@ again:
                } else  dir = tmcomp(&mytm, &yourtm);
                if (dir != 0) {
                        if (t == lo) {
-                               if (t == time_t_max)
-                                       goto overflow;
                                ++t;
+                               if (t <= lo)
+                                       goto overflow;
                                ++lo;
                        } else if (t == hi) {
-                               if (t == time_t_min)
-                                       goto overflow;
                                --t;
+                               if (t >= hi)
+                                       goto overflow;
                                --hi;
                        }
 #ifdef NO_ERROR_IN_DST_GAP
@@ -2403,7 +2340,7 @@ invalid:
 
 static time_t
 time2(const timezone_t sp, struct tm *const tmp, subfun_t funcp,
-    const int_fast32_t offset, int *const okayp)
+    const long offset, int *const okayp)
 {
        time_t  t;
 
@@ -2418,7 +2355,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 int_fast32_t offset)
+    const long offset)
 {
        time_t                  t;
        int                     samei, otheri;
@@ -2436,15 +2373,17 @@ time1(const timezone_t sp, struct tm *const tmp, 
subfun_t funcp,
        if (tmp->tm_isdst > 1)
                tmp->tm_isdst = 1;
        t = time2(sp, tmp, funcp, offset, &okay);
+#ifdef PCTS
+       /*
+       ** PCTS code courtesy Grant Sullivan.
+       */
        if (okay)
                return t;
        if (tmp->tm_isdst < 0)
-#ifdef PCTS
-               /*
-               ** POSIX Conformance Test Suite code courtesy Grant Sullivan.
-               */
                tmp->tm_isdst = 0;      /* reset to std and try again */
-#else
+#endif /* defined PCTS */
+#ifndef PCTS
+       if (okay || tmp->tm_isdst < 0)
                return t;
 #endif /* !defined PCTS */
        /*
@@ -2517,23 +2456,18 @@ timegm(struct tm *const tmp)
 
        if (tmp != NULL)
                tmp->tm_isdst = 0;
-       t = time1(gmtptr, tmp, gmtsub, 0);
+       t = time1(gmtptr, tmp, gmtsub, 0L);
        return t;
 }
 
 extern "C" time_t
-timeoff(struct tm *const tmp, long offset)
+timeoff(struct tm *const tmp, const 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, (int_fast32_t)offset);
+       t = time1(gmtptr, tmp, gmtsub, offset);
        return t;
 }
 
@@ -2572,7 +2506,7 @@ gtime(struct tm *const tmp)
 ** when exchanging timestamps with POSIX conforming systems.
 */
 
-static int_fast64_t
+static long
 leapcorr(const timezone_t sp, time_t *timep)
 {
        struct lsinfo * lp;

Reply via email to