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