@@ -1958,29 +1958,44 @@ struct timerange {
19581958 int defaulttype ;
19591959 ptrdiff_t base , count ;
19601960 int leapbase , leapcount ;
1961- bool leapexpiry ;
1961+ bool pretrans , leapexpiry ;
19621962};
19631963
19641964static struct timerange
1965- limitrange (struct timerange r , zic_t lo , zic_t hi ,
1965+ limitrange (struct timerange r , bool locut , zic_t lo , zic_t hi ,
19661966 zic_t const * ats , unsigned char const * types )
19671967{
1968+ /* Omit ordinary transitions < LO. */
19681969 while (0 < r .count && ats [r .base ] < lo ) {
19691970 r .defaulttype = types [r .base ];
19701971 r .count -- ;
19711972 r .base ++ ;
19721973 }
1974+
1975+ /* Omit as many leap seconds < LO as possible, such that the first
1976+ leap second in the truncated list is <= LO. */
19731977 while (1 < r .leapcount && trans [r .leapbase + 1 ] <= lo ) {
19741978 r .leapcount -- ;
19751979 r .leapbase ++ ;
19761980 }
19771981
1982+ /* Omit ordinary and leap second transitions greater than HI + 1. */
19781983 if (hi < ZIC_MAX ) {
19791984 while (0 < r .count && hi + 1 < ats [r .base + r .count - 1 ])
19801985 r .count -- ;
19811986 while (0 < r .leapcount && hi + 1 < trans [r .leapbase + r .leapcount - 1 ])
19821987 r .leapcount -- ;
19831988 }
1989+
1990+ /* Determine whether to keep the last too-low transition if no
1991+ transition is exactly at LO. The kept transition will be output
1992+ as a LO "transition"; see "Output a LO_TIME transition" below.
1993+ This is needed when the output is truncated at the start, and is
1994+ also useful when catering to buggy 32-bit clients that do not use
1995+ time type 0 for timestamps before the first transition. */
1996+ r .pretrans = locut && ! (r .count && ats [r .base ] == lo );
1997+
1998+ /* Determine whether to append an expiration to the leap second table. */
19841999 r .leapexpiry = 0 <= leapexpires && leapexpires - 1 <= hi ;
19852000
19862001 return r ;
@@ -2092,9 +2107,11 @@ writezone(const char *const name, const char *const string, char version,
20922107 rangeall .base = rangeall .leapbase = 0 ;
20932108 rangeall .count = timecnt ;
20942109 rangeall .leapcount = leapcnt ;
2095- rangeall .leapexpiry = false;
2096- range64 = limitrange (rangeall , lo_time , hi_time , ats , types );
2097- range32 = limitrange (range64 , INT32_MIN , INT32_MAX , ats , types );
2110+ rangeall .pretrans = rangeall .leapexpiry = false;
2111+ range64 = limitrange (rangeall , min_time < lo_time ,
2112+ lo_time , hi_time , ats , types );
2113+ range32 = limitrange (range64 , INT32_MIN < lo_time ,
2114+ INT32_MIN , INT32_MAX , ats , types );
20982115
20992116 /* TZif version 4 is needed if a no-op transition is appended to
21002117 indicate the expiration of the leap second table, or if the first
@@ -2129,7 +2146,7 @@ writezone(const char *const name, const char *const string, char version,
21292146 register int thisleapi , thisleapcnt , thisleaplim ;
21302147 struct tzhead tzh ;
21312148 int currenttype , thisdefaulttype ;
2132- bool locut , hicut , thisleapexpiry ;
2149+ bool hicut , pretrans , thisleapexpiry ;
21332150 zic_t lo ;
21342151 int old0 ;
21352152 char omittype [TZ_MAX_TYPES ];
@@ -2160,8 +2177,8 @@ writezone(const char *const name, const char *const string, char version,
21602177 toomanytimes = thistimecnt >> 31 >> 1 != 0 ;
21612178 thisleapi = range32 .leapbase ;
21622179 thisleapcnt = range32 .leapcount ;
2180+ pretrans = range32 .pretrans ;
21632181 thisleapexpiry = range32 .leapexpiry ;
2164- locut = INT32_MIN < lo_time ;
21652182 hicut = hi_time < INT32_MAX ;
21662183 } else {
21672184 thisdefaulttype = range64 .defaulttype ;
@@ -2170,33 +2187,17 @@ writezone(const char *const name, const char *const string, char version,
21702187 toomanytimes = thistimecnt >> 31 >> 31 >> 2 != 0 ;
21712188 thisleapi = range64 .leapbase ;
21722189 thisleapcnt = range64 .leapcount ;
2190+ pretrans = range64 .pretrans ;
21732191 thisleapexpiry = range64 .leapexpiry ;
2174- locut = min_time < lo_time ;
21752192 hicut = hi_time < max_time ;
21762193 }
21772194 if (toomanytimes )
21782195 error (_ ("too many transition times" ));
21792196
2180- /* Keep the last too-low transition if no transition is
2181- exactly at LO. The kept transition will be output as
2182- a LO "transition"; see "Output a LO_TIME transition"
2183- below. This is needed when the output is truncated at
2184- the start, and is also useful when catering to buggy
2185- 32-bit clients that do not use time type 0 for
2186- timestamps before the first transition. */
2187- if (0 < thistimei && ats [thistimei ] != lo_time ) {
2188- thistimei -- ;
2189- thistimecnt ++ ;
2190- locut = false;
2191- }
2192-
21932197 thistimelim = thistimei + thistimecnt ;
2194- if (thistimecnt != 0 ) {
2195- if (ats [thistimei ] == lo_time )
2196- locut = false;
2197- if (hi_time < ZIC_MAX && ats [thistimelim - 1 ] == hi_time + 1 )
2198- hicut = false;
2199- }
2198+ if (thistimecnt && hi_time < ZIC_MAX
2199+ && ats [thistimelim - 1 ] == hi_time + 1 )
2200+ hicut = false;
22002201 memset (omittype , true, typecnt );
22012202 omittype [thisdefaulttype ] = false;
22022203 for (i = thistimei ; i < thistimelim ; i ++ )
@@ -2291,11 +2292,9 @@ writezone(const char *const name, const char *const string, char version,
22912292 indmap [desigidx [i ]] = j ;
22922293 }
22932294 if (pass == 1 && !want_bloat ()) {
2294- thisleapcnt = 0 ;
2295- thisleapexpiry = false;
2296- thistimecnt = - (locut + hicut );
2295+ pretrans = hicut = thisleapexpiry = false;
2296+ thistimecnt = thisleapcnt = 0 ;
22972297 thistypecnt = thischarcnt = 1 ;
2298- thistimelim = thistimei ;
22992298 }
23002299#define DO (field ) fwrite(tzh.field, sizeof tzh.field, 1, fp)
23012300 memset (& tzh , 0 , sizeof tzh );
@@ -2304,7 +2303,7 @@ writezone(const char *const name, const char *const string, char version,
23042303 convert (utcnt , tzh .tzh_ttisutcnt );
23052304 convert (stdcnt , tzh .tzh_ttisstdcnt );
23062305 convert (thisleapcnt + thisleapexpiry , tzh .tzh_leapcnt );
2307- convert (locut + thistimecnt + hicut , tzh .tzh_timecnt );
2306+ convert (pretrans + thistimecnt + hicut , tzh .tzh_timecnt );
23082307 convert (thistypecnt , tzh .tzh_typecnt );
23092308 convert (thischarcnt , tzh .tzh_charcnt );
23102309 DO (tzh_magic );
@@ -2331,16 +2330,15 @@ writezone(const char *const name, const char *const string, char version,
23312330 for this pass. */
23322331 lo = pass == 1 && lo_time < INT32_MIN ? INT32_MIN : lo_time ;
23332332
2334- if (locut )
2333+ if (pretrans )
23352334 puttzcodepass (lo , fp , pass );
23362335 for (i = thistimei ; i < thistimelim ; ++ i ) {
2337- zic_t at = ats [i ] < lo ? lo : ats [i ];
2338- puttzcodepass (at , fp , pass );
2336+ puttzcodepass (ats [i ], fp , pass );
23392337 }
23402338 if (hicut )
23412339 puttzcodepass (hi_time + 1 , fp , pass );
23422340 currenttype = 0 ;
2343- if (locut )
2341+ if (pretrans )
23442342 putc (currenttype , fp );
23452343 for (i = thistimei ; i < thistimelim ; ++ i ) {
23462344 currenttype = typemap [types [i ]];
0 commit comments