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

commit 3003c3dacd157c11f5e035bc18bdd30631800720
Author: Corinna Vinschen <[email protected]>
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)
 {

Reply via email to