Skip to content

Commit 93132d1

Browse files
committed
Simplify zic's handling of -r
This is refactoring; it should not affect user-visible behavior. * zic.c (struct timerange): New member pretrans. (limitrange): New arg locut. Use it to set r.pretrans. All callers changed. (writezone): Initialize the new member, to avoid undefined behavior. Simplify by using the new member.
1 parent 4170b91 commit 93132d1

1 file changed

Lines changed: 34 additions & 36 deletions

File tree

zic.c

Lines changed: 34 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -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

19641964
static 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

Comments
 (0)