diff options
Diffstat (limited to 'libc/tzcode')
-rw-r--r-- | libc/tzcode/difftime.c | 10 | ||||
-rw-r--r-- | libc/tzcode/localtime.c | 116 | ||||
-rw-r--r-- | libc/tzcode/private.h | 22 | ||||
-rw-r--r-- | libc/tzcode/strftime.c | 4 | ||||
-rw-r--r-- | libc/tzcode/tzfile.h | 13 |
5 files changed, 82 insertions, 83 deletions
diff --git a/libc/tzcode/difftime.c b/libc/tzcode/difftime.c index fcd18ce..449cdf0 100644 --- a/libc/tzcode/difftime.c +++ b/libc/tzcode/difftime.c @@ -5,7 +5,7 @@ /*LINTLIBRARY*/ -#include "private.h" /* for time_t, TYPE_INTEGRAL, and TYPE_SIGNED */ +#include "private.h" /* for time_t and TYPE_SIGNED */ double ATTRIBUTE_CONST difftime(const time_t time1, const time_t time0) @@ -16,15 +16,8 @@ difftime(const time_t time1, const time_t time0) */ if (sizeof (double) > sizeof (time_t)) return (double) time1 - (double) time0; - if (!TYPE_INTEGRAL(time_t)) { - /* - ** time_t is floating. - */ - return time1 - time0; - } if (!TYPE_SIGNED(time_t)) { /* - ** time_t is integral and unsigned. ** The difference of two unsigned values can't overflow ** if the minuend is greater than or equal to the subtrahend. */ @@ -33,7 +26,6 @@ difftime(const time_t time1, const time_t time0) else return -(double) (time0 - time1); } /* - ** time_t is integral and signed. ** Handle cases where both time1 and time0 have the same sign ** (meaning that their difference cannot overflow). */ diff --git a/libc/tzcode/localtime.c b/libc/tzcode/localtime.c index f374541..a52e334 100644 --- a/libc/tzcode/localtime.c +++ b/libc/tzcode/localtime.c @@ -13,7 +13,6 @@ #include "private.h" #include "tzfile.h" #include "fcntl.h" -#include "float.h" /* for FLT_MAX and DBL_MAX */ #ifndef TZ_ABBR_MAX_LEN #define TZ_ABBR_MAX_LEN 16 @@ -91,11 +90,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 */ @@ -232,12 +231,12 @@ char * tzname[2] = { static struct tm tmGlobal; #ifdef USG_COMPAT -time_t timezone = 0; -int daylight = 0; +long timezone = 0; +int daylight = 0; #endif /* defined USG_COMPAT */ #ifdef ALTZONE -time_t altzone = 0; +long altzone = 0; #endif /* defined ALTZONE */ static int_fast32_t @@ -334,8 +333,7 @@ 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) + if (TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS) return 0; return t1 - t0 == SECSPERREPEAT; } @@ -514,9 +512,9 @@ tzload(register const char* name, register struct state* const sp, 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) && TYPE_INTEGRAL(time_t)) + if (stored >= (int) sizeof(time_t)) break; } if (doextend && nread > 2 && @@ -824,14 +822,14 @@ getrule(const char * strp, register 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. */ @@ -914,10 +912,10 @@ transtime(const time_t janfirst, const int year, } /* - ** "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 value + rulep->r_time + offset; } @@ -997,6 +995,7 @@ tzparse(const char * name, register struct state * const sp, struct rule start; struct rule end; register int year; + register int yearlim; register time_t janfirst; time_t starttime; time_t endtime; @@ -1024,35 +1023,43 @@ tzparse(const char * name, register struct state * const sp, atp = sp->ats; 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 += year_lengths[isleap(year)] * - SECSPERDAY; - if (newfirst <= janfirst) + if (time_t_max - janfirst < yearsecs) break; - janfirst = newfirst; + janfirst += yearsecs; } + sp->timecnt = atp - sp->ats; + if (!sp->timecnt) + sp->typecnt = 1; /* Perpetual DST. */ } else { register int_fast32_t theirstdoffset; register int_fast32_t theirdstoffset; @@ -1290,21 +1297,14 @@ localsub(const time_t * const timep, const int_fast32_t offset, (sp->goahead && t > sp->ats[sp->timecnt - 1])) { time_t newt = t; register time_t seconds; - register time_t tcycles; - register int_fast64_t icycles; + register time_t years; if (t < sp->ats[0]) seconds = sp->ats[0] - t; else seconds = t - sp->ats[sp->timecnt - 1]; --seconds; - tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR; - ++tcycles; - icycles = tcycles; - if (tcycles - icycles >= 1 || icycles - tcycles >= 1) - return NULL; - seconds = icycles; - seconds *= YEARSPERREPEAT; - seconds *= AVGSECSPERYEAR; + years = (seconds / SECSPERREPEAT + 1) * YEARSPERREPEAT; + seconds = years * AVGSECSPERYEAR; if (t < sp->ats[0]) newt += seconds; else newt -= seconds; @@ -1317,8 +1317,8 @@ localsub(const time_t * const timep, const int_fast32_t offset, newy = tmp->tm_year; if (t < sp->ats[0]) - newy -= icycles * YEARSPERREPEAT; - else newy += icycles * YEARSPERREPEAT; + newy -= years; + else newy += years; tmp->tm_year = newy; if (tmp->tm_year != newy) return NULL; @@ -1403,7 +1403,7 @@ gmtsub(const time_t * const timep, const int_fast32_t offset, #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 (offset != 0) @@ -1509,9 +1509,10 @@ timesub(const time_t *const timep, const int_fast32_t offset, register int leapdays; tdelta = tdays / DAYSPERLYEAR; + if (! ((! TYPE_SIGNED(time_t) || INT_MIN <= tdelta) + && tdelta <= INT_MAX)) + return NULL; idelta = tdelta; - if (tdelta - idelta >= 1 || idelta - tdelta >= 1) - return NULL; if (idelta == 0) idelta = (tdays < 0) ? -1 : 1; newy = y; @@ -1525,9 +1526,8 @@ timesub(const time_t *const timep, const int_fast32_t offset, } { register int_fast32_t seconds; - register time_t half_second = 0.5; - seconds = tdays * SECSPERDAY + half_second; + seconds = tdays * SECSPERDAY; tdays = seconds / SECSPERDAY; rem += seconds - tdays * SECSPERDAY; } @@ -1685,8 +1685,9 @@ tmcomp(register const struct tm * const atmp, { register 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) @@ -1785,11 +1786,6 @@ time2sub(struct tm * const tmp, if (!TYPE_SIGNED(time_t)) { lo = 0; hi = lo - 1; - } else if (!TYPE_INTEGRAL(time_t)) { - if (sizeof(time_t) > sizeof(float)) - hi = (time_t) DBL_MAX; - else hi = (time_t) FLT_MAX; - lo = -hi; } else { lo = 1; for (i = 0; i < (int) TYPE_BIT(time_t) - 1; ++i) @@ -2019,7 +2015,7 @@ timegm(struct tm * const tmp) ** previous versions of the CMUCS runtime library. */ -int_fast32_t +long gtime(struct tm * const tmp) { const time_t t = mktime(tmp); diff --git a/libc/tzcode/private.h b/libc/tzcode/private.h index 1a938a2..3a19305 100644 --- a/libc/tzcode/private.h +++ b/libc/tzcode/private.h @@ -166,10 +166,21 @@ typedef int int_fast32_t; #ifndef INTMAX_MAX # if defined LLONG_MAX || defined __LONG_LONG_MAX__ typedef long long intmax_t; +# define strtoimax strtoll # define PRIdMAX "lld" +# ifdef LLONG_MAX +# define INTMAX_MAX LLONG_MAX +# define INTMAX_MIN LLONG_MIN +# else +# define INTMAX_MAX __LONG_LONG_MAX__ +# define INTMAX_MIN __LONG_LONG_MIN__ +# endif # else typedef long intmax_t; +# define strtoimax strtol # define PRIdMAX "ld" +# define INTMAX_MAX LONG_MAX +# define INTMAX_MIN LONG_MIN # endif #endif @@ -193,9 +204,11 @@ typedef unsigned long uintmax_t; #if 2 < __GNUC__ + (96 <= __GNUC_MINOR__) # define ATTRIBUTE_CONST __attribute__ ((const)) # define ATTRIBUTE_PURE __attribute__ ((__pure__)) +# define ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec)) #else # define ATTRIBUTE_CONST /* empty */ # define ATTRIBUTE_PURE /* empty */ +# define ATTRIBUTE_FORMAT(spec) /* empty */ #endif #if !defined _Noreturn && __STDC_VERSION__ < 201112 @@ -314,15 +327,6 @@ static time_t const time_t_max = ? - (~ 0 < 0) - ((time_t) -1 << (CHAR_BIT * sizeof (time_t) - 1)) : -1); -/* -** Since the definition of TYPE_INTEGRAL contains floating point numbers, -** it cannot be used in preprocessor directives. -*/ - -#ifndef TYPE_INTEGRAL -#define TYPE_INTEGRAL(type) (((type) 0.5) != 0.5) -#endif /* !defined TYPE_INTEGRAL */ - #ifndef INT_STRLEN_MAXIMUM /* ** 302 / 1000 is log10(2.0) rounded up. diff --git a/libc/tzcode/strftime.c b/libc/tzcode/strftime.c index e92c44d..1b223e5 100644 --- a/libc/tzcode/strftime.c +++ b/libc/tzcode/strftime.c @@ -592,7 +592,7 @@ label: continue; case 'z': { - int diff; + long diff; char const * sign; if (t->tm_isdst < 0) @@ -601,7 +601,7 @@ label: diff = t->TM_GMTOFF; #else /* !defined TM_GMTOFF */ /* - ** C99 says that the UTC offset must + ** C99 says that the UT offset must ** be computed by looking only at ** tm_isdst. This requirement is ** incorrect, since it means the code diff --git a/libc/tzcode/tzfile.h b/libc/tzcode/tzfile.h index d04fe04..a2955dd 100644 --- a/libc/tzcode/tzfile.h +++ b/libc/tzcode/tzfile.h @@ -39,7 +39,7 @@ struct tzhead { char tzh_magic[4]; /* TZ_MAGIC */ - char tzh_version[1]; /* '\0' or '2' as of 2005 */ + char tzh_version[1]; /* '\0' or '2' or '3' as of 2013 */ char tzh_reserved[15]; /* reserved--must be zero */ char tzh_ttisgmtcnt[4]; /* coded number of trans. time flags */ char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */ @@ -55,7 +55,7 @@ struct tzhead { ** tzh_timecnt (char [4])s coded transition times a la time(2) ** tzh_timecnt (unsigned char)s types of local time starting at above ** tzh_typecnt repetitions of -** one (char [4]) coded UTC offset in seconds +** one (char [4]) coded UT offset in seconds ** one (unsigned char) used to set tm_isdst ** one (unsigned char) that's an abbreviation list index ** tzh_charcnt (char)s '\0'-terminated zone abbreviations @@ -68,7 +68,7 @@ struct tzhead { ** if absent, transition times are ** assumed to be wall clock time ** tzh_ttisgmtcnt (char)s indexed by type; if TRUE, transition -** time is UTC, if FALSE, +** time is UT, if FALSE, ** transition time is local time ** if absent, transition times are ** assumed to be local time @@ -82,6 +82,13 @@ struct tzhead { ** instants after the last transition time stored in the file ** (with nothing between the newlines if there is no POSIX representation for ** such instants). +** +** If tz_version is '3' or greater, the above is extended as follows. +** First, the POSIX TZ string's hour offset may range from -167 +** through 167 as compared to the POSIX-required 0 through 24. +** Second, its DST start time may be January 1 at 00:00 and its stop +** time December 31 at 24:00 plus the difference between DST and +** standard time, indicating DST all year. */ /* |