4
0
mirror of git://sourceware.org/git/newlib-cygwin.git synced 2025-02-09 02:29:07 +08:00

localtime 1.78

This commit is contained in:
Corinna Vinschen 2020-04-28 21:14:01 +02:00 committed by Ken Brown
parent 2a84917364
commit 23e0558ba0

View File

@ -1,4 +1,4 @@
/* $NetBSD: localtime.c,v 1.77 2013/07/30 15:30:37 joerg Exp $ */
/* $NetBSD: localtime.c,v 1.78 2013/09/20 19:06:54 christos Exp $ */
/*
** This file is in the public domain, so clarified as of
@ -71,6 +71,11 @@ 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>
#endif
#define time_t_min LONG_MIN
#define time_t_max LONG_MAX
/* Unlike <ctype.h>'s isdigit, this also works if c < 0 | c > UCHAR_MAX. */
#define is_digit(c) ((unsigned)(c) - '0' <= 9)
@ -85,7 +90,7 @@ static char privatehid[] = "@(#)private.h 7.48";
#if 0
static char elsieid[] = "@(#)localtime.cc 8.17";
#else
__RCSID("$NetBSD: localtime.c,v 1.77 2013/07/30 15:30:37 joerg Exp $");
__RCSID("$NetBSD: localtime.c,v 1.78 2013/09/20 19:06:54 christos Exp $");
#endif
/*
@ -406,11 +411,11 @@ static const char gmt[] = "GMT";
#endif /* !defined TZDEFDST */
struct ttinfo { /* time type information */
int_fast32_t tt_gmtoff; /* UTC offset in seconds */
int_fast32_t tt_gmtoff; /* UT 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 UTC */
int tt_ttisgmt; /* TRUE if transition is UT */
};
struct lsinfo { /* leap second information */
@ -642,9 +647,8 @@ settzname (void)
static int
differ_by_repeat(const time_t t1, const time_t t0)
{
if (TYPE_INTEGRAL(time_t) &&
TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS)
return 0;
if (TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS)
return 0;
return (int_fast64_t)t1 - (int_fast64_t)t0 == SECSPERREPEAT;
}
@ -864,11 +868,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 integer time_t system, we're done.
** If this is a narrow time_t system, we're done.
*/
if (stored >= (int) sizeof(time_t)
/* CONSTCOND */
&& TYPE_INTEGRAL(time_t))
if (stored >= (int) sizeof(time_t))
break;
}
if (doextend && nread > 2 &&
@ -1191,14 +1193,14 @@ getrule(const char *strp, struct rule *const rulep)
** Time specified.
*/
++strp;
strp = getsecs(strp, &rulep->r_time);
strp = getoffset(strp, &rulep->r_time);
} else rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */
return strp;
}
/*
** 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,
** year, a rule, and the offset from UT at the time that rule takes effect,
** calculate the Epoch-relative time that rule takes effect.
*/
@ -1281,10 +1283,10 @@ transtime(const time_t janfirst, const int year, const struct rule *const rulep,
}
/*
** "value" is the Epoch-relative time of 00:00:00 UTC on the day in
** "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
** time on that day, add the transition time and the current offset
** from UTC.
** from UT.
*/
return (time_t)(value + rulep->r_time + offset);
}
@ -1361,8 +1363,9 @@ tzparse(timezone_t sp, const char *name, const int lastditch)
if (*name == ',' || *name == ';') {
struct rule start;
struct rule end;
int year;
time_t janfirst;
int year;
int yearlim;
time_t janfirst;
time_t starttime;
time_t endtime;
@ -1390,33 +1393,39 @@ tzparse(timezone_t sp, const char *name, const int lastditch)
typep = sp->types;
janfirst = 0;
sp->timecnt = 0;
for (year = EPOCH_YEAR;
sp->timecnt + 2 <= TZ_MAX_TIMES;
++year) {
time_t newfirst;
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);
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 */
yearsecs = (year_lengths[isleap(year)]
* SECSPERDAY);
if (starttime > endtime
|| (starttime < endtime
&& (endtime - starttime
< (yearsecs
+ (stdoffset - dstoffset))))) {
if (&sp->ats[TZ_MAX_TIMES - 2] < atp)
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->timecnt += 2;
newfirst = janfirst;
newfirst += (time_t)
(year_lengths[isleap(year)] * SECSPERDAY);
if (newfirst <= janfirst)
if (time_t_max - janfirst < yearsecs)
break;
janfirst = newfirst;
janfirst += yearsecs;
}
/*
** Get zone offsets into tzinfo (for newlib). . .
@ -1428,6 +1437,10 @@ 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->typecnt = 1; /* Perpetual DST. */
} else {
int_fast32_t theirstdoffset;
int_fast32_t theirdstoffset;
@ -1759,22 +1772,14 @@ 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 tcycles;
int_fast64_t icycles;
time_t years;
if (t < sp->ats[0])
seconds = sp->ats[0] - t;
else seconds = t - sp->ats[sp->timecnt - 1];
--seconds;
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;
years = (time_t)((seconds / SECSPERREPEAT + 1) * YEARSPERREPEAT);
seconds = (time_t)(years * AVGSECSPERYEAR);
if (t < sp->ats[0])
newt += seconds;
else newt -= seconds;
@ -1787,8 +1792,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 -= (time_t)icycles * YEARSPERREPEAT;
else newy += (time_t)icycles * YEARSPERREPEAT;
newy -= years;
else newy += years;
tmp->tm_year = (int)newy;
if (tmp->tm_year != newy)
return NULL;
@ -1873,7 +1878,7 @@ gmtsub(const timezone_t sp, const time_t *const timep,
#ifdef TM_ZONE
/*
** Could get fancy here and deliver something such as
** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero,
** "UT+xxxx" or "UT-xxxx" if offset is non-zero,
** but this is no time for a treasure hunt.
*/
if (CYGWIN_VERSION_CHECK_FOR_EXTRA_TM_MEMBERS)
@ -1997,9 +2002,10 @@ timesub(const timezone_t sp, const time_t *const timep,
int leapdays;
tdelta = tdays / DAYSPERLYEAR;
idelta = (int) tdelta;
if (tdelta - idelta >= 1 || idelta - tdelta >= 1)
if (! ((! TYPE_SIGNED(time_t) || INT_MIN <= tdelta)
&& tdelta <= INT_MAX))
return NULL;
idelta = tdelta;
if (idelta == 0)
idelta = (tdays < 0) ? -1 : 1;
newy = y;
@ -2013,9 +2019,8 @@ timesub(const timezone_t sp, const time_t *const timep,
}
{
int_fast32_t seconds;
const time_t half_second = (time_t)0.5;
seconds = (int_fast32_t)(tdays * SECSPERDAY + half_second);
seconds = (int_fast32_t)(tdays * SECSPERDAY);
tdays = (time_t)(seconds / SECSPERDAY);
rem += (int_fast64_t)(seconds - tdays * SECSPERDAY);
}
@ -2179,8 +2184,9 @@ tmcomp(const struct tm *const atmp, const struct tm *const btmp)
{
int result;
if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
(result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
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 &&
(result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
(result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
(result = (atmp->tm_min - btmp->tm_min)) == 0)
@ -2283,7 +2289,6 @@ 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)
@ -2309,14 +2314,14 @@ again:
} else dir = tmcomp(&mytm, &yourtm);
if (dir != 0) {
if (t == lo) {
++t;
if (t <= lo)
if (t == time_t_max)
goto overflow;
++t;
++lo;
} else if (t == hi) {
--t;
if (t >= hi)
if (t == time_t_min)
goto overflow;
--t;
--hi;
}
#ifdef NO_ERROR_IN_DST_GAP
@ -2541,8 +2546,7 @@ timeoff(struct tm *const tmp, long offset)
** previous versions of the CMUCS runtime library.
*/
extern "C"
int_fast32_t
extern "C" long
gtime(struct tm *const tmp)
{
const time_t t = mktime(tmp);