mirror of
https://github.com/postgres/postgres.git
synced 2025-05-03 22:24:49 +03:00
Sync our copy of the timezone library with IANA release tzcode2019b.
A large fraction of this diff is just due to upstream's somewhat random decision to rename a bunch of internal variables and struct fields. However, there is an interesting new feature in zic: it's grown a "-b slim" option that emits zone files without 32-bit data and other backwards-compatibility hacks. We should consider whether we wish to enable that.
This commit is contained in:
parent
e0d13dc6fd
commit
59cea8f36b
@ -55,7 +55,7 @@ match properly on the old version.
|
|||||||
Time Zone code
|
Time Zone code
|
||||||
==============
|
==============
|
||||||
|
|
||||||
The code in this directory is currently synced with tzcode release 2019a.
|
The code in this directory is currently synced with tzcode release 2019b.
|
||||||
There are many cosmetic (and not so cosmetic) differences from the
|
There are many cosmetic (and not so cosmetic) differences from the
|
||||||
original tzcode library, but diffs in the upstream version should usually
|
original tzcode library, but diffs in the upstream version should usually
|
||||||
be propagated to our version. Here are some notes about that.
|
be propagated to our version. Here are some notes about that.
|
||||||
@ -127,4 +127,7 @@ and then run them through pgindent. (The first three sed patterns deal
|
|||||||
with conversion of their block comment style to something pgindent
|
with conversion of their block comment style to something pgindent
|
||||||
won't make a hash of; the remainder address other points noted above.)
|
won't make a hash of; the remainder address other points noted above.)
|
||||||
After that, the files can be diff'd directly against our corresponding
|
After that, the files can be diff'd directly against our corresponding
|
||||||
files.
|
files. Also, it's typically helpful to diff against the previous tzcode
|
||||||
|
release (after processing that the same way), and then try to apply the
|
||||||
|
diff to our files. This will take care of most of the changes
|
||||||
|
mechanically.
|
||||||
|
@ -107,15 +107,15 @@ static bool typesequiv(struct state const *, int, int);
|
|||||||
|
|
||||||
static struct pg_tm tm;
|
static struct pg_tm tm;
|
||||||
|
|
||||||
/* Initialize *S to a value based on GMTOFF, ISDST, and ABBRIND. */
|
/* Initialize *S to a value based on UTOFF, ISDST, and DESIGIDX. */
|
||||||
static void
|
static void
|
||||||
init_ttinfo(struct ttinfo *s, int32 gmtoff, bool isdst, int abbrind)
|
init_ttinfo(struct ttinfo *s, int32 utoff, bool isdst, int desigidx)
|
||||||
{
|
{
|
||||||
s->tt_gmtoff = gmtoff;
|
s->tt_utoff = utoff;
|
||||||
s->tt_isdst = isdst;
|
s->tt_isdst = isdst;
|
||||||
s->tt_abbrind = abbrind;
|
s->tt_desigidx = desigidx;
|
||||||
s->tt_ttisstd = false;
|
s->tt_ttisstd = false;
|
||||||
s->tt_ttisgmt = false;
|
s->tt_ttisut = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32
|
static int32
|
||||||
@ -251,7 +251,7 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
|
|||||||
for (stored = 4; stored <= 8; stored *= 2)
|
for (stored = 4; stored <= 8; stored *= 2)
|
||||||
{
|
{
|
||||||
int32 ttisstdcnt = detzcode(up->tzhead.tzh_ttisstdcnt);
|
int32 ttisstdcnt = detzcode(up->tzhead.tzh_ttisstdcnt);
|
||||||
int32 ttisgmtcnt = detzcode(up->tzhead.tzh_ttisgmtcnt);
|
int32 ttisutcnt = detzcode(up->tzhead.tzh_ttisutcnt);
|
||||||
int64 prevtr = 0;
|
int64 prevtr = 0;
|
||||||
int32 prevcorr = 0;
|
int32 prevcorr = 0;
|
||||||
int32 leapcnt = detzcode(up->tzhead.tzh_leapcnt);
|
int32 leapcnt = detzcode(up->tzhead.tzh_leapcnt);
|
||||||
@ -270,7 +270,7 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
|
|||||||
&& 0 <= timecnt && timecnt < TZ_MAX_TIMES
|
&& 0 <= timecnt && timecnt < TZ_MAX_TIMES
|
||||||
&& 0 <= charcnt && charcnt < TZ_MAX_CHARS
|
&& 0 <= charcnt && charcnt < TZ_MAX_CHARS
|
||||||
&& (ttisstdcnt == typecnt || ttisstdcnt == 0)
|
&& (ttisstdcnt == typecnt || ttisstdcnt == 0)
|
||||||
&& (ttisgmtcnt == typecnt || ttisgmtcnt == 0)))
|
&& (ttisutcnt == typecnt || ttisutcnt == 0)))
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
if (nread
|
if (nread
|
||||||
< (tzheadsize /* struct tzhead */
|
< (tzheadsize /* struct tzhead */
|
||||||
@ -280,7 +280,7 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
|
|||||||
+ charcnt /* chars */
|
+ charcnt /* chars */
|
||||||
+ leapcnt * (stored + 4) /* lsinfos */
|
+ leapcnt * (stored + 4) /* lsinfos */
|
||||||
+ ttisstdcnt /* ttisstds */
|
+ ttisstdcnt /* ttisstds */
|
||||||
+ ttisgmtcnt)) /* ttisgmts */
|
+ ttisutcnt)) /* ttisuts */
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
sp->leapcnt = leapcnt;
|
sp->leapcnt = leapcnt;
|
||||||
sp->timecnt = timecnt;
|
sp->timecnt = timecnt;
|
||||||
@ -332,19 +332,19 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
|
|||||||
{
|
{
|
||||||
struct ttinfo *ttisp;
|
struct ttinfo *ttisp;
|
||||||
unsigned char isdst,
|
unsigned char isdst,
|
||||||
abbrind;
|
desigidx;
|
||||||
|
|
||||||
ttisp = &sp->ttis[i];
|
ttisp = &sp->ttis[i];
|
||||||
ttisp->tt_gmtoff = detzcode(p);
|
ttisp->tt_utoff = detzcode(p);
|
||||||
p += 4;
|
p += 4;
|
||||||
isdst = *p++;
|
isdst = *p++;
|
||||||
if (!(isdst < 2))
|
if (!(isdst < 2))
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
ttisp->tt_isdst = isdst;
|
ttisp->tt_isdst = isdst;
|
||||||
abbrind = *p++;
|
desigidx = *p++;
|
||||||
if (!(abbrind < sp->charcnt))
|
if (!(desigidx < sp->charcnt))
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
ttisp->tt_abbrind = abbrind;
|
ttisp->tt_desigidx = desigidx;
|
||||||
}
|
}
|
||||||
for (i = 0; i < sp->charcnt; ++i)
|
for (i = 0; i < sp->charcnt; ++i)
|
||||||
sp->chars[i] = *p++;
|
sp->chars[i] = *p++;
|
||||||
@ -398,13 +398,13 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
|
|||||||
struct ttinfo *ttisp;
|
struct ttinfo *ttisp;
|
||||||
|
|
||||||
ttisp = &sp->ttis[i];
|
ttisp = &sp->ttis[i];
|
||||||
if (ttisgmtcnt == 0)
|
if (ttisutcnt == 0)
|
||||||
ttisp->tt_ttisgmt = false;
|
ttisp->tt_ttisut = false;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (*p != true && *p != false)
|
if (*p != true && *p != false)
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
ttisp->tt_ttisgmt = *p++;
|
ttisp->tt_ttisut = *p++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -438,13 +438,13 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
|
|||||||
|
|
||||||
for (i = 0; i < ts->typecnt; i++)
|
for (i = 0; i < ts->typecnt; i++)
|
||||||
{
|
{
|
||||||
char *tsabbr = ts->chars + ts->ttis[i].tt_abbrind;
|
char *tsabbr = ts->chars + ts->ttis[i].tt_desigidx;
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
for (j = 0; j < charcnt; j++)
|
for (j = 0; j < charcnt; j++)
|
||||||
if (strcmp(sp->chars + j, tsabbr) == 0)
|
if (strcmp(sp->chars + j, tsabbr) == 0)
|
||||||
{
|
{
|
||||||
ts->ttis[i].tt_abbrind = j;
|
ts->ttis[i].tt_desigidx = j;
|
||||||
gotabbr++;
|
gotabbr++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -456,7 +456,7 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
|
|||||||
{
|
{
|
||||||
strcpy(sp->chars + j, tsabbr);
|
strcpy(sp->chars + j, tsabbr);
|
||||||
charcnt = j + tsabbrlen + 1;
|
charcnt = j + tsabbrlen + 1;
|
||||||
ts->ttis[i].tt_abbrind = j;
|
ts->ttis[i].tt_desigidx = j;
|
||||||
gotabbr++;
|
gotabbr++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -614,12 +614,13 @@ typesequiv(const struct state *sp, int a, int b)
|
|||||||
const struct ttinfo *ap = &sp->ttis[a];
|
const struct ttinfo *ap = &sp->ttis[a];
|
||||||
const struct ttinfo *bp = &sp->ttis[b];
|
const struct ttinfo *bp = &sp->ttis[b];
|
||||||
|
|
||||||
result = ap->tt_gmtoff == bp->tt_gmtoff &&
|
result = (ap->tt_utoff == bp->tt_utoff
|
||||||
ap->tt_isdst == bp->tt_isdst &&
|
&& ap->tt_isdst == bp->tt_isdst
|
||||||
ap->tt_ttisstd == bp->tt_ttisstd &&
|
&& ap->tt_ttisstd == bp->tt_ttisstd
|
||||||
ap->tt_ttisgmt == bp->tt_ttisgmt &&
|
&& ap->tt_ttisut == bp->tt_ttisut
|
||||||
strcmp(&sp->chars[ap->tt_abbrind],
|
&& (strcmp(&sp->chars[ap->tt_desigidx],
|
||||||
&sp->chars[bp->tt_abbrind]) == 0;
|
&sp->chars[bp->tt_desigidx])
|
||||||
|
== 0));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -1176,7 +1177,7 @@ tzparse(const char *name, struct state *sp, bool lastditch)
|
|||||||
if (!sp->ttis[j].tt_isdst)
|
if (!sp->ttis[j].tt_isdst)
|
||||||
{
|
{
|
||||||
theirstdoffset =
|
theirstdoffset =
|
||||||
-sp->ttis[j].tt_gmtoff;
|
-sp->ttis[j].tt_utoff;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1187,7 +1188,7 @@ tzparse(const char *name, struct state *sp, bool lastditch)
|
|||||||
if (sp->ttis[j].tt_isdst)
|
if (sp->ttis[j].tt_isdst)
|
||||||
{
|
{
|
||||||
theirdstoffset =
|
theirdstoffset =
|
||||||
-sp->ttis[j].tt_gmtoff;
|
-sp->ttis[j].tt_utoff;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1206,7 +1207,7 @@ tzparse(const char *name, struct state *sp, bool lastditch)
|
|||||||
{
|
{
|
||||||
j = sp->types[i];
|
j = sp->types[i];
|
||||||
sp->types[i] = sp->ttis[j].tt_isdst;
|
sp->types[i] = sp->ttis[j].tt_isdst;
|
||||||
if (sp->ttis[j].tt_ttisgmt)
|
if (sp->ttis[j].tt_ttisut)
|
||||||
{
|
{
|
||||||
/* No adjustment to transition time */
|
/* No adjustment to transition time */
|
||||||
}
|
}
|
||||||
@ -1234,7 +1235,7 @@ tzparse(const char *name, struct state *sp, bool lastditch)
|
|||||||
theirstdoffset;
|
theirstdoffset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
theiroffset = -sp->ttis[j].tt_gmtoff;
|
theiroffset = -sp->ttis[j].tt_utoff;
|
||||||
if (sp->ttis[j].tt_isdst)
|
if (sp->ttis[j].tt_isdst)
|
||||||
theirdstoffset = theiroffset;
|
theirdstoffset = theiroffset;
|
||||||
else
|
else
|
||||||
@ -1357,14 +1358,14 @@ localsub(struct state const *sp, pg_time_t const *timep,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* To get (wrong) behavior that's compatible with System V Release 2.0
|
* To get (wrong) behavior that's compatible with System V Release 2.0
|
||||||
* you'd replace the statement below with t += ttisp->tt_gmtoff;
|
* you'd replace the statement below with t += ttisp->tt_utoff;
|
||||||
* timesub(&t, 0L, sp, tmp);
|
* timesub(&t, 0L, sp, tmp);
|
||||||
*/
|
*/
|
||||||
result = timesub(&t, ttisp->tt_gmtoff, sp, tmp);
|
result = timesub(&t, ttisp->tt_utoff, sp, tmp);
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
result->tm_isdst = ttisp->tt_isdst;
|
result->tm_isdst = ttisp->tt_isdst;
|
||||||
result->tm_zone = unconstify(char *, &sp->chars[ttisp->tt_abbrind]);
|
result->tm_zone = unconstify(char *, &sp->chars[ttisp->tt_desigidx]);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -1647,7 +1648,7 @@ pg_next_dst_boundary(const pg_time_t *timep,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ttisp = &sp->ttis[i];
|
ttisp = &sp->ttis[i];
|
||||||
*before_gmtoff = ttisp->tt_gmtoff;
|
*before_gmtoff = ttisp->tt_utoff;
|
||||||
*before_isdst = ttisp->tt_isdst;
|
*before_isdst = ttisp->tt_isdst;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1700,7 +1701,7 @@ pg_next_dst_boundary(const pg_time_t *timep,
|
|||||||
/* No known transition > t, so use last known segment's type */
|
/* No known transition > t, so use last known segment's type */
|
||||||
i = sp->types[sp->timecnt - 1];
|
i = sp->types[sp->timecnt - 1];
|
||||||
ttisp = &sp->ttis[i];
|
ttisp = &sp->ttis[i];
|
||||||
*before_gmtoff = ttisp->tt_gmtoff;
|
*before_gmtoff = ttisp->tt_utoff;
|
||||||
*before_isdst = ttisp->tt_isdst;
|
*before_isdst = ttisp->tt_isdst;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1715,13 +1716,13 @@ pg_next_dst_boundary(const pg_time_t *timep,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ttisp = &sp->ttis[i];
|
ttisp = &sp->ttis[i];
|
||||||
*before_gmtoff = ttisp->tt_gmtoff;
|
*before_gmtoff = ttisp->tt_utoff;
|
||||||
*before_isdst = ttisp->tt_isdst;
|
*before_isdst = ttisp->tt_isdst;
|
||||||
*boundary = sp->ats[0];
|
*boundary = sp->ats[0];
|
||||||
/* And for "after", use the first segment's type */
|
/* And for "after", use the first segment's type */
|
||||||
i = sp->types[0];
|
i = sp->types[0];
|
||||||
ttisp = &sp->ttis[i];
|
ttisp = &sp->ttis[i];
|
||||||
*after_gmtoff = ttisp->tt_gmtoff;
|
*after_gmtoff = ttisp->tt_utoff;
|
||||||
*after_isdst = ttisp->tt_isdst;
|
*after_isdst = ttisp->tt_isdst;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -1743,12 +1744,12 @@ pg_next_dst_boundary(const pg_time_t *timep,
|
|||||||
}
|
}
|
||||||
j = sp->types[i - 1];
|
j = sp->types[i - 1];
|
||||||
ttisp = &sp->ttis[j];
|
ttisp = &sp->ttis[j];
|
||||||
*before_gmtoff = ttisp->tt_gmtoff;
|
*before_gmtoff = ttisp->tt_utoff;
|
||||||
*before_isdst = ttisp->tt_isdst;
|
*before_isdst = ttisp->tt_isdst;
|
||||||
*boundary = sp->ats[i];
|
*boundary = sp->ats[i];
|
||||||
j = sp->types[i];
|
j = sp->types[i];
|
||||||
ttisp = &sp->ttis[j];
|
ttisp = &sp->ttis[j];
|
||||||
*after_gmtoff = ttisp->tt_gmtoff;
|
*after_gmtoff = ttisp->tt_utoff;
|
||||||
*after_isdst = ttisp->tt_isdst;
|
*after_isdst = ttisp->tt_isdst;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -1832,9 +1833,9 @@ pg_interpret_timezone_abbrev(const char *abbrev,
|
|||||||
for (i = cutoff - 1; i >= 0; i--)
|
for (i = cutoff - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
ttisp = &sp->ttis[sp->types[i]];
|
ttisp = &sp->ttis[sp->types[i]];
|
||||||
if (ttisp->tt_abbrind == abbrind)
|
if (ttisp->tt_desigidx == abbrind)
|
||||||
{
|
{
|
||||||
*gmtoff = ttisp->tt_gmtoff;
|
*gmtoff = ttisp->tt_utoff;
|
||||||
*isdst = ttisp->tt_isdst;
|
*isdst = ttisp->tt_isdst;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1846,9 +1847,9 @@ pg_interpret_timezone_abbrev(const char *abbrev,
|
|||||||
for (i = cutoff; i < sp->timecnt; i++)
|
for (i = cutoff; i < sp->timecnt; i++)
|
||||||
{
|
{
|
||||||
ttisp = &sp->ttis[sp->types[i]];
|
ttisp = &sp->ttis[sp->types[i]];
|
||||||
if (ttisp->tt_abbrind == abbrind)
|
if (ttisp->tt_desigidx == abbrind)
|
||||||
{
|
{
|
||||||
*gmtoff = ttisp->tt_gmtoff;
|
*gmtoff = ttisp->tt_utoff;
|
||||||
*isdst = ttisp->tt_isdst;
|
*isdst = ttisp->tt_isdst;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1875,10 +1876,10 @@ pg_get_timezone_offset(const pg_tz *tz, long int *gmtoff)
|
|||||||
sp = &tz->state;
|
sp = &tz->state;
|
||||||
for (i = 1; i < sp->typecnt; i++)
|
for (i = 1; i < sp->typecnt; i++)
|
||||||
{
|
{
|
||||||
if (sp->ttis[i].tt_gmtoff != sp->ttis[0].tt_gmtoff)
|
if (sp->ttis[i].tt_utoff != sp->ttis[0].tt_utoff)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
*gmtoff = sp->ttis[0].tt_gmtoff;
|
*gmtoff = sp->ttis[0].tt_utoff;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,11 +25,11 @@
|
|||||||
|
|
||||||
struct ttinfo
|
struct ttinfo
|
||||||
{ /* time type information */
|
{ /* time type information */
|
||||||
int32 tt_gmtoff; /* UT offset in seconds */
|
int32 tt_utoff; /* UT offset in seconds */
|
||||||
bool tt_isdst; /* used to set tm_isdst */
|
bool tt_isdst; /* used to set tm_isdst */
|
||||||
int tt_abbrind; /* abbreviation list index */
|
int tt_desigidx; /* abbreviation list index */
|
||||||
bool tt_ttisstd; /* transition is std time */
|
bool tt_ttisstd; /* transition is std time */
|
||||||
bool tt_ttisgmt; /* transition is UT */
|
bool tt_ttisut; /* transition is UT */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct lsinfo
|
struct lsinfo
|
||||||
|
@ -41,7 +41,7 @@ struct tzhead
|
|||||||
char tzh_magic[4]; /* TZ_MAGIC */
|
char tzh_magic[4]; /* TZ_MAGIC */
|
||||||
char tzh_version[1]; /* '\0' or '2' or '3' as of 2013 */
|
char tzh_version[1]; /* '\0' or '2' or '3' as of 2013 */
|
||||||
char tzh_reserved[15]; /* reserved; must be zero */
|
char tzh_reserved[15]; /* reserved; must be zero */
|
||||||
char tzh_ttisgmtcnt[4]; /* coded number of trans. time flags */
|
char tzh_ttisutcnt[4]; /* coded number of trans. time flags */
|
||||||
char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */
|
char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */
|
||||||
char tzh_leapcnt[4]; /* coded number of leap seconds */
|
char tzh_leapcnt[4]; /* coded number of leap seconds */
|
||||||
char tzh_timecnt[4]; /* coded number of transition times */
|
char tzh_timecnt[4]; /* coded number of transition times */
|
||||||
@ -64,14 +64,15 @@ struct tzhead
|
|||||||
* one (char [4]) total correction after above
|
* one (char [4]) total correction after above
|
||||||
* tzh_ttisstdcnt (char)s indexed by type; if 1, transition
|
* tzh_ttisstdcnt (char)s indexed by type; if 1, transition
|
||||||
* time is standard time, if 0,
|
* time is standard time, if 0,
|
||||||
* transition time is wall clock time
|
* transition time is local (wall clock)
|
||||||
* if absent, transition times are
|
* time; if absent, transition times are
|
||||||
* assumed to be wall clock time
|
|
||||||
* tzh_ttisgmtcnt (char)s indexed by type; if 1, transition
|
|
||||||
* time is UT, if 0,
|
|
||||||
* transition time is local time
|
|
||||||
* if absent, transition times are
|
|
||||||
* assumed to be local time
|
* assumed to be local time
|
||||||
|
* tzh_ttisutcnt (char)s indexed by type; if 1, transition
|
||||||
|
* time is UT, if 0, transition time is
|
||||||
|
* local time; if absent, transition
|
||||||
|
* times are assumed to be local time.
|
||||||
|
* When this is 1, the corresponding
|
||||||
|
* std/wall indicator must also be 1.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -77,12 +77,10 @@ struct rule
|
|||||||
int r_wday;
|
int r_wday;
|
||||||
|
|
||||||
zic_t r_tod; /* time from midnight */
|
zic_t r_tod; /* time from midnight */
|
||||||
bool r_todisstd; /* above is standard time if 1 or wall clock
|
bool r_todisstd; /* is r_tod standard time? */
|
||||||
* time if 0 */
|
bool r_todisut; /* is r_tod UT? */
|
||||||
bool r_todisgmt; /* above is GMT if 1 or local time if 0 */
|
|
||||||
bool r_isdst; /* is this daylight saving time? */
|
bool r_isdst; /* is this daylight saving time? */
|
||||||
zic_t r_stdoff; /* offset from default time (which is usually
|
zic_t r_save; /* offset from standard time */
|
||||||
* standard time) */
|
|
||||||
const char *r_abbrvar; /* variable part of abbreviation */
|
const char *r_abbrvar; /* variable part of abbreviation */
|
||||||
|
|
||||||
bool r_todo; /* a rule to do (used in outzone) */
|
bool r_todo; /* a rule to do (used in outzone) */
|
||||||
@ -103,13 +101,13 @@ struct zone
|
|||||||
lineno_t z_linenum;
|
lineno_t z_linenum;
|
||||||
|
|
||||||
const char *z_name;
|
const char *z_name;
|
||||||
zic_t z_gmtoff;
|
zic_t z_stdoff;
|
||||||
char *z_rule;
|
char *z_rule;
|
||||||
const char *z_format;
|
const char *z_format;
|
||||||
char z_format_specifier;
|
char z_format_specifier;
|
||||||
|
|
||||||
bool z_isdst;
|
bool z_isdst;
|
||||||
zic_t z_stdoff;
|
zic_t z_save;
|
||||||
|
|
||||||
struct rule *z_rules;
|
struct rule *z_rules;
|
||||||
ptrdiff_t z_nrules;
|
ptrdiff_t z_nrules;
|
||||||
@ -133,7 +131,7 @@ static void associate(void);
|
|||||||
static void dolink(const char *, const char *, bool);
|
static void dolink(const char *, const char *, bool);
|
||||||
static char **getfields(char *buf);
|
static char **getfields(char *buf);
|
||||||
static zic_t gethms(const char *string, const char *errstring);
|
static zic_t gethms(const char *string, const char *errstring);
|
||||||
static zic_t getstdoff(char *, bool *);
|
static zic_t getsave(char *, bool *);
|
||||||
static void infile(const char *filename);
|
static void infile(const char *filename);
|
||||||
static void inleap(char **fields, int nfields);
|
static void inleap(char **fields, int nfields);
|
||||||
static void inlink(char **fields, int nfields);
|
static void inlink(char **fields, int nfields);
|
||||||
@ -210,7 +208,7 @@ static int typecnt;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define ZF_NAME 1
|
#define ZF_NAME 1
|
||||||
#define ZF_GMTOFF 2
|
#define ZF_STDOFF 2
|
||||||
#define ZF_RULE 3
|
#define ZF_RULE 3
|
||||||
#define ZF_FORMAT 4
|
#define ZF_FORMAT 4
|
||||||
#define ZF_TILYEAR 5
|
#define ZF_TILYEAR 5
|
||||||
@ -224,7 +222,7 @@ static int typecnt;
|
|||||||
* Which fields are which on a Zone continuation line.
|
* Which fields are which on a Zone continuation line.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define ZFC_GMTOFF 0
|
#define ZFC_STDOFF 0
|
||||||
#define ZFC_RULE 1
|
#define ZFC_RULE 1
|
||||||
#define ZFC_FORMAT 2
|
#define ZFC_FORMAT 2
|
||||||
#define ZFC_TILYEAR 3
|
#define ZFC_TILYEAR 3
|
||||||
@ -245,7 +243,7 @@ static int typecnt;
|
|||||||
#define RF_MONTH 5
|
#define RF_MONTH 5
|
||||||
#define RF_DAY 6
|
#define RF_DAY 6
|
||||||
#define RF_TOD 7
|
#define RF_TOD 7
|
||||||
#define RF_STDOFF 8
|
#define RF_SAVE 8
|
||||||
#define RF_ABBRVAR 9
|
#define RF_ABBRVAR 9
|
||||||
#define RULE_FIELDS 10
|
#define RULE_FIELDS 10
|
||||||
|
|
||||||
@ -389,11 +387,11 @@ static struct attype
|
|||||||
bool dontmerge;
|
bool dontmerge;
|
||||||
unsigned char type;
|
unsigned char type;
|
||||||
} *attypes;
|
} *attypes;
|
||||||
static zic_t gmtoffs[TZ_MAX_TYPES];
|
static zic_t utoffs[TZ_MAX_TYPES];
|
||||||
static char isdsts[TZ_MAX_TYPES];
|
static char isdsts[TZ_MAX_TYPES];
|
||||||
static unsigned char abbrinds[TZ_MAX_TYPES];
|
static unsigned char desigidx[TZ_MAX_TYPES];
|
||||||
static bool ttisstds[TZ_MAX_TYPES];
|
static bool ttisstds[TZ_MAX_TYPES];
|
||||||
static bool ttisgmts[TZ_MAX_TYPES];
|
static bool ttisuts[TZ_MAX_TYPES];
|
||||||
static char chars[TZ_MAX_CHARS];
|
static char chars[TZ_MAX_CHARS];
|
||||||
static zic_t trans[TZ_MAX_LEAPS];
|
static zic_t trans[TZ_MAX_LEAPS];
|
||||||
static zic_t corr[TZ_MAX_LEAPS];
|
static zic_t corr[TZ_MAX_LEAPS];
|
||||||
@ -540,8 +538,9 @@ usage(FILE *stream, int status)
|
|||||||
{
|
{
|
||||||
fprintf(stream,
|
fprintf(stream,
|
||||||
_("%s: usage is %s [ --version ] [ --help ] [ -v ] [ -P ] \\\n"
|
_("%s: usage is %s [ --version ] [ --help ] [ -v ] [ -P ] \\\n"
|
||||||
"\t[ -l localtime ] [ -p posixrules ] [ -d directory ] \\\n"
|
"\t[ -b {slim|fat} ] [ -d directory ] [ -l localtime ]"
|
||||||
"\t[ -t localtime-link ] [ -L leapseconds ] [ -r '[@lo][/@hi]' ] \\\n"
|
" [ -L leapseconds ] \\\n"
|
||||||
|
"\t[ -p posixrules ] [ -r '[@lo][/@hi]' ] [ -t localtime-link ] \\\n"
|
||||||
"\t[ filename ... ]\n\n"
|
"\t[ filename ... ]\n\n"
|
||||||
"Report bugs to %s.\n"),
|
"Report bugs to %s.\n"),
|
||||||
progname, progname, PACKAGE_BUGREPORT);
|
progname, progname, PACKAGE_BUGREPORT);
|
||||||
@ -625,6 +624,21 @@ static const char *leapsec;
|
|||||||
static const char *tzdefault;
|
static const char *tzdefault;
|
||||||
static const char *yitcommand;
|
static const char *yitcommand;
|
||||||
|
|
||||||
|
/* -1 if the TZif output file should be slim, 0 if default, 1 if the
|
||||||
|
output should be fat for backward compatibility. Currently the
|
||||||
|
default is fat, although this may change. */
|
||||||
|
static int bloat;
|
||||||
|
|
||||||
|
static bool
|
||||||
|
want_bloat(void)
|
||||||
|
{
|
||||||
|
return 0 <= bloat;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef ZIC_BLOAT_DEFAULT
|
||||||
|
#define ZIC_BLOAT_DEFAULT "fat"
|
||||||
|
#endif
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
@ -655,11 +669,27 @@ main(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
usage(stdout, EXIT_SUCCESS);
|
usage(stdout, EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
while ((c = getopt(argc, argv, "d:l:L:p:Pr:st:vy:")) != EOF && c != -1)
|
while ((c = getopt(argc, argv, "b:d:l:L:p:Pr:st:vy:")) != EOF && c != -1)
|
||||||
switch (c)
|
switch (c)
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
usage(stderr, EXIT_FAILURE);
|
usage(stderr, EXIT_FAILURE);
|
||||||
|
case 'b':
|
||||||
|
if (strcmp(optarg, "slim") == 0)
|
||||||
|
{
|
||||||
|
if (0 < bloat)
|
||||||
|
error(_("incompatible -b options"));
|
||||||
|
bloat = -1;
|
||||||
|
}
|
||||||
|
else if (strcmp(optarg, "fat") == 0)
|
||||||
|
{
|
||||||
|
if (bloat < 0)
|
||||||
|
error(_("incompatible -b options"));
|
||||||
|
bloat = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
error(_("invalid option: -b '%s'"), optarg);
|
||||||
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
if (directory == NULL)
|
if (directory == NULL)
|
||||||
directory = strdup(optarg);
|
directory = strdup(optarg);
|
||||||
@ -759,6 +789,8 @@ main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
if (optind == argc - 1 && strcmp(argv[optind], "=") == 0)
|
if (optind == argc - 1 && strcmp(argv[optind], "=") == 0)
|
||||||
usage(stderr, EXIT_FAILURE); /* usage message by request */
|
usage(stderr, EXIT_FAILURE); /* usage message by request */
|
||||||
|
if (bloat == 0)
|
||||||
|
bloat = strcmp(ZIC_BLOAT_DEFAULT, "slim") == 0 ? -1 : 1;
|
||||||
if (directory == NULL)
|
if (directory == NULL)
|
||||||
directory = "data";
|
directory = "data";
|
||||||
if (tzdefault == NULL)
|
if (tzdefault == NULL)
|
||||||
@ -1183,7 +1215,7 @@ associate(void)
|
|||||||
* Maybe we have a local standard time offset.
|
* Maybe we have a local standard time offset.
|
||||||
*/
|
*/
|
||||||
eat(zp->z_filename, zp->z_linenum);
|
eat(zp->z_filename, zp->z_linenum);
|
||||||
zp->z_stdoff = getstdoff(zp->z_rule, &zp->z_isdst);
|
zp->z_save = getsave(zp->z_rule, &zp->z_isdst);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note, though, that if there's no rule, a '%s' in the format is
|
* Note, though, that if there's no rule, a '%s' in the format is
|
||||||
@ -1380,10 +1412,10 @@ gethms(char const *string, char const *errstring)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static zic_t
|
static zic_t
|
||||||
getstdoff(char *field, bool *isdst)
|
getsave(char *field, bool *isdst)
|
||||||
{
|
{
|
||||||
int dst = -1;
|
int dst = -1;
|
||||||
zic_t stdoff;
|
zic_t save;
|
||||||
size_t fieldlen = strlen(field);
|
size_t fieldlen = strlen(field);
|
||||||
|
|
||||||
if (fieldlen != 0)
|
if (fieldlen != 0)
|
||||||
@ -1402,9 +1434,9 @@ getstdoff(char *field, bool *isdst)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stdoff = gethms(field, _("invalid saved time"));
|
save = gethms(field, _("invalid saved time"));
|
||||||
*isdst = dst < 0 ? stdoff != 0 : dst;
|
*isdst = dst < 0 ? save != 0 : dst;
|
||||||
return stdoff;
|
return save;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1443,7 +1475,7 @@ inrule(char **fields, int nfields)
|
|||||||
}
|
}
|
||||||
r.r_filename = filename;
|
r.r_filename = filename;
|
||||||
r.r_linenum = linenum;
|
r.r_linenum = linenum;
|
||||||
r.r_stdoff = getstdoff(fields[RF_STDOFF], &r.r_isdst);
|
r.r_save = getsave(fields[RF_SAVE], &r.r_isdst);
|
||||||
rulesub(&r, fields[RF_LOYEAR], fields[RF_HIYEAR], fields[RF_COMMAND],
|
rulesub(&r, fields[RF_LOYEAR], fields[RF_HIYEAR], fields[RF_COMMAND],
|
||||||
fields[RF_MONTH], fields[RF_DAY], fields[RF_TOD]);
|
fields[RF_MONTH], fields[RF_DAY], fields[RF_TOD]);
|
||||||
r.r_name = ecpyalloc(fields[RF_NAME]);
|
r.r_name = ecpyalloc(fields[RF_NAME]);
|
||||||
@ -1509,7 +1541,7 @@ inzsub(char **fields, int nfields, bool iscont)
|
|||||||
char *cp;
|
char *cp;
|
||||||
char *cp1;
|
char *cp1;
|
||||||
static struct zone z;
|
static struct zone z;
|
||||||
int i_gmtoff,
|
int i_stdoff,
|
||||||
i_rule,
|
i_rule,
|
||||||
i_format;
|
i_format;
|
||||||
int i_untilyear,
|
int i_untilyear,
|
||||||
@ -1520,7 +1552,7 @@ inzsub(char **fields, int nfields, bool iscont)
|
|||||||
|
|
||||||
if (iscont)
|
if (iscont)
|
||||||
{
|
{
|
||||||
i_gmtoff = ZFC_GMTOFF;
|
i_stdoff = ZFC_STDOFF;
|
||||||
i_rule = ZFC_RULE;
|
i_rule = ZFC_RULE;
|
||||||
i_format = ZFC_FORMAT;
|
i_format = ZFC_FORMAT;
|
||||||
i_untilyear = ZFC_TILYEAR;
|
i_untilyear = ZFC_TILYEAR;
|
||||||
@ -1533,7 +1565,7 @@ inzsub(char **fields, int nfields, bool iscont)
|
|||||||
return false;
|
return false;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
i_gmtoff = ZF_GMTOFF;
|
i_stdoff = ZF_STDOFF;
|
||||||
i_rule = ZF_RULE;
|
i_rule = ZF_RULE;
|
||||||
i_format = ZF_FORMAT;
|
i_format = ZF_FORMAT;
|
||||||
i_untilyear = ZF_TILYEAR;
|
i_untilyear = ZF_TILYEAR;
|
||||||
@ -1544,7 +1576,7 @@ inzsub(char **fields, int nfields, bool iscont)
|
|||||||
}
|
}
|
||||||
z.z_filename = filename;
|
z.z_filename = filename;
|
||||||
z.z_linenum = linenum;
|
z.z_linenum = linenum;
|
||||||
z.z_gmtoff = gethms(fields[i_gmtoff], _("invalid UT offset"));
|
z.z_stdoff = gethms(fields[i_stdoff], _("invalid UT offset"));
|
||||||
if ((cp = strchr(fields[i_format], '%')) != NULL)
|
if ((cp = strchr(fields[i_format], '%')) != NULL)
|
||||||
{
|
{
|
||||||
if ((*++cp != 's' && *cp != 'z') || strchr(cp, '%')
|
if ((*++cp != 's' && *cp != 'z') || strchr(cp, '%')
|
||||||
@ -1768,7 +1800,7 @@ rulesub(struct rule *rp, const char *loyearp, const char *hiyearp,
|
|||||||
}
|
}
|
||||||
rp->r_month = lp->l_value;
|
rp->r_month = lp->l_value;
|
||||||
rp->r_todisstd = false;
|
rp->r_todisstd = false;
|
||||||
rp->r_todisgmt = false;
|
rp->r_todisut = false;
|
||||||
dp = ecpyalloc(timep);
|
dp = ecpyalloc(timep);
|
||||||
if (*dp != '\0')
|
if (*dp != '\0')
|
||||||
{
|
{
|
||||||
@ -1777,19 +1809,19 @@ rulesub(struct rule *rp, const char *loyearp, const char *hiyearp,
|
|||||||
{
|
{
|
||||||
case 's': /* Standard */
|
case 's': /* Standard */
|
||||||
rp->r_todisstd = true;
|
rp->r_todisstd = true;
|
||||||
rp->r_todisgmt = false;
|
rp->r_todisut = false;
|
||||||
*ep = '\0';
|
*ep = '\0';
|
||||||
break;
|
break;
|
||||||
case 'w': /* Wall */
|
case 'w': /* Wall */
|
||||||
rp->r_todisstd = false;
|
rp->r_todisstd = false;
|
||||||
rp->r_todisgmt = false;
|
rp->r_todisut = false;
|
||||||
*ep = '\0';
|
*ep = '\0';
|
||||||
break;
|
break;
|
||||||
case 'g': /* Greenwich */
|
case 'g': /* Greenwich */
|
||||||
case 'u': /* Universal */
|
case 'u': /* Universal */
|
||||||
case 'z': /* Zulu */
|
case 'z': /* Zulu */
|
||||||
rp->r_todisstd = true;
|
rp->r_todisstd = true;
|
||||||
rp->r_todisgmt = true;
|
rp->r_todisut = true;
|
||||||
*ep = '\0';
|
*ep = '\0';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1977,41 +2009,6 @@ atcomp(const void *avp, const void *bvp)
|
|||||||
return (a < b) ? -1 : (a > b);
|
return (a < b) ? -1 : (a > b);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
swaptypes(int i, int j)
|
|
||||||
{
|
|
||||||
{
|
|
||||||
zic_t t = gmtoffs[i];
|
|
||||||
|
|
||||||
gmtoffs[i] = gmtoffs[j];
|
|
||||||
gmtoffs[j] = t;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
char t = isdsts[i];
|
|
||||||
|
|
||||||
isdsts[i] = isdsts[j];
|
|
||||||
isdsts[j] = t;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
unsigned char t = abbrinds[i];
|
|
||||||
|
|
||||||
abbrinds[i] = abbrinds[j];
|
|
||||||
abbrinds[j] = t;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
bool t = ttisstds[i];
|
|
||||||
|
|
||||||
ttisstds[i] = ttisstds[j];
|
|
||||||
ttisstds[j] = t;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
bool t = ttisgmts[i];
|
|
||||||
|
|
||||||
ttisgmts[i] = ttisgmts[j];
|
|
||||||
ttisgmts[j] = t;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct timerange
|
struct timerange
|
||||||
{
|
{
|
||||||
int defaulttype;
|
int defaulttype;
|
||||||
@ -2091,10 +2088,12 @@ writezone(const char *const name, const char *const string, char version,
|
|||||||
fromi = 0;
|
fromi = 0;
|
||||||
for (; fromi < timecnt; ++fromi)
|
for (; fromi < timecnt; ++fromi)
|
||||||
{
|
{
|
||||||
if (toi != 0 && ((attypes[fromi].at +
|
if (toi != 0
|
||||||
gmtoffs[attypes[toi - 1].type]) <=
|
&& ((attypes[fromi].at
|
||||||
(attypes[toi - 1].at + gmtoffs[toi == 1 ? 0
|
+ utoffs[attypes[toi - 1].type])
|
||||||
: attypes[toi - 2].type])))
|
<= (attypes[toi - 1].at
|
||||||
|
+ utoffs[toi == 1 ? 0
|
||||||
|
: attypes[toi - 2].type])))
|
||||||
{
|
{
|
||||||
attypes[toi - 1].type =
|
attypes[toi - 1].type =
|
||||||
attypes[fromi].type;
|
attypes[fromi].type;
|
||||||
@ -2102,7 +2101,12 @@ writezone(const char *const name, const char *const string, char version,
|
|||||||
}
|
}
|
||||||
if (toi == 0
|
if (toi == 0
|
||||||
|| attypes[fromi].dontmerge
|
|| attypes[fromi].dontmerge
|
||||||
|| attypes[toi - 1].type != attypes[fromi].type)
|
|| (utoffs[attypes[toi - 1].type]
|
||||||
|
!= utoffs[attypes[fromi].type])
|
||||||
|
|| (isdsts[attypes[toi - 1].type]
|
||||||
|
!= isdsts[attypes[fromi].type])
|
||||||
|
|| (desigidx[attypes[toi - 1].type]
|
||||||
|
!= desigidx[attypes[fromi].type]))
|
||||||
attypes[toi++] = attypes[fromi];
|
attypes[toi++] = attypes[fromi];
|
||||||
}
|
}
|
||||||
timecnt = toi;
|
timecnt = toi;
|
||||||
@ -2151,7 +2155,7 @@ writezone(const char *const name, const char *const string, char version,
|
|||||||
* before 32-bit pg_time_t rolls around, and this occurs at a slightly
|
* before 32-bit pg_time_t rolls around, and this occurs at a slightly
|
||||||
* different moment if transitions are leap-second corrected.
|
* different moment if transitions are leap-second corrected.
|
||||||
*/
|
*/
|
||||||
if (WORK_AROUND_QTBUG_53071 && timecnt != 0
|
if (WORK_AROUND_QTBUG_53071 && timecnt != 0 && want_bloat()
|
||||||
&& ats[timecnt - 1] < y2038_boundary - 1 && strchr(string, '<'))
|
&& ats[timecnt - 1] < y2038_boundary - 1 && strchr(string, '<'))
|
||||||
{
|
{
|
||||||
ats[timecnt] = y2038_boundary - 1;
|
ats[timecnt] = y2038_boundary - 1;
|
||||||
@ -2213,7 +2217,9 @@ writezone(const char *const name, const char *const string, char version,
|
|||||||
int old0;
|
int old0;
|
||||||
char omittype[TZ_MAX_TYPES];
|
char omittype[TZ_MAX_TYPES];
|
||||||
int typemap[TZ_MAX_TYPES];
|
int typemap[TZ_MAX_TYPES];
|
||||||
int thistypecnt;
|
int thistypecnt,
|
||||||
|
stdcnt,
|
||||||
|
utcnt;
|
||||||
char thischars[TZ_MAX_CHARS];
|
char thischars[TZ_MAX_CHARS];
|
||||||
int thischarcnt;
|
int thischarcnt;
|
||||||
bool toomanytimes;
|
bool toomanytimes;
|
||||||
@ -2293,7 +2299,6 @@ writezone(const char *const name, const char *const string, char version,
|
|||||||
* in the output instead of OLD0. TYPEMAP also omits unused types.
|
* in the output instead of OLD0. TYPEMAP also omits unused types.
|
||||||
*/
|
*/
|
||||||
old0 = strlen(omittype);
|
old0 = strlen(omittype);
|
||||||
swaptypes(old0, thisdefaulttype);
|
|
||||||
|
|
||||||
#ifndef LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH
|
#ifndef LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH
|
||||||
|
|
||||||
@ -2303,6 +2308,7 @@ writezone(const char *const name, const char *const string, char version,
|
|||||||
* offset, append an (unused) copy of the most recently used type (to
|
* offset, append an (unused) copy of the most recently used type (to
|
||||||
* help get global "altzone" and "timezone" variables set correctly).
|
* help get global "altzone" and "timezone" variables set correctly).
|
||||||
*/
|
*/
|
||||||
|
if (want_bloat())
|
||||||
{
|
{
|
||||||
int mrudst,
|
int mrudst,
|
||||||
mrustd,
|
mrustd,
|
||||||
@ -2317,34 +2323,39 @@ writezone(const char *const name, const char *const string, char version,
|
|||||||
else
|
else
|
||||||
mrustd = types[i];
|
mrustd = types[i];
|
||||||
for (i = old0; i < typecnt; i++)
|
for (i = old0; i < typecnt; i++)
|
||||||
if (!omittype[i])
|
{
|
||||||
|
int h = (i == old0 ? thisdefaulttype
|
||||||
|
: i == thisdefaulttype ? old0 : i);
|
||||||
|
|
||||||
|
if (!omittype[h])
|
||||||
{
|
{
|
||||||
if (isdsts[i])
|
if (isdsts[h])
|
||||||
hidst = i;
|
hidst = i;
|
||||||
else
|
else
|
||||||
histd = i;
|
histd = i;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (hidst >= 0 && mrudst >= 0 && hidst != mrudst &&
|
if (hidst >= 0 && mrudst >= 0 && hidst != mrudst &&
|
||||||
gmtoffs[hidst] != gmtoffs[mrudst])
|
utoffs[hidst] != utoffs[mrudst])
|
||||||
{
|
{
|
||||||
isdsts[mrudst] = -1;
|
isdsts[mrudst] = -1;
|
||||||
type = addtype(gmtoffs[mrudst],
|
type = addtype(utoffs[mrudst],
|
||||||
&chars[abbrinds[mrudst]],
|
&chars[desigidx[mrudst]],
|
||||||
true,
|
true,
|
||||||
ttisstds[mrudst],
|
ttisstds[mrudst],
|
||||||
ttisgmts[mrudst]);
|
ttisuts[mrudst]);
|
||||||
isdsts[mrudst] = 1;
|
isdsts[mrudst] = 1;
|
||||||
omittype[type] = false;
|
omittype[type] = false;
|
||||||
}
|
}
|
||||||
if (histd >= 0 && mrustd >= 0 && histd != mrustd &&
|
if (histd >= 0 && mrustd >= 0 && histd != mrustd &&
|
||||||
gmtoffs[histd] != gmtoffs[mrustd])
|
utoffs[histd] != utoffs[mrustd])
|
||||||
{
|
{
|
||||||
isdsts[mrustd] = -1;
|
isdsts[mrustd] = -1;
|
||||||
type = addtype(gmtoffs[mrustd],
|
type = addtype(utoffs[mrustd],
|
||||||
&chars[abbrinds[mrustd]],
|
&chars[desigidx[mrustd]],
|
||||||
false,
|
false,
|
||||||
ttisstds[mrustd],
|
ttisstds[mrustd],
|
||||||
ttisgmts[mrustd]);
|
ttisuts[mrustd]);
|
||||||
isdsts[mrustd] = 0;
|
isdsts[mrustd] = 0;
|
||||||
omittype[type] = false;
|
omittype[type] = false;
|
||||||
}
|
}
|
||||||
@ -2360,16 +2371,20 @@ writezone(const char *const name, const char *const string, char version,
|
|||||||
|
|
||||||
for (i = 0; i < sizeof indmap / sizeof indmap[0]; ++i)
|
for (i = 0; i < sizeof indmap / sizeof indmap[0]; ++i)
|
||||||
indmap[i] = -1;
|
indmap[i] = -1;
|
||||||
thischarcnt = 0;
|
thischarcnt = stdcnt = utcnt = 0;
|
||||||
for (i = old0; i < typecnt; i++)
|
for (i = old0; i < typecnt; i++)
|
||||||
{
|
{
|
||||||
char *thisabbr;
|
char *thisabbr;
|
||||||
|
|
||||||
if (omittype[i])
|
if (omittype[i])
|
||||||
continue;
|
continue;
|
||||||
if (indmap[abbrinds[i]] >= 0)
|
if (ttisstds[i])
|
||||||
|
stdcnt = thistypecnt;
|
||||||
|
if (ttisuts[i])
|
||||||
|
utcnt = thistypecnt;
|
||||||
|
if (indmap[desigidx[i]] >= 0)
|
||||||
continue;
|
continue;
|
||||||
thisabbr = &chars[abbrinds[i]];
|
thisabbr = &chars[desigidx[i]];
|
||||||
for (j = 0; j < thischarcnt; ++j)
|
for (j = 0; j < thischarcnt; ++j)
|
||||||
if (strcmp(&thischars[j], thisabbr) == 0)
|
if (strcmp(&thischars[j], thisabbr) == 0)
|
||||||
break;
|
break;
|
||||||
@ -2378,14 +2393,21 @@ writezone(const char *const name, const char *const string, char version,
|
|||||||
strcpy(&thischars[thischarcnt], thisabbr);
|
strcpy(&thischars[thischarcnt], thisabbr);
|
||||||
thischarcnt += strlen(thisabbr) + 1;
|
thischarcnt += strlen(thisabbr) + 1;
|
||||||
}
|
}
|
||||||
indmap[abbrinds[i]] = j;
|
indmap[desigidx[i]] = j;
|
||||||
|
}
|
||||||
|
if (pass == 1 && !want_bloat())
|
||||||
|
{
|
||||||
|
utcnt = stdcnt = thisleapcnt = 0;
|
||||||
|
thistimecnt = -locut - hicut;
|
||||||
|
thistypecnt = thischarcnt = 1;
|
||||||
|
thistimelim = thistimei;
|
||||||
}
|
}
|
||||||
#define DO(field) fwrite(tzh.field, sizeof tzh.field, 1, fp)
|
#define DO(field) fwrite(tzh.field, sizeof tzh.field, 1, fp)
|
||||||
tzh = tzh0;
|
tzh = tzh0;
|
||||||
memcpy(tzh.tzh_magic, TZ_MAGIC, sizeof tzh.tzh_magic);
|
memcpy(tzh.tzh_magic, TZ_MAGIC, sizeof tzh.tzh_magic);
|
||||||
tzh.tzh_version[0] = version;
|
tzh.tzh_version[0] = version;
|
||||||
convert(thistypecnt, tzh.tzh_ttisgmtcnt);
|
convert(utcnt, tzh.tzh_ttisutcnt);
|
||||||
convert(thistypecnt, tzh.tzh_ttisstdcnt);
|
convert(stdcnt, tzh.tzh_ttisstdcnt);
|
||||||
convert(thisleapcnt, tzh.tzh_leapcnt);
|
convert(thisleapcnt, tzh.tzh_leapcnt);
|
||||||
convert(locut + thistimecnt + hicut, tzh.tzh_timecnt);
|
convert(locut + thistimecnt + hicut, tzh.tzh_timecnt);
|
||||||
convert(thistypecnt, tzh.tzh_typecnt);
|
convert(thistypecnt, tzh.tzh_typecnt);
|
||||||
@ -2393,13 +2415,22 @@ writezone(const char *const name, const char *const string, char version,
|
|||||||
DO(tzh_magic);
|
DO(tzh_magic);
|
||||||
DO(tzh_version);
|
DO(tzh_version);
|
||||||
DO(tzh_reserved);
|
DO(tzh_reserved);
|
||||||
DO(tzh_ttisgmtcnt);
|
DO(tzh_ttisutcnt);
|
||||||
DO(tzh_ttisstdcnt);
|
DO(tzh_ttisstdcnt);
|
||||||
DO(tzh_leapcnt);
|
DO(tzh_leapcnt);
|
||||||
DO(tzh_timecnt);
|
DO(tzh_timecnt);
|
||||||
DO(tzh_typecnt);
|
DO(tzh_typecnt);
|
||||||
DO(tzh_charcnt);
|
DO(tzh_charcnt);
|
||||||
#undef DO
|
#undef DO
|
||||||
|
if (pass == 1 && !want_bloat())
|
||||||
|
{
|
||||||
|
/* Output a minimal data block with just one time type. */
|
||||||
|
puttzcode(0, fp); /* utoff */
|
||||||
|
putc(0, fp); /* dst */
|
||||||
|
putc(0, fp); /* index of abbreviation */
|
||||||
|
putc(0, fp); /* empty-string abbreviation */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* PG: print current timezone abbreviations if requested */
|
/* PG: print current timezone abbreviations if requested */
|
||||||
if (print_abbrevs && pass == 2)
|
if (print_abbrevs && pass == 2)
|
||||||
@ -2410,14 +2441,14 @@ writezone(const char *const name, const char *const string, char version,
|
|||||||
if (i == thistimelim - 1 || ats[i + 1] > print_cutoff)
|
if (i == thistimelim - 1 || ats[i + 1] > print_cutoff)
|
||||||
{
|
{
|
||||||
unsigned char tm = types[i];
|
unsigned char tm = types[i];
|
||||||
char *thisabbrev = &thischars[indmap[abbrinds[tm]]];
|
char *thisabbrev = &thischars[indmap[desigidx[tm]]];
|
||||||
|
|
||||||
/* filter out assorted junk entries */
|
/* filter out assorted junk entries */
|
||||||
if (strcmp(thisabbrev, GRANDPARENTED) != 0 &&
|
if (strcmp(thisabbrev, GRANDPARENTED) != 0 &&
|
||||||
strcmp(thisabbrev, "zzz") != 0)
|
strcmp(thisabbrev, "zzz") != 0)
|
||||||
fprintf(stdout, "%s\t" INT64_FORMAT "%s\n",
|
fprintf(stdout, "%s\t" INT64_FORMAT "%s\n",
|
||||||
thisabbrev,
|
thisabbrev,
|
||||||
gmtoffs[tm],
|
utoffs[tm],
|
||||||
isdsts[tm] ? "\tD" : "");
|
isdsts[tm] ? "\tD" : "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2425,14 +2456,14 @@ writezone(const char *const name, const char *const string, char version,
|
|||||||
if (thistimei >= thistimelim)
|
if (thistimei >= thistimelim)
|
||||||
{
|
{
|
||||||
unsigned char tm = defaulttype;
|
unsigned char tm = defaulttype;
|
||||||
char *thisabbrev = &thischars[indmap[abbrinds[tm]]];
|
char *thisabbrev = &thischars[indmap[desigidx[tm]]];
|
||||||
|
|
||||||
/* filter out assorted junk entries */
|
/* filter out assorted junk entries */
|
||||||
if (strcmp(thisabbrev, GRANDPARENTED) != 0 &&
|
if (strcmp(thisabbrev, GRANDPARENTED) != 0 &&
|
||||||
strcmp(thisabbrev, "zzz") != 0)
|
strcmp(thisabbrev, "zzz") != 0)
|
||||||
fprintf(stdout, "%s\t" INT64_FORMAT "%s\n",
|
fprintf(stdout, "%s\t" INT64_FORMAT "%s\n",
|
||||||
thisabbrev,
|
thisabbrev,
|
||||||
gmtoffs[tm],
|
utoffs[tm],
|
||||||
isdsts[tm] ? "\tD" : "");
|
isdsts[tm] ? "\tD" : "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2465,12 +2496,17 @@ writezone(const char *const name, const char *const string, char version,
|
|||||||
putc(currenttype, fp);
|
putc(currenttype, fp);
|
||||||
|
|
||||||
for (i = old0; i < typecnt; i++)
|
for (i = old0; i < typecnt; i++)
|
||||||
if (!omittype[i])
|
{
|
||||||
|
int h = (i == old0 ? thisdefaulttype
|
||||||
|
: i == thisdefaulttype ? old0 : i);
|
||||||
|
|
||||||
|
if (!omittype[h])
|
||||||
{
|
{
|
||||||
puttzcode(gmtoffs[i], fp);
|
puttzcode(utoffs[h], fp);
|
||||||
putc(isdsts[i], fp);
|
putc(isdsts[h], fp);
|
||||||
putc((unsigned char) indmap[abbrinds[i]], fp);
|
putc(indmap[desigidx[h]], fp);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (thischarcnt != 0)
|
if (thischarcnt != 0)
|
||||||
fwrite(thischars, sizeof thischars[0],
|
fwrite(thischars, sizeof thischars[0],
|
||||||
thischarcnt, fp);
|
thischarcnt, fp);
|
||||||
@ -2498,20 +2534,21 @@ writezone(const char *const name, const char *const string, char version,
|
|||||||
++j;
|
++j;
|
||||||
j = types[j - 1];
|
j = types[j - 1];
|
||||||
}
|
}
|
||||||
todo = tadd(trans[i], -gmtoffs[j]);
|
todo = tadd(trans[i], -utoffs[j]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
todo = trans[i];
|
todo = trans[i];
|
||||||
puttzcodepass(todo, fp, pass);
|
puttzcodepass(todo, fp, pass);
|
||||||
puttzcode(corr[i], fp);
|
puttzcode(corr[i], fp);
|
||||||
}
|
}
|
||||||
for (i = old0; i < typecnt; i++)
|
if (stdcnt != 0)
|
||||||
if (!omittype[i])
|
for (i = old0; i < typecnt; i++)
|
||||||
putc(ttisstds[i], fp);
|
if (!omittype[i])
|
||||||
for (i = old0; i < typecnt; i++)
|
putc(ttisstds[i], fp);
|
||||||
if (!omittype[i])
|
if (utcnt != 0)
|
||||||
putc(ttisgmts[i], fp);
|
for (i = old0; i < typecnt; i++)
|
||||||
swaptypes(old0, thisdefaulttype);
|
if (!omittype[i])
|
||||||
|
putc(ttisuts[i], fp);
|
||||||
}
|
}
|
||||||
fprintf(fp, "\n%s\n", string);
|
fprintf(fp, "\n%s\n", string);
|
||||||
close_file(fp, directory, name);
|
close_file(fp, directory, name);
|
||||||
@ -2564,7 +2601,7 @@ abbroffset(char *buf, zic_t offset)
|
|||||||
|
|
||||||
static size_t
|
static size_t
|
||||||
doabbr(char *abbr, struct zone const *zp, char const *letters,
|
doabbr(char *abbr, struct zone const *zp, char const *letters,
|
||||||
bool isdst, zic_t stdoff, bool doquotes)
|
bool isdst, zic_t save, bool doquotes)
|
||||||
{
|
{
|
||||||
char *cp;
|
char *cp;
|
||||||
char *slashp;
|
char *slashp;
|
||||||
@ -2577,7 +2614,7 @@ doabbr(char *abbr, struct zone const *zp, char const *letters,
|
|||||||
char letterbuf[PERCENT_Z_LEN_BOUND + 1];
|
char letterbuf[PERCENT_Z_LEN_BOUND + 1];
|
||||||
|
|
||||||
if (zp->z_format_specifier == 'z')
|
if (zp->z_format_specifier == 'z')
|
||||||
letters = abbroffset(letterbuf, zp->z_gmtoff + stdoff);
|
letters = abbroffset(letterbuf, zp->z_stdoff + save);
|
||||||
else if (!letters)
|
else if (!letters)
|
||||||
letters = "%s";
|
letters = "%s";
|
||||||
sprintf(abbr, format, letters);
|
sprintf(abbr, format, letters);
|
||||||
@ -2649,8 +2686,7 @@ stringoffset(char *result, zic_t offset)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
stringrule(char *result, const struct rule *const rp, const zic_t dstoff,
|
stringrule(char *result, struct rule *const rp, zic_t save, zic_t stdoff)
|
||||||
const zic_t gmtoff)
|
|
||||||
{
|
{
|
||||||
zic_t tod = rp->r_tod;
|
zic_t tod = rp->r_tod;
|
||||||
int compat = 0;
|
int compat = 0;
|
||||||
@ -2707,10 +2743,10 @@ stringrule(char *result, const struct rule *const rp, const zic_t dstoff,
|
|||||||
result += sprintf(result, "M%d.%d.%d",
|
result += sprintf(result, "M%d.%d.%d",
|
||||||
rp->r_month + 1, week, wday);
|
rp->r_month + 1, week, wday);
|
||||||
}
|
}
|
||||||
if (rp->r_todisgmt)
|
if (rp->r_todisut)
|
||||||
tod += gmtoff;
|
tod += stdoff;
|
||||||
if (rp->r_todisstd && !rp->r_isdst)
|
if (rp->r_todisstd && !rp->r_isdst)
|
||||||
tod += dstoff;
|
tod += save;
|
||||||
if (tod != 2 * SECSPERMIN * MINSPERHOUR)
|
if (tod != 2 * SECSPERMIN * MINSPERHOUR)
|
||||||
{
|
{
|
||||||
*result++ = '/';
|
*result++ = '/';
|
||||||
@ -2744,10 +2780,6 @@ rule_cmp(struct rule const *a, struct rule const *b)
|
|||||||
return a->r_dayofmonth - b->r_dayofmonth;
|
return a->r_dayofmonth - b->r_dayofmonth;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
YEAR_BY_YEAR_ZONE = 1};
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
stringzone(char *result, struct zone const *zpfirst, ptrdiff_t zonecount)
|
stringzone(char *result, struct zone const *zpfirst, ptrdiff_t zonecount)
|
||||||
{
|
{
|
||||||
@ -2813,15 +2845,6 @@ stringzone(char *result, struct zone const *zpfirst, ptrdiff_t zonecount)
|
|||||||
if (rule_cmp(stdrp, rp) < 0)
|
if (rule_cmp(stdrp, rp) < 0)
|
||||||
stdrp = rp;
|
stdrp = rp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Horrid special case: if year is 2037, presume this is a zone
|
|
||||||
* handled on a year-by-year basis; do not try to apply a rule to the
|
|
||||||
* zone.
|
|
||||||
*/
|
|
||||||
if (stdrp != NULL && stdrp->r_hiyear == 2037)
|
|
||||||
return YEAR_BY_YEAR_ZONE;
|
|
||||||
|
|
||||||
if (stdrp != NULL && stdrp->r_isdst)
|
if (stdrp != NULL && stdrp->r_isdst)
|
||||||
{
|
{
|
||||||
/* Perpetual DST. */
|
/* Perpetual DST. */
|
||||||
@ -2829,17 +2852,17 @@ stringzone(char *result, struct zone const *zpfirst, ptrdiff_t zonecount)
|
|||||||
dstr.r_dycode = DC_DOM;
|
dstr.r_dycode = DC_DOM;
|
||||||
dstr.r_dayofmonth = 1;
|
dstr.r_dayofmonth = 1;
|
||||||
dstr.r_tod = 0;
|
dstr.r_tod = 0;
|
||||||
dstr.r_todisstd = dstr.r_todisgmt = false;
|
dstr.r_todisstd = dstr.r_todisut = false;
|
||||||
dstr.r_isdst = stdrp->r_isdst;
|
dstr.r_isdst = stdrp->r_isdst;
|
||||||
dstr.r_stdoff = stdrp->r_stdoff;
|
dstr.r_save = stdrp->r_save;
|
||||||
dstr.r_abbrvar = stdrp->r_abbrvar;
|
dstr.r_abbrvar = stdrp->r_abbrvar;
|
||||||
stdr.r_month = TM_DECEMBER;
|
stdr.r_month = TM_DECEMBER;
|
||||||
stdr.r_dycode = DC_DOM;
|
stdr.r_dycode = DC_DOM;
|
||||||
stdr.r_dayofmonth = 31;
|
stdr.r_dayofmonth = 31;
|
||||||
stdr.r_tod = SECSPERDAY + stdrp->r_stdoff;
|
stdr.r_tod = SECSPERDAY + stdrp->r_save;
|
||||||
stdr.r_todisstd = stdr.r_todisgmt = false;
|
stdr.r_todisstd = stdr.r_todisut = false;
|
||||||
stdr.r_isdst = false;
|
stdr.r_isdst = false;
|
||||||
stdr.r_stdoff = 0;
|
stdr.r_save = 0;
|
||||||
stdr.r_abbrvar
|
stdr.r_abbrvar
|
||||||
= (stdabbrrp ? stdabbrrp->r_abbrvar : "");
|
= (stdabbrrp ? stdabbrrp->r_abbrvar : "");
|
||||||
dstrp = &dstr;
|
dstrp = &dstr;
|
||||||
@ -2850,7 +2873,7 @@ stringzone(char *result, struct zone const *zpfirst, ptrdiff_t zonecount)
|
|||||||
return -1;
|
return -1;
|
||||||
abbrvar = (stdrp == NULL) ? "" : stdrp->r_abbrvar;
|
abbrvar = (stdrp == NULL) ? "" : stdrp->r_abbrvar;
|
||||||
len = doabbr(result, zp, abbrvar, false, 0, true);
|
len = doabbr(result, zp, abbrvar, false, 0, true);
|
||||||
offsetlen = stringoffset(result + len, -zp->z_gmtoff);
|
offsetlen = stringoffset(result + len, -zp->z_stdoff);
|
||||||
if (!offsetlen)
|
if (!offsetlen)
|
||||||
{
|
{
|
||||||
result[0] = '\0';
|
result[0] = '\0';
|
||||||
@ -2860,11 +2883,11 @@ stringzone(char *result, struct zone const *zpfirst, ptrdiff_t zonecount)
|
|||||||
if (dstrp == NULL)
|
if (dstrp == NULL)
|
||||||
return compat;
|
return compat;
|
||||||
len += doabbr(result + len, zp, dstrp->r_abbrvar,
|
len += doabbr(result + len, zp, dstrp->r_abbrvar,
|
||||||
dstrp->r_isdst, dstrp->r_stdoff, true);
|
dstrp->r_isdst, dstrp->r_save, true);
|
||||||
if (dstrp->r_stdoff != SECSPERMIN * MINSPERHOUR)
|
if (dstrp->r_save != SECSPERMIN * MINSPERHOUR)
|
||||||
{
|
{
|
||||||
offsetlen = stringoffset(result + len,
|
offsetlen = stringoffset(result + len,
|
||||||
-(zp->z_gmtoff + dstrp->r_stdoff));
|
-(zp->z_stdoff + dstrp->r_save));
|
||||||
if (!offsetlen)
|
if (!offsetlen)
|
||||||
{
|
{
|
||||||
result[0] = '\0';
|
result[0] = '\0';
|
||||||
@ -2873,7 +2896,7 @@ stringzone(char *result, struct zone const *zpfirst, ptrdiff_t zonecount)
|
|||||||
len += offsetlen;
|
len += offsetlen;
|
||||||
}
|
}
|
||||||
result[len++] = ',';
|
result[len++] = ',';
|
||||||
c = stringrule(result + len, dstrp, dstrp->r_stdoff, zp->z_gmtoff);
|
c = stringrule(result + len, dstrp, dstrp->r_save, zp->z_stdoff);
|
||||||
if (c < 0)
|
if (c < 0)
|
||||||
{
|
{
|
||||||
result[0] = '\0';
|
result[0] = '\0';
|
||||||
@ -2883,7 +2906,7 @@ stringzone(char *result, struct zone const *zpfirst, ptrdiff_t zonecount)
|
|||||||
compat = c;
|
compat = c;
|
||||||
len += strlen(result + len);
|
len += strlen(result + len);
|
||||||
result[len++] = ',';
|
result[len++] = ',';
|
||||||
c = stringrule(result + len, stdrp, dstrp->r_stdoff, zp->z_gmtoff);
|
c = stringrule(result + len, stdrp, dstrp->r_save, zp->z_stdoff);
|
||||||
if (c < 0)
|
if (c < 0)
|
||||||
{
|
{
|
||||||
result[0] = '\0';
|
result[0] = '\0';
|
||||||
@ -2905,12 +2928,12 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
|
|||||||
useuntil;
|
useuntil;
|
||||||
zic_t starttime,
|
zic_t starttime,
|
||||||
untiltime;
|
untiltime;
|
||||||
zic_t gmtoff;
|
|
||||||
zic_t stdoff;
|
zic_t stdoff;
|
||||||
|
zic_t save;
|
||||||
zic_t year;
|
zic_t year;
|
||||||
zic_t startoff;
|
zic_t startoff;
|
||||||
bool startttisstd;
|
bool startttisstd;
|
||||||
bool startttisgmt;
|
bool startttisut;
|
||||||
int type;
|
int type;
|
||||||
char *startbuf;
|
char *startbuf;
|
||||||
char *ab;
|
char *ab;
|
||||||
@ -2948,7 +2971,7 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
|
|||||||
* startttisstd.
|
* startttisstd.
|
||||||
*/
|
*/
|
||||||
startttisstd = false;
|
startttisstd = false;
|
||||||
startttisgmt = false;
|
startttisut = false;
|
||||||
min_year = max_year = EPOCH_YEAR;
|
min_year = max_year = EPOCH_YEAR;
|
||||||
if (leapseen)
|
if (leapseen)
|
||||||
{
|
{
|
||||||
@ -2977,14 +3000,14 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
|
|||||||
*/
|
*/
|
||||||
compat = stringzone(envvar, zpfirst, zonecount);
|
compat = stringzone(envvar, zpfirst, zonecount);
|
||||||
version = compat < 2013 ? ZIC_VERSION_PRE_2013 : ZIC_VERSION;
|
version = compat < 2013 ? ZIC_VERSION_PRE_2013 : ZIC_VERSION;
|
||||||
do_extend = compat < 0 || compat == YEAR_BY_YEAR_ZONE;
|
do_extend = compat < 0;
|
||||||
if (noise)
|
if (noise)
|
||||||
{
|
{
|
||||||
if (!*envvar)
|
if (!*envvar)
|
||||||
warning("%s %s",
|
warning("%s %s",
|
||||||
_("no POSIX environment variable for zone"),
|
_("no POSIX environment variable for zone"),
|
||||||
zpfirst->z_name);
|
zpfirst->z_name);
|
||||||
else if (compat != 0 && compat != YEAR_BY_YEAR_ZONE)
|
else if (compat != 0)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Circa-COMPAT clients, and earlier clients, might not work for
|
* Circa-COMPAT clients, and earlier clients, might not work for
|
||||||
@ -3033,37 +3056,43 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
|
|||||||
max_year = min_year + years_of_observations;
|
max_year = min_year + years_of_observations;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* For the benefit of older systems, generate data from 1900 through 2038.
|
|
||||||
*/
|
|
||||||
if (min_year > 1900)
|
|
||||||
min_year = 1900;
|
|
||||||
max_year0 = max_year;
|
max_year0 = max_year;
|
||||||
if (max_year < 2038)
|
if (want_bloat())
|
||||||
max_year = 2038;
|
{
|
||||||
|
/*
|
||||||
|
* For the benefit of older systems, generate data from 1900 through
|
||||||
|
* 2038.
|
||||||
|
*/
|
||||||
|
if (min_year > 1900)
|
||||||
|
min_year = 1900;
|
||||||
|
if (max_year < 2038)
|
||||||
|
max_year = 2038;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < zonecount; ++i)
|
for (i = 0; i < zonecount; ++i)
|
||||||
{
|
{
|
||||||
|
struct rule *prevrp = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A guess that may well be corrected later.
|
* A guess that may well be corrected later.
|
||||||
*/
|
*/
|
||||||
stdoff = 0;
|
save = 0;
|
||||||
zp = &zpfirst[i];
|
zp = &zpfirst[i];
|
||||||
usestart = i > 0 && (zp - 1)->z_untiltime > min_time;
|
usestart = i > 0 && (zp - 1)->z_untiltime > min_time;
|
||||||
useuntil = i < (zonecount - 1);
|
useuntil = i < (zonecount - 1);
|
||||||
if (useuntil && zp->z_untiltime <= min_time)
|
if (useuntil && zp->z_untiltime <= min_time)
|
||||||
continue;
|
continue;
|
||||||
gmtoff = zp->z_gmtoff;
|
stdoff = zp->z_stdoff;
|
||||||
eat(zp->z_filename, zp->z_linenum);
|
eat(zp->z_filename, zp->z_linenum);
|
||||||
*startbuf = '\0';
|
*startbuf = '\0';
|
||||||
startoff = zp->z_gmtoff;
|
startoff = zp->z_stdoff;
|
||||||
if (zp->z_nrules == 0)
|
if (zp->z_nrules == 0)
|
||||||
{
|
{
|
||||||
stdoff = zp->z_stdoff;
|
save = zp->z_save;
|
||||||
doabbr(startbuf, zp, NULL, zp->z_isdst, stdoff, false);
|
doabbr(startbuf, zp, NULL, zp->z_isdst, save, false);
|
||||||
type = addtype(oadd(zp->z_gmtoff, stdoff),
|
type = addtype(oadd(zp->z_stdoff, save),
|
||||||
startbuf, zp->z_isdst, startttisstd,
|
startbuf, zp->z_isdst, startttisstd,
|
||||||
startttisgmt);
|
startttisut);
|
||||||
if (usestart)
|
if (usestart)
|
||||||
{
|
{
|
||||||
addtt(starttime, type);
|
addtt(starttime, type);
|
||||||
@ -3109,16 +3138,16 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
|
|||||||
if (useuntil)
|
if (useuntil)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Turn untiltime into UT assuming the current gmtoff
|
* Turn untiltime into UT assuming the current stdoff
|
||||||
* and stdoff values.
|
* and save values.
|
||||||
*/
|
*/
|
||||||
untiltime = zp->z_untiltime;
|
untiltime = zp->z_untiltime;
|
||||||
if (!zp->z_untilrule.r_todisgmt)
|
if (!zp->z_untilrule.r_todisut)
|
||||||
untiltime = tadd(untiltime,
|
|
||||||
-gmtoff);
|
|
||||||
if (!zp->z_untilrule.r_todisstd)
|
|
||||||
untiltime = tadd(untiltime,
|
untiltime = tadd(untiltime,
|
||||||
-stdoff);
|
-stdoff);
|
||||||
|
if (!zp->z_untilrule.r_todisstd)
|
||||||
|
untiltime = tadd(untiltime,
|
||||||
|
-save);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -3133,9 +3162,9 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
|
|||||||
continue;
|
continue;
|
||||||
eats(zp->z_filename, zp->z_linenum,
|
eats(zp->z_filename, zp->z_linenum,
|
||||||
rp->r_filename, rp->r_linenum);
|
rp->r_filename, rp->r_linenum);
|
||||||
offset = rp->r_todisgmt ? 0 : gmtoff;
|
offset = rp->r_todisut ? 0 : stdoff;
|
||||||
if (!rp->r_todisstd)
|
if (!rp->r_todisstd)
|
||||||
offset = oadd(offset, stdoff);
|
offset = oadd(offset, save);
|
||||||
jtime = rp->r_temp;
|
jtime = rp->r_temp;
|
||||||
if (jtime == min_time ||
|
if (jtime == min_time ||
|
||||||
jtime == max_time)
|
jtime == max_time)
|
||||||
@ -3166,41 +3195,46 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
|
|||||||
rp->r_todo = false;
|
rp->r_todo = false;
|
||||||
if (useuntil && ktime >= untiltime)
|
if (useuntil && ktime >= untiltime)
|
||||||
break;
|
break;
|
||||||
stdoff = rp->r_stdoff;
|
save = rp->r_save;
|
||||||
if (usestart && ktime == starttime)
|
if (usestart && ktime == starttime)
|
||||||
usestart = false;
|
usestart = false;
|
||||||
if (usestart)
|
if (usestart)
|
||||||
{
|
{
|
||||||
if (ktime < starttime)
|
if (ktime < starttime)
|
||||||
{
|
{
|
||||||
startoff = oadd(zp->z_gmtoff,
|
startoff = oadd(zp->z_stdoff,
|
||||||
stdoff);
|
save);
|
||||||
doabbr(startbuf, zp,
|
doabbr(startbuf, zp,
|
||||||
rp->r_abbrvar,
|
rp->r_abbrvar,
|
||||||
rp->r_isdst,
|
rp->r_isdst,
|
||||||
rp->r_stdoff,
|
rp->r_save,
|
||||||
false);
|
false);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (*startbuf == '\0' &&
|
if (*startbuf == '\0'
|
||||||
startoff == oadd(zp->z_gmtoff,
|
&& startoff == oadd(zp->z_stdoff,
|
||||||
stdoff))
|
save))
|
||||||
{
|
{
|
||||||
doabbr(startbuf,
|
doabbr(startbuf,
|
||||||
zp,
|
zp,
|
||||||
rp->r_abbrvar,
|
rp->r_abbrvar,
|
||||||
rp->r_isdst,
|
rp->r_isdst,
|
||||||
rp->r_stdoff,
|
rp->r_save,
|
||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
eats(zp->z_filename, zp->z_linenum,
|
eats(zp->z_filename, zp->z_linenum,
|
||||||
rp->r_filename, rp->r_linenum);
|
rp->r_filename, rp->r_linenum);
|
||||||
doabbr(ab, zp, rp->r_abbrvar,
|
doabbr(ab, zp, rp->r_abbrvar,
|
||||||
rp->r_isdst, rp->r_stdoff, false);
|
rp->r_isdst, rp->r_save, false);
|
||||||
offset = oadd(zp->z_gmtoff, rp->r_stdoff);
|
offset = oadd(zp->z_stdoff, rp->r_save);
|
||||||
|
if (!want_bloat() && !useuntil && !do_extend
|
||||||
|
&& prevrp
|
||||||
|
&& rp->r_hiyear == ZIC_MAX
|
||||||
|
&& prevrp->r_hiyear == ZIC_MAX)
|
||||||
|
break;
|
||||||
type = addtype(offset, ab, rp->r_isdst,
|
type = addtype(offset, ab, rp->r_isdst,
|
||||||
rp->r_todisstd, rp->r_todisgmt);
|
rp->r_todisstd, rp->r_todisut);
|
||||||
if (defaulttype < 0 && !rp->r_isdst)
|
if (defaulttype < 0 && !rp->r_isdst)
|
||||||
defaulttype = type;
|
defaulttype = type;
|
||||||
if (rp->r_hiyear == ZIC_MAX
|
if (rp->r_hiyear == ZIC_MAX
|
||||||
@ -3208,6 +3242,7 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
|
|||||||
&& ktime < attypes[lastatmax].at))
|
&& ktime < attypes[lastatmax].at))
|
||||||
lastatmax = timecnt;
|
lastatmax = timecnt;
|
||||||
addtt(ktime, type);
|
addtt(ktime, type);
|
||||||
|
prevrp = rp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (usestart)
|
if (usestart)
|
||||||
@ -3222,10 +3257,10 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
|
|||||||
error(_("cannot determine time zone abbreviation to use just after until time"));
|
error(_("cannot determine time zone abbreviation to use just after until time"));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bool isdst = startoff != zp->z_gmtoff;
|
bool isdst = startoff != zp->z_stdoff;
|
||||||
|
|
||||||
type = addtype(startoff, startbuf, isdst,
|
type = addtype(startoff, startbuf, isdst,
|
||||||
startttisstd, startttisgmt);
|
startttisstd, startttisut);
|
||||||
if (defaulttype < 0 && !isdst)
|
if (defaulttype < 0 && !isdst)
|
||||||
defaulttype = type;
|
defaulttype = type;
|
||||||
addtt(starttime, type);
|
addtt(starttime, type);
|
||||||
@ -3238,12 +3273,12 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
|
|||||||
if (useuntil)
|
if (useuntil)
|
||||||
{
|
{
|
||||||
startttisstd = zp->z_untilrule.r_todisstd;
|
startttisstd = zp->z_untilrule.r_todisstd;
|
||||||
startttisgmt = zp->z_untilrule.r_todisgmt;
|
startttisut = zp->z_untilrule.r_todisut;
|
||||||
starttime = zp->z_untiltime;
|
starttime = zp->z_untiltime;
|
||||||
if (!startttisstd)
|
if (!startttisstd)
|
||||||
|
starttime = tadd(starttime, -save);
|
||||||
|
if (!startttisut)
|
||||||
starttime = tadd(starttime, -stdoff);
|
starttime = tadd(starttime, -stdoff);
|
||||||
if (!startttisgmt)
|
|
||||||
starttime = tadd(starttime, -gmtoff);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (defaulttype < 0)
|
if (defaulttype < 0)
|
||||||
@ -3295,22 +3330,31 @@ addtt(zic_t starttime, int type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
addtype(zic_t gmtoff, char const *abbr, bool isdst, bool ttisstd, bool ttisgmt)
|
addtype(zic_t utoff, char const *abbr, bool isdst, bool ttisstd, bool ttisut)
|
||||||
{
|
{
|
||||||
int i,
|
int i,
|
||||||
j;
|
j;
|
||||||
|
|
||||||
/*
|
if (!(-1L - 2147483647L <= utoff && utoff <= 2147483647L))
|
||||||
* See if there's already an entry for this zone type. If so, just return
|
|
||||||
* its index.
|
|
||||||
*/
|
|
||||||
for (i = 0; i < typecnt; ++i)
|
|
||||||
{
|
{
|
||||||
if (gmtoff == gmtoffs[i] && isdst == isdsts[i] &&
|
error(_("UT offset out of range"));
|
||||||
strcmp(abbr, &chars[abbrinds[i]]) == 0 &&
|
exit(EXIT_FAILURE);
|
||||||
ttisstd == ttisstds[i] &&
|
}
|
||||||
ttisgmt == ttisgmts[i])
|
if (!want_bloat())
|
||||||
return i;
|
ttisstd = ttisut = false;
|
||||||
|
|
||||||
|
for (j = 0; j < charcnt; ++j)
|
||||||
|
if (strcmp(&chars[j], abbr) == 0)
|
||||||
|
break;
|
||||||
|
if (j == charcnt)
|
||||||
|
newabbr(abbr);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* If there's already an entry, return its index. */
|
||||||
|
for (i = 0; i < typecnt; i++)
|
||||||
|
if (utoff == utoffs[i] && isdst == isdsts[i] && j == desigidx[i]
|
||||||
|
&& ttisstd == ttisstds[i] && ttisut == ttisuts[i])
|
||||||
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -3321,23 +3365,12 @@ addtype(zic_t gmtoff, char const *abbr, bool isdst, bool ttisstd, bool ttisgmt)
|
|||||||
error(_("too many local time types"));
|
error(_("too many local time types"));
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
if (!(-1L - 2147483647L <= gmtoff && gmtoff <= 2147483647L))
|
i = typecnt++;
|
||||||
{
|
utoffs[i] = utoff;
|
||||||
error(_("UT offset out of range"));
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
gmtoffs[i] = gmtoff;
|
|
||||||
isdsts[i] = isdst;
|
isdsts[i] = isdst;
|
||||||
ttisstds[i] = ttisstd;
|
ttisstds[i] = ttisstd;
|
||||||
ttisgmts[i] = ttisgmt;
|
ttisuts[i] = ttisut;
|
||||||
|
desigidx[i] = j;
|
||||||
for (j = 0; j < charcnt; ++j)
|
|
||||||
if (strcmp(&chars[j], abbr) == 0)
|
|
||||||
break;
|
|
||||||
if (j == charcnt)
|
|
||||||
newabbr(abbr);
|
|
||||||
abbrinds[i] = j;
|
|
||||||
++typecnt;
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3671,9 +3704,9 @@ byword(const char *word, const struct lookup *table)
|
|||||||
return NULL; /* multiple inexact matches */
|
return NULL; /* multiple inexact matches */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Warn about any backward-compatibility issue with pre-2017c zic. */
|
if (foundlp && noise)
|
||||||
if (foundlp)
|
|
||||||
{
|
{
|
||||||
|
/* Warn about any backward-compatibility issue with pre-2017c zic. */
|
||||||
bool pre_2017c_match = false;
|
bool pre_2017c_match = false;
|
||||||
|
|
||||||
for (lp = table; lp->l_word; lp++)
|
for (lp = table; lp->l_word; lp++)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user