]> sourceware.org Git - glibc.git/commitdiff
Update timezone code from tzcode 2014e.
authorJoseph Myers <joseph@codesourcery.com>
Wed, 25 Jun 2014 16:51:17 +0000 (16:51 +0000)
committerJoseph Myers <joseph@codesourcery.com>
Wed, 25 Jun 2014 16:51:17 +0000 (16:51 +0000)
This patch updates the timezone code from tzcode 2014e (the previous
version used was 2013i).

Tested x86_64.

* timezone/checktab.awk: Update from tzcode 2014e.
* timezone/private.h: Likewise.
* timezone/tzfile.h: Likewise.
* timezone/zdump.c: Likewise.
* timezone/zic.c: Likewise.

ChangeLog
timezone/checktab.awk
timezone/private.h
timezone/tzfile.h
timezone/zdump.c
timezone/zic.c

index 0849f424148504f4d56cf1c3f8429f4bc164919c..93c6bc9597616af5d83cede3b54a701da65d1f6b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2014-06-25  Joseph Myers  <joseph@codesourcery.com>
 
+       * timezone/checktab.awk: Update from tzcode 2014e.
+       * timezone/private.h: Likewise.
+       * timezone/tzfile.h: Likewise.
+       * timezone/zdump.c: Likewise.
+       * timezone/zic.c: Likewise.
+
        * sysdeps/unix/sysv/linux/kernel-features.h
        (__ASSUME_XFS_RESTRICTED_CHOWN): Remove macro.
        * sysdeps/unix/sysv/linux/pathconf.c (__statfs_chown_restricted)
index fec4f628e5a1b473c87e3eab192f305d9cf7bdfb..d78ba73156c3688b8b199ce7714ec94cecd2846e 100644 (file)
@@ -115,10 +115,14 @@ BEGIN {
        FS = " "
 }
 
+$1 ~ /^#/ { next }
+
 {
-       tz = ""
-       if ($1 == "Zone") tz = $2
-       if ($1 == "Link") {
+       tz = rules = ""
+       if ($1 == "Zone") {
+               tz = $2
+               ruleUsed[$4] = 1
+       } else if ($1 == "Link") {
                # Ignore Link commands if source and destination basenames
                # are identical, e.g. Europe/Istanbul versus Asia/Istanbul.
                src = $2
@@ -126,6 +130,10 @@ BEGIN {
                while ((i = index(src, "/"))) src = substr(src, i+1)
                while ((i = index(dst, "/"))) dst = substr(dst, i+1)
                if (src != dst) tz = $3
+       } else if ($1 == "Rule") {
+               ruleDefined[$2] = 1
+       } else {
+               ruleUsed[$2] = 1
        }
        if (tz && tz ~ /\//) {
                if (!tztab[tz]) {
@@ -138,6 +146,12 @@ BEGIN {
 }
 
 END {
+       for (tz in ruleDefined) {
+               if (!ruleUsed[tz]) {
+                       printf "%s: Rule never used\n", tz
+                       status = 1
+               }
+       }
        for (tz in tz2cc) {
                if (!zoneSeen[tz]) {
                        printf "%s:%d: no Zone table for `%s'\n", \
index 4eb0ab62215bf39b52119fc6934466388ffe6471..4e8f4ae7bc63554dda9983b07a40f68a19318442 100644 (file)
 */
 #ifndef HAVE_STDINT_H
 #define HAVE_STDINT_H \
-       (199901 <= __STDC_VERSION__ || \
-       2 < (__GLIBC__ + (0 < __GLIBC_MINOR__)))
+   (199901 <= __STDC_VERSION__ \
+    || 2 < __GLIBC__ + (1 <= __GLIBC_MINOR__)  \
+    || __CYGWIN__)
 #endif /* !defined HAVE_STDINT_H */
 
 #if HAVE_STDINT_H
@@ -205,6 +206,10 @@ typedef unsigned long uintmax_t;
 #define INT32_MIN (-1 - INT32_MAX)
 #endif /* !defined INT32_MIN */
 
+#ifndef SIZE_MAX
+#define SIZE_MAX ((size_t) -1)
+#endif
+
 #if 2 < __GNUC__ + (96 <= __GNUC_MINOR__)
 # define ATTRIBUTE_CONST __attribute__ ((const))
 # define ATTRIBUTE_PURE __attribute__ ((__pure__))
index 529650dd8a044b7a141dd41fbff76134c36dcb01..911130eb939a1abe95470616dad6675ecbaf40f0 100644 (file)
@@ -97,7 +97,7 @@ struct tzhead {
 */
 
 #ifndef TZ_MAX_TIMES
-#define TZ_MAX_TIMES   1200
+#define TZ_MAX_TIMES   2000
 #endif /* !defined TZ_MAX_TIMES */
 
 #ifndef TZ_MAX_TYPES
index 209b79d06c4727c1a9239b80d73e3653e3c0210e..c48ac8435fe142de60d8536c84185ed572dcb9db 100644 (file)
@@ -36,7 +36,9 @@
 
 #ifndef HAVE_STDINT_H
 # define HAVE_STDINT_H \
-    (199901 <= __STDC_VERSION__ || 2 < (__GLIBC__ + (0 < __GLIBC_MINOR__)))
+    (199901 <= __STDC_VERSION__ \
+     || 2 < __GLIBC__ + (1 <= __GLIBC_MINOR__) \
+     || __CYGWIN__)
 #endif
 #if HAVE_STDINT_H
 # include "stdint.h"
index e7b0081193299155d7a5a36534cc3980b8acf1c6..07d6c30ae226098916acd6dff9f60d889a3ff6f2 100644 (file)
@@ -162,6 +162,7 @@ static const char * rfilename;
 static int             rlinenum;
 static const char *    progname;
 static int             timecnt;
+static int             timecnt_alloc;
 static int             typecnt;
 
 /*
@@ -247,9 +248,11 @@ static int         typecnt;
 
 static struct rule *   rules;
 static int             nrules; /* number of rules */
+static int             nrules_alloc;
 
 static struct zone *   zones;
 static int             nzones; /* number of zones */
+static int             nzones_alloc;
 
 struct link {
        const char *    l_filename;
@@ -260,6 +263,7 @@ struct link {
 
 static struct link *   links;
 static int             nlinks;
+static int             nlinks_alloc;
 
 struct lookup {
        const char *    l_word;
@@ -346,7 +350,7 @@ static const int    len_years[2] = {
 static struct attype {
        zic_t           at;
        unsigned char   type;
-}                      attypes[TZ_MAX_TIMES];
+} *                    attypes;
 static zic_t           gmtoffs[TZ_MAX_TYPES];
 static char            isdsts[TZ_MAX_TYPES];
 static unsigned char   abbrinds[TZ_MAX_TYPES];
@@ -361,16 +365,26 @@ static char               roll[TZ_MAX_LEAPS];
 ** Memory allocation.
 */
 
+static _Noreturn void
+memory_exhausted(const char *msg)
+{
+       fprintf(stderr, _("%s: Memory exhausted: %s\n"), progname, msg);
+       exit(EXIT_FAILURE);
+}
+
+static ATTRIBUTE_PURE size_t
+size_product(size_t nitems, size_t itemsize)
+{
+       if (SIZE_MAX / itemsize < nitems)
+               memory_exhausted("size overflow");
+       return nitems * itemsize;
+}
+
 static ATTRIBUTE_PURE void *
 memcheck(void *const ptr)
 {
-       if (ptr == NULL) {
-               const char *e = strerror(errno);
-
-               (void) fprintf(stderr, _("%s: Memory exhausted: %s\n"),
-                       progname, e);
-               exit(EXIT_FAILURE);
-       }
+       if (ptr == NULL)
+               memory_exhausted(strerror(errno));
        return ptr;
 }
 
@@ -379,6 +393,20 @@ memcheck(void *const ptr)
 #define ecpyalloc(ptr)         memcheck(icpyalloc(ptr))
 #define ecatalloc(oldp, newp)  memcheck(icatalloc((oldp), (newp)))
 
+static void *
+growalloc(void *ptr, size_t itemsize, int nitems, int *nitems_alloc)
+{
+       if (nitems < *nitems_alloc)
+               return ptr;
+       else {
+               int amax = INT_MAX < SIZE_MAX ? INT_MAX : SIZE_MAX;
+               if ((amax - 1) / 3 * 2 < *nitems_alloc)
+                       memory_exhausted("int overflow");
+               *nitems_alloc = *nitems_alloc + (*nitems_alloc >> 1) + 1;
+               return erealloc(ptr, size_product(*nitems_alloc, itemsize));
+       }
+}
+
 /*
 ** Error handling.
 */
@@ -695,6 +723,36 @@ warning(_("hard link failed, symbolic link used"));
 static const zic_t min_time = (zic_t) -1 << (TIME_T_BITS_IN_FILE - 1);
 static const zic_t max_time = -1 - ((zic_t) -1 << (TIME_T_BITS_IN_FILE - 1));
 
+/* Estimated time of the Big Bang, in seconds since the POSIX epoch.
+   rounded downward to the negation of a power of two that is
+   comfortably outside the error bounds.
+
+   zic does not output time stamps before this, partly because they
+   are physically suspect, and partly because GNOME mishandles them; see
+   GNOME bug 730332 <https://bugzilla.gnome.org/show_bug.cgi?id=730332>.
+
+   For the time of the Big Bang, see:
+
+   Ade PAR, Aghanim N, Armitage-Caplan C et al.  Planck 2013 results.
+   I. Overview of products and scientific results.
+   arXiv:1303.5062 2013-03-20 20:10:01 UTC
+   <http://arxiv.org/pdf/1303.5062v1> [PDF]
+
+   Page 36, Table 9, row Age/Gyr, column Planck+WP+highL+BAO 68% limits
+   gives the value 13.798 plus-or-minus 0.037 billion years.
+   Multiplying this by 1000000000 and then by 31557600 (the number of
+   seconds in an astronomical year) gives a value that is comfortably
+   less than 2**59, so BIG_BANG is - 2**59.
+
+   BIG_BANG is approximate, and may change in future versions.
+   Please do not rely on its exact value.  */
+
+#ifndef BIG_BANG
+#define BIG_BANG (- (1LL << 59))
+#endif
+
+static const zic_t big_bang_time = BIG_BANG;
+
 static int
 itsdir(const char *const name)
 {
@@ -934,8 +992,6 @@ gethms(const char *string, const char *const errstring, const int signable)
                error(_("time overflow"));
                return 0;
        }
-       if (noise && hh == HOURSPERDAY && mm == 0 && ss == 0)
-               warning(_("24:00 not handled by pre-1998 versions of zic"));
        if (noise && (hh > HOURSPERDAY ||
                (hh == HOURSPERDAY && (mm != 0 || ss != 0))))
 warning(_("values over 24 hours not handled by pre-2007 versions of zic"));
@@ -965,7 +1021,7 @@ inrule(register char **const fields, const int nfields)
        r.r_abbrvar = ecpyalloc(fields[RF_ABBRVAR]);
        if (max_abbrvar_len < strlen(r.r_abbrvar))
                max_abbrvar_len = strlen(r.r_abbrvar);
-       rules = erealloc(rules, (nrules + 1) * sizeof *rules);
+       rules = growalloc(rules, sizeof *rules, nrules, &nrules_alloc);
        rules[nrules++] = r;
 }
 
@@ -1081,7 +1137,7 @@ inzsub(register char **const fields, const int nfields, const int iscont)
                                return FALSE;
                }
        }
-       zones = erealloc(zones, (nzones + 1) * sizeof *zones);
+       zones = growalloc(zones, sizeof *zones, nzones, &nzones_alloc);
        zones[nzones++] = z;
        /*
        ** If there was an UNTIL field on this line,
@@ -1148,10 +1204,6 @@ inleap(register char ** const fields, const int nfields)
                        return;
        }
        dayoff = oadd(dayoff, day - 1);
-       if (dayoff < 0 && !TYPE_SIGNED(zic_t)) {
-               error(_("time before zero"));
-               return;
-       }
        if (dayoff < min_time / SECSPERDAY) {
                error(_("time too small"));
                return;
@@ -1160,7 +1212,7 @@ inleap(register char ** const fields, const int nfields)
                error(_("time too large"));
                return;
        }
-       t = (zic_t) dayoff * SECSPERDAY;
+       t = dayoff * SECSPERDAY;
        tod = gethms(fields[LP_TIME], _("invalid time of day"), FALSE);
        cp = fields[LP_CORR];
        {
@@ -1189,7 +1241,12 @@ inleap(register char ** const fields, const int nfields)
                                ));
                        return;
                }
-               leapadd(tadd(t, tod), positive, lp->l_value, count);
+               t = tadd(t, tod);
+               if (t < big_bang_time) {
+                       error(_("leap second precedes Big Bang"));
+                       return;
+               }
+               leapadd(t, positive, lp->l_value, count);
        }
 }
 
@@ -1214,7 +1271,7 @@ inlink(register char **const fields, const int nfields)
        l.l_linenum = linenum;
        l.l_from = ecpyalloc(fields[LF_FROM]);
        l.l_to = ecpyalloc(fields[LF_TO]);
-       links = erealloc(links, (nlinks + 1) * sizeof *links);
+       links = growalloc(links, sizeof *links, nlinks, &nlinks_alloc);
        links[nlinks++] = l;
 }
 
@@ -1434,8 +1491,9 @@ writezone(const char *const name, const char *const string, char version)
        static char *                   fullname;
        static const struct tzhead      tzh0;
        static struct tzhead            tzh;
-       zic_t                           ats[TZ_MAX_TIMES];
-       unsigned char                   types[TZ_MAX_TIMES];
+       zic_t *ats = emalloc(size_product(timecnt, sizeof *ats + 1));
+       void *typesptr = ats + timecnt;
+       unsigned char *types = typesptr;
 
        /*
        ** Sort.
@@ -1451,19 +1509,13 @@ writezone(const char *const name, const char *const string, char version)
 
                toi = 0;
                fromi = 0;
-               while (fromi < timecnt && attypes[fromi].at < min_time)
+               while (fromi < timecnt && attypes[fromi].at < big_bang_time)
                        ++fromi;
-               /*
-               ** Remember that type 0 is reserved.
-               */
-               if (isdsts[1] == 0)
-                       while (fromi < timecnt && attypes[fromi].type == 1)
-                               ++fromi;        /* handled by default rule */
                for ( ; fromi < timecnt; ++fromi) {
-                       if (toi != 0 && ((attypes[fromi].at +
+                       if (toi > 1 && ((attypes[fromi].at +
                                gmtoffs[attypes[toi - 1].type]) <=
-                               (attypes[toi - 1].at + gmtoffs[toi == 1 ? 0
-                               attypes[toi - 2].type]))) {
+                               (attypes[toi - 1].at +
+                               gmtoffs[attypes[toi - 2].type]))) {
                                        attypes[toi - 1].type =
                                                attypes[fromi].type;
                                        continue;
@@ -1474,6 +1526,9 @@ writezone(const char *const name, const char *const string, char version)
                }
                timecnt = toi;
        }
+       if (noise && timecnt > 1200)
+               warning(_("pre-2014 clients may mishandle"
+                         " more than 1200 transition times"));
        /*
        ** Transfer.
        */
@@ -1505,6 +1560,13 @@ writezone(const char *const name, const char *const string, char version)
                --timecnt32;
                ++timei32;
        }
+       /*
+       ** Output an INT32_MIN "transition" if appropriate--see below.
+       */
+       if (timei32 > 0 && ats[timei32] > INT32_MIN) {
+               --timei32;
+               ++timecnt32;
+       }
        while (leapcnt32 > 0 && !is32(trans[leapcnt32 - 1]))
                --leapcnt32;
        while (leapcnt32 > 0 && !is32(trans[leapi32])) {
@@ -1539,7 +1601,7 @@ writezone(const char *const name, const char *const string, char version)
                register int    thistimei, thistimecnt;
                register int    thisleapi, thisleapcnt;
                register int    thistimelim, thisleaplim;
-               int             writetype[TZ_MAX_TIMES];
+               int             writetype[TZ_MAX_TYPES];
                int             typemap[TZ_MAX_TYPES];
                register int    thistypecnt;
                char            thischars[TZ_MAX_CHARS];
@@ -1559,11 +1621,7 @@ writezone(const char *const name, const char *const string, char version)
                }
                thistimelim = thistimei + thistimecnt;
                thisleaplim = thisleapi + thisleapcnt;
-               /*
-               ** Remember that type 0 is reserved.
-               */
-               writetype[0] = FALSE;
-               for (i = 1; i < typecnt; ++i)
+               for (i = 0; i < typecnt; ++i)
                        writetype[i] = thistimecnt == timecnt;
                if (thistimecnt == 0) {
                        /*
@@ -1579,11 +1637,8 @@ writezone(const char *const name, const char *const string, char version)
                        /*
                        ** For America/Godthab and Antarctica/Palmer
                        */
-                       /*
-                       ** Remember that type 0 is reserved.
-                       */
                        if (thistimei == 0)
-                               writetype[1] = TRUE;
+                               writetype[0] = TRUE;
                }
 #ifndef LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH
                /*
@@ -1633,26 +1688,8 @@ writezone(const char *const name, const char *const string, char version)
                }
 #endif /* !defined LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH */
                thistypecnt = 0;
-               /*
-               ** Potentially, set type 0 to that of lowest-valued time.
-               */
-               if (thistimei > 0) {
-                       for (i = 1; i < typecnt; ++i)
-                               if (writetype[i] && !isdsts[i])
-                                       break;
-                       if (i != types[thistimei - 1]) {
-                               i = types[thistimei - 1];
-                               gmtoffs[0] = gmtoffs[i];
-                               isdsts[0] = isdsts[i];
-                               ttisstds[0] = ttisstds[i];
-                               ttisgmts[0] = ttisgmts[i];
-                               abbrinds[0] = abbrinds[i];
-                               writetype[0] = TRUE;
-                               writetype[i] = FALSE;
-                       }
-               }
                for (i = 0; i < typecnt; ++i)
-                       typemap[i] = writetype[i] ?  thistypecnt++ : 0;
+                       typemap[i] = writetype[i] ?  thistypecnt++ : -1;
                for (i = 0; i < sizeof indmap / sizeof indmap[0]; ++i)
                        indmap[i] = -1;
                thischarcnt = 0;
@@ -1696,7 +1733,12 @@ writezone(const char *const name, const char *const string, char version)
 #undef DO
                for (i = thistimei; i < thistimelim; ++i)
                        if (pass == 1)
-                               puttzcode(ats[i], fp);
+                               /*
+                               ** Output an INT32_MIN "transition"
+                               ** if appropriate--see above.
+                               */
+                               puttzcode(((ats[i] < INT32_MIN) ?
+                                       INT32_MIN : ats[i]), fp);
                        else    puttzcode64(ats[i], fp);
                for (i = thistimei; i < thistimelim; ++i) {
                        unsigned char   uc;
@@ -1751,6 +1793,7 @@ writezone(const char *const name, const char *const string, char version)
                        progname, fullname);
                exit(EXIT_FAILURE);
        }
+       free(ats);
 }
 
 static void
@@ -2074,11 +2117,6 @@ outzone(const struct zone * const zpfirst, const int zonecount)
                updateminmax(leapminyear);
                updateminmax(leapmaxyear + (leapmaxyear < ZIC_MAX));
        }
-       /*
-       ** Reserve type 0.
-       */
-       gmtoffs[0] = isdsts[0] = ttisstds[0] = ttisgmts[0] = abbrinds[0] = -1;
-       typecnt = 1;
        for (i = 0; i < zonecount; ++i) {
                zp = &zpfirst[i];
                if (i < zonecount - 1)
@@ -2160,9 +2198,9 @@ outzone(const struct zone * const zpfirst, const int zonecount)
                */
                stdoff = 0;
                zp = &zpfirst[i];
-               usestart = i > 0 && (zp - 1)->z_untiltime > min_time;
+               usestart = i > 0 && (zp - 1)->z_untiltime > big_bang_time;
                useuntil = i < (zonecount - 1);
-               if (useuntil && zp->z_untiltime <= min_time)
+               if (useuntil && zp->z_untiltime <= big_bang_time)
                        continue;
                gmtoff = zp->z_gmtoff;
                eat(zp->z_filename, zp->z_linenum);
@@ -2178,8 +2216,7 @@ outzone(const struct zone * const zpfirst, const int zonecount)
                        if (usestart) {
                                addtt(starttime, type);
                                usestart = FALSE;
-                       } else if (stdoff != 0)
-                               addtt(min_time, type);
+                       } else  addtt(big_bang_time, type);
                } else for (year = min_year; year <= max_year; ++year) {
                        if (useuntil && year > zp->z_untilrule.r_hiyear)
                                break;
@@ -2356,8 +2393,8 @@ error(_("can't determine time zone abbreviation to use just after until time"));
 static void
 addtt(const zic_t starttime, int type)
 {
-       if (starttime <= min_time ||
-               (timecnt == 1 && attypes[0].at < min_time)) {
+       if (starttime <= big_bang_time ||
+               (timecnt == 1 && attypes[0].at < big_bang_time)) {
                gmtoffs[0] = gmtoffs[type];
                isdsts[0] = isdsts[type];
                ttisstds[0] = ttisstds[type];
@@ -2370,10 +2407,7 @@ addtt(const zic_t starttime, int type)
                timecnt = 0;
                type = 0;
        }
-       if (timecnt >= TZ_MAX_TIMES) {
-               error(_("too many transitions?!"));
-               exit(EXIT_FAILURE);
-       }
+       attypes = growalloc(attypes, sizeof *attypes, timecnt, &timecnt_alloc);
        attypes[timecnt].at = starttime;
        attypes[timecnt].type = type;
        ++timecnt;
@@ -2572,7 +2606,7 @@ getfields(register char *cp)
 
        if (cp == NULL)
                return NULL;
-       array = emalloc((strlen(cp) + 1) * sizeof *array);
+       array = emalloc(size_product(strlen(cp) + 1, sizeof *array));
        nsubs = 0;
        for ( ; ; ) {
                while (isascii((unsigned char) *cp) &&
This page took 0.136507 seconds and 5 git commands to generate.