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
|
||||
==============
|
||||
|
||||
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
|
||||
original tzcode library, but diffs in the upstream version should usually
|
||||
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
|
||||
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
|
||||
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;
|
||||
|
||||
/* Initialize *S to a value based on GMTOFF, ISDST, and ABBRIND. */
|
||||
/* Initialize *S to a value based on UTOFF, ISDST, and DESIGIDX. */
|
||||
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_abbrind = abbrind;
|
||||
s->tt_desigidx = desigidx;
|
||||
s->tt_ttisstd = false;
|
||||
s->tt_ttisgmt = false;
|
||||
s->tt_ttisut = false;
|
||||
}
|
||||
|
||||
static int32
|
||||
@ -251,7 +251,7 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
|
||||
for (stored = 4; stored <= 8; stored *= 2)
|
||||
{
|
||||
int32 ttisstdcnt = detzcode(up->tzhead.tzh_ttisstdcnt);
|
||||
int32 ttisgmtcnt = detzcode(up->tzhead.tzh_ttisgmtcnt);
|
||||
int32 ttisutcnt = detzcode(up->tzhead.tzh_ttisutcnt);
|
||||
int64 prevtr = 0;
|
||||
int32 prevcorr = 0;
|
||||
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 <= charcnt && charcnt < TZ_MAX_CHARS
|
||||
&& (ttisstdcnt == typecnt || ttisstdcnt == 0)
|
||||
&& (ttisgmtcnt == typecnt || ttisgmtcnt == 0)))
|
||||
&& (ttisutcnt == typecnt || ttisutcnt == 0)))
|
||||
return EINVAL;
|
||||
if (nread
|
||||
< (tzheadsize /* struct tzhead */
|
||||
@ -280,7 +280,7 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
|
||||
+ charcnt /* chars */
|
||||
+ leapcnt * (stored + 4) /* lsinfos */
|
||||
+ ttisstdcnt /* ttisstds */
|
||||
+ ttisgmtcnt)) /* ttisgmts */
|
||||
+ ttisutcnt)) /* ttisuts */
|
||||
return EINVAL;
|
||||
sp->leapcnt = leapcnt;
|
||||
sp->timecnt = timecnt;
|
||||
@ -332,19 +332,19 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
|
||||
{
|
||||
struct ttinfo *ttisp;
|
||||
unsigned char isdst,
|
||||
abbrind;
|
||||
desigidx;
|
||||
|
||||
ttisp = &sp->ttis[i];
|
||||
ttisp->tt_gmtoff = detzcode(p);
|
||||
ttisp->tt_utoff = detzcode(p);
|
||||
p += 4;
|
||||
isdst = *p++;
|
||||
if (!(isdst < 2))
|
||||
return EINVAL;
|
||||
ttisp->tt_isdst = isdst;
|
||||
abbrind = *p++;
|
||||
if (!(abbrind < sp->charcnt))
|
||||
desigidx = *p++;
|
||||
if (!(desigidx < sp->charcnt))
|
||||
return EINVAL;
|
||||
ttisp->tt_abbrind = abbrind;
|
||||
ttisp->tt_desigidx = desigidx;
|
||||
}
|
||||
for (i = 0; i < sp->charcnt; ++i)
|
||||
sp->chars[i] = *p++;
|
||||
@ -398,13 +398,13 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
|
||||
struct ttinfo *ttisp;
|
||||
|
||||
ttisp = &sp->ttis[i];
|
||||
if (ttisgmtcnt == 0)
|
||||
ttisp->tt_ttisgmt = false;
|
||||
if (ttisutcnt == 0)
|
||||
ttisp->tt_ttisut = false;
|
||||
else
|
||||
{
|
||||
if (*p != true && *p != false)
|
||||
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++)
|
||||
{
|
||||
char *tsabbr = ts->chars + ts->ttis[i].tt_abbrind;
|
||||
char *tsabbr = ts->chars + ts->ttis[i].tt_desigidx;
|
||||
int j;
|
||||
|
||||
for (j = 0; j < charcnt; j++)
|
||||
if (strcmp(sp->chars + j, tsabbr) == 0)
|
||||
{
|
||||
ts->ttis[i].tt_abbrind = j;
|
||||
ts->ttis[i].tt_desigidx = j;
|
||||
gotabbr++;
|
||||
break;
|
||||
}
|
||||
@ -456,7 +456,7 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
|
||||
{
|
||||
strcpy(sp->chars + j, tsabbr);
|
||||
charcnt = j + tsabbrlen + 1;
|
||||
ts->ttis[i].tt_abbrind = j;
|
||||
ts->ttis[i].tt_desigidx = j;
|
||||
gotabbr++;
|
||||
}
|
||||
}
|
||||
@ -614,12 +614,13 @@ typesequiv(const struct state *sp, int a, int b)
|
||||
const struct ttinfo *ap = &sp->ttis[a];
|
||||
const struct ttinfo *bp = &sp->ttis[b];
|
||||
|
||||
result = ap->tt_gmtoff == bp->tt_gmtoff &&
|
||||
ap->tt_isdst == bp->tt_isdst &&
|
||||
ap->tt_ttisstd == bp->tt_ttisstd &&
|
||||
ap->tt_ttisgmt == bp->tt_ttisgmt &&
|
||||
strcmp(&sp->chars[ap->tt_abbrind],
|
||||
&sp->chars[bp->tt_abbrind]) == 0;
|
||||
result = (ap->tt_utoff == bp->tt_utoff
|
||||
&& ap->tt_isdst == bp->tt_isdst
|
||||
&& ap->tt_ttisstd == bp->tt_ttisstd
|
||||
&& ap->tt_ttisut == bp->tt_ttisut
|
||||
&& (strcmp(&sp->chars[ap->tt_desigidx],
|
||||
&sp->chars[bp->tt_desigidx])
|
||||
== 0));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -1176,7 +1177,7 @@ tzparse(const char *name, struct state *sp, bool lastditch)
|
||||
if (!sp->ttis[j].tt_isdst)
|
||||
{
|
||||
theirstdoffset =
|
||||
-sp->ttis[j].tt_gmtoff;
|
||||
-sp->ttis[j].tt_utoff;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1187,7 +1188,7 @@ tzparse(const char *name, struct state *sp, bool lastditch)
|
||||
if (sp->ttis[j].tt_isdst)
|
||||
{
|
||||
theirdstoffset =
|
||||
-sp->ttis[j].tt_gmtoff;
|
||||
-sp->ttis[j].tt_utoff;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1206,7 +1207,7 @@ tzparse(const char *name, struct state *sp, bool lastditch)
|
||||
{
|
||||
j = sp->types[i];
|
||||
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 */
|
||||
}
|
||||
@ -1234,7 +1235,7 @@ tzparse(const char *name, struct state *sp, bool lastditch)
|
||||
theirstdoffset;
|
||||
}
|
||||
}
|
||||
theiroffset = -sp->ttis[j].tt_gmtoff;
|
||||
theiroffset = -sp->ttis[j].tt_utoff;
|
||||
if (sp->ttis[j].tt_isdst)
|
||||
theirdstoffset = theiroffset;
|
||||
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
|
||||
* 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);
|
||||
*/
|
||||
result = timesub(&t, ttisp->tt_gmtoff, sp, tmp);
|
||||
result = timesub(&t, ttisp->tt_utoff, sp, tmp);
|
||||
if (result)
|
||||
{
|
||||
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;
|
||||
}
|
||||
@ -1647,7 +1648,7 @@ pg_next_dst_boundary(const pg_time_t *timep,
|
||||
break;
|
||||
}
|
||||
ttisp = &sp->ttis[i];
|
||||
*before_gmtoff = ttisp->tt_gmtoff;
|
||||
*before_gmtoff = ttisp->tt_utoff;
|
||||
*before_isdst = ttisp->tt_isdst;
|
||||
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 */
|
||||
i = sp->types[sp->timecnt - 1];
|
||||
ttisp = &sp->ttis[i];
|
||||
*before_gmtoff = ttisp->tt_gmtoff;
|
||||
*before_gmtoff = ttisp->tt_utoff;
|
||||
*before_isdst = ttisp->tt_isdst;
|
||||
return 0;
|
||||
}
|
||||
@ -1715,13 +1716,13 @@ pg_next_dst_boundary(const pg_time_t *timep,
|
||||
break;
|
||||
}
|
||||
ttisp = &sp->ttis[i];
|
||||
*before_gmtoff = ttisp->tt_gmtoff;
|
||||
*before_gmtoff = ttisp->tt_utoff;
|
||||
*before_isdst = ttisp->tt_isdst;
|
||||
*boundary = sp->ats[0];
|
||||
/* And for "after", use the first segment's type */
|
||||
i = sp->types[0];
|
||||
ttisp = &sp->ttis[i];
|
||||
*after_gmtoff = ttisp->tt_gmtoff;
|
||||
*after_gmtoff = ttisp->tt_utoff;
|
||||
*after_isdst = ttisp->tt_isdst;
|
||||
return 1;
|
||||
}
|
||||
@ -1743,12 +1744,12 @@ pg_next_dst_boundary(const pg_time_t *timep,
|
||||
}
|
||||
j = sp->types[i - 1];
|
||||
ttisp = &sp->ttis[j];
|
||||
*before_gmtoff = ttisp->tt_gmtoff;
|
||||
*before_gmtoff = ttisp->tt_utoff;
|
||||
*before_isdst = ttisp->tt_isdst;
|
||||
*boundary = sp->ats[i];
|
||||
j = sp->types[i];
|
||||
ttisp = &sp->ttis[j];
|
||||
*after_gmtoff = ttisp->tt_gmtoff;
|
||||
*after_gmtoff = ttisp->tt_utoff;
|
||||
*after_isdst = ttisp->tt_isdst;
|
||||
return 1;
|
||||
}
|
||||
@ -1832,9 +1833,9 @@ pg_interpret_timezone_abbrev(const char *abbrev,
|
||||
for (i = cutoff - 1; i >= 0; 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;
|
||||
return true;
|
||||
}
|
||||
@ -1846,9 +1847,9 @@ pg_interpret_timezone_abbrev(const char *abbrev,
|
||||
for (i = cutoff; i < sp->timecnt; 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;
|
||||
return true;
|
||||
}
|
||||
@ -1875,10 +1876,10 @@ pg_get_timezone_offset(const pg_tz *tz, long int *gmtoff)
|
||||
sp = &tz->state;
|
||||
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;
|
||||
}
|
||||
*gmtoff = sp->ttis[0].tt_gmtoff;
|
||||
*gmtoff = sp->ttis[0].tt_utoff;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -25,11 +25,11 @@
|
||||
|
||||
struct ttinfo
|
||||
{ /* 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 */
|
||||
int tt_abbrind; /* abbreviation list index */
|
||||
int tt_desigidx; /* abbreviation list index */
|
||||
bool tt_ttisstd; /* transition is std time */
|
||||
bool tt_ttisgmt; /* transition is UT */
|
||||
bool tt_ttisut; /* transition is UT */
|
||||
};
|
||||
|
||||
struct lsinfo
|
||||
|
@ -41,7 +41,7 @@ struct tzhead
|
||||
char tzh_magic[4]; /* TZ_MAGIC */
|
||||
char tzh_version[1]; /* '\0' or '2' or '3' as of 2013 */
|
||||
char tzh_reserved[15]; /* reserved; must be zero */
|
||||
char tzh_ttisgmtcnt[4]; /* coded number of trans. time flags */
|
||||
char tzh_ttisutcnt[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_timecnt[4]; /* coded number of transition times */
|
||||
@ -64,14 +64,15 @@ struct tzhead
|
||||
* one (char [4]) total correction after above
|
||||
* tzh_ttisstdcnt (char)s indexed by type; if 1, transition
|
||||
* time is standard time, if 0,
|
||||
* transition time is wall clock 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
|
||||
* transition time is local (wall clock)
|
||||
* time; if absent, transition times are
|
||||
* 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;
|
||||
|
||||
zic_t r_tod; /* time from midnight */
|
||||
bool r_todisstd; /* above is standard time if 1 or wall clock
|
||||
* time if 0 */
|
||||
bool r_todisgmt; /* above is GMT if 1 or local time if 0 */
|
||||
bool r_todisstd; /* is r_tod standard time? */
|
||||
bool r_todisut; /* is r_tod UT? */
|
||||
bool r_isdst; /* is this daylight saving time? */
|
||||
zic_t r_stdoff; /* offset from default time (which is usually
|
||||
* standard time) */
|
||||
zic_t r_save; /* offset from standard time */
|
||||
const char *r_abbrvar; /* variable part of abbreviation */
|
||||
|
||||
bool r_todo; /* a rule to do (used in outzone) */
|
||||
@ -103,13 +101,13 @@ struct zone
|
||||
lineno_t z_linenum;
|
||||
|
||||
const char *z_name;
|
||||
zic_t z_gmtoff;
|
||||
zic_t z_stdoff;
|
||||
char *z_rule;
|
||||
const char *z_format;
|
||||
char z_format_specifier;
|
||||
|
||||
bool z_isdst;
|
||||
zic_t z_stdoff;
|
||||
zic_t z_save;
|
||||
|
||||
struct rule *z_rules;
|
||||
ptrdiff_t z_nrules;
|
||||
@ -133,7 +131,7 @@ static void associate(void);
|
||||
static void dolink(const char *, const char *, bool);
|
||||
static char **getfields(char *buf);
|
||||
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 inleap(char **fields, int nfields);
|
||||
static void inlink(char **fields, int nfields);
|
||||
@ -210,7 +208,7 @@ static int typecnt;
|
||||
*/
|
||||
|
||||
#define ZF_NAME 1
|
||||
#define ZF_GMTOFF 2
|
||||
#define ZF_STDOFF 2
|
||||
#define ZF_RULE 3
|
||||
#define ZF_FORMAT 4
|
||||
#define ZF_TILYEAR 5
|
||||
@ -224,7 +222,7 @@ static int typecnt;
|
||||
* Which fields are which on a Zone continuation line.
|
||||
*/
|
||||
|
||||
#define ZFC_GMTOFF 0
|
||||
#define ZFC_STDOFF 0
|
||||
#define ZFC_RULE 1
|
||||
#define ZFC_FORMAT 2
|
||||
#define ZFC_TILYEAR 3
|
||||
@ -245,7 +243,7 @@ static int typecnt;
|
||||
#define RF_MONTH 5
|
||||
#define RF_DAY 6
|
||||
#define RF_TOD 7
|
||||
#define RF_STDOFF 8
|
||||
#define RF_SAVE 8
|
||||
#define RF_ABBRVAR 9
|
||||
#define RULE_FIELDS 10
|
||||
|
||||
@ -389,11 +387,11 @@ static struct attype
|
||||
bool dontmerge;
|
||||
unsigned char type;
|
||||
} *attypes;
|
||||
static zic_t gmtoffs[TZ_MAX_TYPES];
|
||||
static zic_t utoffs[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 ttisgmts[TZ_MAX_TYPES];
|
||||
static bool ttisuts[TZ_MAX_TYPES];
|
||||
static char chars[TZ_MAX_CHARS];
|
||||
static zic_t trans[TZ_MAX_LEAPS];
|
||||
static zic_t corr[TZ_MAX_LEAPS];
|
||||
@ -540,8 +538,9 @@ usage(FILE *stream, int status)
|
||||
{
|
||||
fprintf(stream,
|
||||
_("%s: usage is %s [ --version ] [ --help ] [ -v ] [ -P ] \\\n"
|
||||
"\t[ -l localtime ] [ -p posixrules ] [ -d directory ] \\\n"
|
||||
"\t[ -t localtime-link ] [ -L leapseconds ] [ -r '[@lo][/@hi]' ] \\\n"
|
||||
"\t[ -b {slim|fat} ] [ -d directory ] [ -l localtime ]"
|
||||
" [ -L leapseconds ] \\\n"
|
||||
"\t[ -p posixrules ] [ -r '[@lo][/@hi]' ] [ -t localtime-link ] \\\n"
|
||||
"\t[ filename ... ]\n\n"
|
||||
"Report bugs to %s.\n"),
|
||||
progname, progname, PACKAGE_BUGREPORT);
|
||||
@ -625,6 +624,21 @@ static const char *leapsec;
|
||||
static const char *tzdefault;
|
||||
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
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
@ -655,11 +669,27 @@ main(int argc, char **argv)
|
||||
{
|
||||
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)
|
||||
{
|
||||
default:
|
||||
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':
|
||||
if (directory == NULL)
|
||||
directory = strdup(optarg);
|
||||
@ -759,6 +789,8 @@ main(int argc, char **argv)
|
||||
}
|
||||
if (optind == argc - 1 && strcmp(argv[optind], "=") == 0)
|
||||
usage(stderr, EXIT_FAILURE); /* usage message by request */
|
||||
if (bloat == 0)
|
||||
bloat = strcmp(ZIC_BLOAT_DEFAULT, "slim") == 0 ? -1 : 1;
|
||||
if (directory == NULL)
|
||||
directory = "data";
|
||||
if (tzdefault == NULL)
|
||||
@ -1183,7 +1215,7 @@ associate(void)
|
||||
* Maybe we have a local standard time offset.
|
||||
*/
|
||||
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
|
||||
@ -1380,10 +1412,10 @@ gethms(char const *string, char const *errstring)
|
||||
}
|
||||
|
||||
static zic_t
|
||||
getstdoff(char *field, bool *isdst)
|
||||
getsave(char *field, bool *isdst)
|
||||
{
|
||||
int dst = -1;
|
||||
zic_t stdoff;
|
||||
zic_t save;
|
||||
size_t fieldlen = strlen(field);
|
||||
|
||||
if (fieldlen != 0)
|
||||
@ -1402,9 +1434,9 @@ getstdoff(char *field, bool *isdst)
|
||||
break;
|
||||
}
|
||||
}
|
||||
stdoff = gethms(field, _("invalid saved time"));
|
||||
*isdst = dst < 0 ? stdoff != 0 : dst;
|
||||
return stdoff;
|
||||
save = gethms(field, _("invalid saved time"));
|
||||
*isdst = dst < 0 ? save != 0 : dst;
|
||||
return save;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1443,7 +1475,7 @@ inrule(char **fields, int nfields)
|
||||
}
|
||||
r.r_filename = filename;
|
||||
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],
|
||||
fields[RF_MONTH], fields[RF_DAY], fields[RF_TOD]);
|
||||
r.r_name = ecpyalloc(fields[RF_NAME]);
|
||||
@ -1509,7 +1541,7 @@ inzsub(char **fields, int nfields, bool iscont)
|
||||
char *cp;
|
||||
char *cp1;
|
||||
static struct zone z;
|
||||
int i_gmtoff,
|
||||
int i_stdoff,
|
||||
i_rule,
|
||||
i_format;
|
||||
int i_untilyear,
|
||||
@ -1520,7 +1552,7 @@ inzsub(char **fields, int nfields, bool iscont)
|
||||
|
||||
if (iscont)
|
||||
{
|
||||
i_gmtoff = ZFC_GMTOFF;
|
||||
i_stdoff = ZFC_STDOFF;
|
||||
i_rule = ZFC_RULE;
|
||||
i_format = ZFC_FORMAT;
|
||||
i_untilyear = ZFC_TILYEAR;
|
||||
@ -1533,7 +1565,7 @@ inzsub(char **fields, int nfields, bool iscont)
|
||||
return false;
|
||||
else
|
||||
{
|
||||
i_gmtoff = ZF_GMTOFF;
|
||||
i_stdoff = ZF_STDOFF;
|
||||
i_rule = ZF_RULE;
|
||||
i_format = ZF_FORMAT;
|
||||
i_untilyear = ZF_TILYEAR;
|
||||
@ -1544,7 +1576,7 @@ inzsub(char **fields, int nfields, bool iscont)
|
||||
}
|
||||
z.z_filename = filename;
|
||||
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 != '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_todisstd = false;
|
||||
rp->r_todisgmt = false;
|
||||
rp->r_todisut = false;
|
||||
dp = ecpyalloc(timep);
|
||||
if (*dp != '\0')
|
||||
{
|
||||
@ -1777,19 +1809,19 @@ rulesub(struct rule *rp, const char *loyearp, const char *hiyearp,
|
||||
{
|
||||
case 's': /* Standard */
|
||||
rp->r_todisstd = true;
|
||||
rp->r_todisgmt = false;
|
||||
rp->r_todisut = false;
|
||||
*ep = '\0';
|
||||
break;
|
||||
case 'w': /* Wall */
|
||||
rp->r_todisstd = false;
|
||||
rp->r_todisgmt = false;
|
||||
rp->r_todisut = false;
|
||||
*ep = '\0';
|
||||
break;
|
||||
case 'g': /* Greenwich */
|
||||
case 'u': /* Universal */
|
||||
case 'z': /* Zulu */
|
||||
rp->r_todisstd = true;
|
||||
rp->r_todisgmt = true;
|
||||
rp->r_todisut = true;
|
||||
*ep = '\0';
|
||||
break;
|
||||
}
|
||||
@ -1977,41 +2009,6 @@ atcomp(const void *avp, const void *bvp)
|
||||
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
|
||||
{
|
||||
int defaulttype;
|
||||
@ -2091,9 +2088,11 @@ writezone(const char *const name, const char *const string, char version,
|
||||
fromi = 0;
|
||||
for (; fromi < timecnt; ++fromi)
|
||||
{
|
||||
if (toi != 0 && ((attypes[fromi].at +
|
||||
gmtoffs[attypes[toi - 1].type]) <=
|
||||
(attypes[toi - 1].at + gmtoffs[toi == 1 ? 0
|
||||
if (toi != 0
|
||||
&& ((attypes[fromi].at
|
||||
+ utoffs[attypes[toi - 1].type])
|
||||
<= (attypes[toi - 1].at
|
||||
+ utoffs[toi == 1 ? 0
|
||||
: attypes[toi - 2].type])))
|
||||
{
|
||||
attypes[toi - 1].type =
|
||||
@ -2102,7 +2101,12 @@ writezone(const char *const name, const char *const string, char version,
|
||||
}
|
||||
if (toi == 0
|
||||
|| 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];
|
||||
}
|
||||
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
|
||||
* 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] = y2038_boundary - 1;
|
||||
@ -2213,7 +2217,9 @@ writezone(const char *const name, const char *const string, char version,
|
||||
int old0;
|
||||
char omittype[TZ_MAX_TYPES];
|
||||
int typemap[TZ_MAX_TYPES];
|
||||
int thistypecnt;
|
||||
int thistypecnt,
|
||||
stdcnt,
|
||||
utcnt;
|
||||
char thischars[TZ_MAX_CHARS];
|
||||
int thischarcnt;
|
||||
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.
|
||||
*/
|
||||
old0 = strlen(omittype);
|
||||
swaptypes(old0, thisdefaulttype);
|
||||
|
||||
#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
|
||||
* help get global "altzone" and "timezone" variables set correctly).
|
||||
*/
|
||||
if (want_bloat())
|
||||
{
|
||||
int mrudst,
|
||||
mrustd,
|
||||
@ -2317,34 +2323,39 @@ writezone(const char *const name, const char *const string, char version,
|
||||
else
|
||||
mrustd = types[i];
|
||||
for (i = old0; i < typecnt; i++)
|
||||
if (!omittype[i])
|
||||
{
|
||||
if (isdsts[i])
|
||||
int h = (i == old0 ? thisdefaulttype
|
||||
: i == thisdefaulttype ? old0 : i);
|
||||
|
||||
if (!omittype[h])
|
||||
{
|
||||
if (isdsts[h])
|
||||
hidst = i;
|
||||
else
|
||||
histd = i;
|
||||
}
|
||||
}
|
||||
if (hidst >= 0 && mrudst >= 0 && hidst != mrudst &&
|
||||
gmtoffs[hidst] != gmtoffs[mrudst])
|
||||
utoffs[hidst] != utoffs[mrudst])
|
||||
{
|
||||
isdsts[mrudst] = -1;
|
||||
type = addtype(gmtoffs[mrudst],
|
||||
&chars[abbrinds[mrudst]],
|
||||
type = addtype(utoffs[mrudst],
|
||||
&chars[desigidx[mrudst]],
|
||||
true,
|
||||
ttisstds[mrudst],
|
||||
ttisgmts[mrudst]);
|
||||
ttisuts[mrudst]);
|
||||
isdsts[mrudst] = 1;
|
||||
omittype[type] = false;
|
||||
}
|
||||
if (histd >= 0 && mrustd >= 0 && histd != mrustd &&
|
||||
gmtoffs[histd] != gmtoffs[mrustd])
|
||||
utoffs[histd] != utoffs[mrustd])
|
||||
{
|
||||
isdsts[mrustd] = -1;
|
||||
type = addtype(gmtoffs[mrustd],
|
||||
&chars[abbrinds[mrustd]],
|
||||
type = addtype(utoffs[mrustd],
|
||||
&chars[desigidx[mrustd]],
|
||||
false,
|
||||
ttisstds[mrustd],
|
||||
ttisgmts[mrustd]);
|
||||
ttisuts[mrustd]);
|
||||
isdsts[mrustd] = 0;
|
||||
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)
|
||||
indmap[i] = -1;
|
||||
thischarcnt = 0;
|
||||
thischarcnt = stdcnt = utcnt = 0;
|
||||
for (i = old0; i < typecnt; i++)
|
||||
{
|
||||
char *thisabbr;
|
||||
|
||||
if (omittype[i])
|
||||
continue;
|
||||
if (indmap[abbrinds[i]] >= 0)
|
||||
if (ttisstds[i])
|
||||
stdcnt = thistypecnt;
|
||||
if (ttisuts[i])
|
||||
utcnt = thistypecnt;
|
||||
if (indmap[desigidx[i]] >= 0)
|
||||
continue;
|
||||
thisabbr = &chars[abbrinds[i]];
|
||||
thisabbr = &chars[desigidx[i]];
|
||||
for (j = 0; j < thischarcnt; ++j)
|
||||
if (strcmp(&thischars[j], thisabbr) == 0)
|
||||
break;
|
||||
@ -2378,14 +2393,21 @@ writezone(const char *const name, const char *const string, char version,
|
||||
strcpy(&thischars[thischarcnt], thisabbr);
|
||||
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)
|
||||
tzh = tzh0;
|
||||
memcpy(tzh.tzh_magic, TZ_MAGIC, sizeof tzh.tzh_magic);
|
||||
tzh.tzh_version[0] = version;
|
||||
convert(thistypecnt, tzh.tzh_ttisgmtcnt);
|
||||
convert(thistypecnt, tzh.tzh_ttisstdcnt);
|
||||
convert(utcnt, tzh.tzh_ttisutcnt);
|
||||
convert(stdcnt, tzh.tzh_ttisstdcnt);
|
||||
convert(thisleapcnt, tzh.tzh_leapcnt);
|
||||
convert(locut + thistimecnt + hicut, tzh.tzh_timecnt);
|
||||
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_version);
|
||||
DO(tzh_reserved);
|
||||
DO(tzh_ttisgmtcnt);
|
||||
DO(tzh_ttisutcnt);
|
||||
DO(tzh_ttisstdcnt);
|
||||
DO(tzh_leapcnt);
|
||||
DO(tzh_timecnt);
|
||||
DO(tzh_typecnt);
|
||||
DO(tzh_charcnt);
|
||||
#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 */
|
||||
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)
|
||||
{
|
||||
unsigned char tm = types[i];
|
||||
char *thisabbrev = &thischars[indmap[abbrinds[tm]]];
|
||||
char *thisabbrev = &thischars[indmap[desigidx[tm]]];
|
||||
|
||||
/* filter out assorted junk entries */
|
||||
if (strcmp(thisabbrev, GRANDPARENTED) != 0 &&
|
||||
strcmp(thisabbrev, "zzz") != 0)
|
||||
fprintf(stdout, "%s\t" INT64_FORMAT "%s\n",
|
||||
thisabbrev,
|
||||
gmtoffs[tm],
|
||||
utoffs[tm],
|
||||
isdsts[tm] ? "\tD" : "");
|
||||
}
|
||||
}
|
||||
@ -2425,14 +2456,14 @@ writezone(const char *const name, const char *const string, char version,
|
||||
if (thistimei >= thistimelim)
|
||||
{
|
||||
unsigned char tm = defaulttype;
|
||||
char *thisabbrev = &thischars[indmap[abbrinds[tm]]];
|
||||
char *thisabbrev = &thischars[indmap[desigidx[tm]]];
|
||||
|
||||
/* filter out assorted junk entries */
|
||||
if (strcmp(thisabbrev, GRANDPARENTED) != 0 &&
|
||||
strcmp(thisabbrev, "zzz") != 0)
|
||||
fprintf(stdout, "%s\t" INT64_FORMAT "%s\n",
|
||||
thisabbrev,
|
||||
gmtoffs[tm],
|
||||
utoffs[tm],
|
||||
isdsts[tm] ? "\tD" : "");
|
||||
}
|
||||
}
|
||||
@ -2465,11 +2496,16 @@ writezone(const char *const name, const char *const string, char version,
|
||||
putc(currenttype, fp);
|
||||
|
||||
for (i = old0; i < typecnt; i++)
|
||||
if (!omittype[i])
|
||||
{
|
||||
puttzcode(gmtoffs[i], fp);
|
||||
putc(isdsts[i], fp);
|
||||
putc((unsigned char) indmap[abbrinds[i]], fp);
|
||||
int h = (i == old0 ? thisdefaulttype
|
||||
: i == thisdefaulttype ? old0 : i);
|
||||
|
||||
if (!omittype[h])
|
||||
{
|
||||
puttzcode(utoffs[h], fp);
|
||||
putc(isdsts[h], fp);
|
||||
putc(indmap[desigidx[h]], fp);
|
||||
}
|
||||
}
|
||||
if (thischarcnt != 0)
|
||||
fwrite(thischars, sizeof thischars[0],
|
||||
@ -2498,20 +2534,21 @@ writezone(const char *const name, const char *const string, char version,
|
||||
++j;
|
||||
j = types[j - 1];
|
||||
}
|
||||
todo = tadd(trans[i], -gmtoffs[j]);
|
||||
todo = tadd(trans[i], -utoffs[j]);
|
||||
}
|
||||
else
|
||||
todo = trans[i];
|
||||
puttzcodepass(todo, fp, pass);
|
||||
puttzcode(corr[i], fp);
|
||||
}
|
||||
if (stdcnt != 0)
|
||||
for (i = old0; i < typecnt; i++)
|
||||
if (!omittype[i])
|
||||
putc(ttisstds[i], fp);
|
||||
if (utcnt != 0)
|
||||
for (i = old0; i < typecnt; i++)
|
||||
if (!omittype[i])
|
||||
putc(ttisgmts[i], fp);
|
||||
swaptypes(old0, thisdefaulttype);
|
||||
putc(ttisuts[i], fp);
|
||||
}
|
||||
fprintf(fp, "\n%s\n", string);
|
||||
close_file(fp, directory, name);
|
||||
@ -2564,7 +2601,7 @@ abbroffset(char *buf, zic_t offset)
|
||||
|
||||
static size_t
|
||||
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 *slashp;
|
||||
@ -2577,7 +2614,7 @@ doabbr(char *abbr, struct zone const *zp, char const *letters,
|
||||
char letterbuf[PERCENT_Z_LEN_BOUND + 1];
|
||||
|
||||
if (zp->z_format_specifier == 'z')
|
||||
letters = abbroffset(letterbuf, zp->z_gmtoff + stdoff);
|
||||
letters = abbroffset(letterbuf, zp->z_stdoff + save);
|
||||
else if (!letters)
|
||||
letters = "%s";
|
||||
sprintf(abbr, format, letters);
|
||||
@ -2649,8 +2686,7 @@ stringoffset(char *result, zic_t offset)
|
||||
}
|
||||
|
||||
static int
|
||||
stringrule(char *result, const struct rule *const rp, const zic_t dstoff,
|
||||
const zic_t gmtoff)
|
||||
stringrule(char *result, struct rule *const rp, zic_t save, zic_t stdoff)
|
||||
{
|
||||
zic_t tod = rp->r_tod;
|
||||
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",
|
||||
rp->r_month + 1, week, wday);
|
||||
}
|
||||
if (rp->r_todisgmt)
|
||||
tod += gmtoff;
|
||||
if (rp->r_todisut)
|
||||
tod += stdoff;
|
||||
if (rp->r_todisstd && !rp->r_isdst)
|
||||
tod += dstoff;
|
||||
tod += save;
|
||||
if (tod != 2 * SECSPERMIN * MINSPERHOUR)
|
||||
{
|
||||
*result++ = '/';
|
||||
@ -2744,10 +2780,6 @@ rule_cmp(struct rule const *a, struct rule const *b)
|
||||
return a->r_dayofmonth - b->r_dayofmonth;
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
YEAR_BY_YEAR_ZONE = 1};
|
||||
|
||||
static int
|
||||
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)
|
||||
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)
|
||||
{
|
||||
/* Perpetual DST. */
|
||||
@ -2829,17 +2852,17 @@ stringzone(char *result, struct zone const *zpfirst, ptrdiff_t zonecount)
|
||||
dstr.r_dycode = DC_DOM;
|
||||
dstr.r_dayofmonth = 1;
|
||||
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_stdoff = stdrp->r_stdoff;
|
||||
dstr.r_save = stdrp->r_save;
|
||||
dstr.r_abbrvar = stdrp->r_abbrvar;
|
||||
stdr.r_month = TM_DECEMBER;
|
||||
stdr.r_dycode = DC_DOM;
|
||||
stdr.r_dayofmonth = 31;
|
||||
stdr.r_tod = SECSPERDAY + stdrp->r_stdoff;
|
||||
stdr.r_todisstd = stdr.r_todisgmt = false;
|
||||
stdr.r_tod = SECSPERDAY + stdrp->r_save;
|
||||
stdr.r_todisstd = stdr.r_todisut = false;
|
||||
stdr.r_isdst = false;
|
||||
stdr.r_stdoff = 0;
|
||||
stdr.r_save = 0;
|
||||
stdr.r_abbrvar
|
||||
= (stdabbrrp ? stdabbrrp->r_abbrvar : "");
|
||||
dstrp = &dstr;
|
||||
@ -2850,7 +2873,7 @@ stringzone(char *result, struct zone const *zpfirst, ptrdiff_t zonecount)
|
||||
return -1;
|
||||
abbrvar = (stdrp == NULL) ? "" : stdrp->r_abbrvar;
|
||||
len = doabbr(result, zp, abbrvar, false, 0, true);
|
||||
offsetlen = stringoffset(result + len, -zp->z_gmtoff);
|
||||
offsetlen = stringoffset(result + len, -zp->z_stdoff);
|
||||
if (!offsetlen)
|
||||
{
|
||||
result[0] = '\0';
|
||||
@ -2860,11 +2883,11 @@ stringzone(char *result, struct zone const *zpfirst, ptrdiff_t zonecount)
|
||||
if (dstrp == NULL)
|
||||
return compat;
|
||||
len += doabbr(result + len, zp, dstrp->r_abbrvar,
|
||||
dstrp->r_isdst, dstrp->r_stdoff, true);
|
||||
if (dstrp->r_stdoff != SECSPERMIN * MINSPERHOUR)
|
||||
dstrp->r_isdst, dstrp->r_save, true);
|
||||
if (dstrp->r_save != SECSPERMIN * MINSPERHOUR)
|
||||
{
|
||||
offsetlen = stringoffset(result + len,
|
||||
-(zp->z_gmtoff + dstrp->r_stdoff));
|
||||
-(zp->z_stdoff + dstrp->r_save));
|
||||
if (!offsetlen)
|
||||
{
|
||||
result[0] = '\0';
|
||||
@ -2873,7 +2896,7 @@ stringzone(char *result, struct zone const *zpfirst, ptrdiff_t zonecount)
|
||||
len += offsetlen;
|
||||
}
|
||||
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)
|
||||
{
|
||||
result[0] = '\0';
|
||||
@ -2883,7 +2906,7 @@ stringzone(char *result, struct zone const *zpfirst, ptrdiff_t zonecount)
|
||||
compat = c;
|
||||
len += strlen(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)
|
||||
{
|
||||
result[0] = '\0';
|
||||
@ -2905,12 +2928,12 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
|
||||
useuntil;
|
||||
zic_t starttime,
|
||||
untiltime;
|
||||
zic_t gmtoff;
|
||||
zic_t stdoff;
|
||||
zic_t save;
|
||||
zic_t year;
|
||||
zic_t startoff;
|
||||
bool startttisstd;
|
||||
bool startttisgmt;
|
||||
bool startttisut;
|
||||
int type;
|
||||
char *startbuf;
|
||||
char *ab;
|
||||
@ -2948,7 +2971,7 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
|
||||
* startttisstd.
|
||||
*/
|
||||
startttisstd = false;
|
||||
startttisgmt = false;
|
||||
startttisut = false;
|
||||
min_year = max_year = EPOCH_YEAR;
|
||||
if (leapseen)
|
||||
{
|
||||
@ -2977,14 +3000,14 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
|
||||
*/
|
||||
compat = stringzone(envvar, zpfirst, zonecount);
|
||||
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 (!*envvar)
|
||||
warning("%s %s",
|
||||
_("no POSIX environment variable for zone"),
|
||||
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
|
||||
@ -3033,37 +3056,43 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
|
||||
max_year = min_year + years_of_observations;
|
||||
}
|
||||
}
|
||||
|
||||
max_year0 = max_year;
|
||||
if (want_bloat())
|
||||
{
|
||||
/*
|
||||
* For the benefit of older systems, generate data from 1900 through 2038.
|
||||
* For the benefit of older systems, generate data from 1900 through
|
||||
* 2038.
|
||||
*/
|
||||
if (min_year > 1900)
|
||||
min_year = 1900;
|
||||
max_year0 = max_year;
|
||||
if (max_year < 2038)
|
||||
max_year = 2038;
|
||||
}
|
||||
|
||||
for (i = 0; i < zonecount; ++i)
|
||||
{
|
||||
struct rule *prevrp = NULL;
|
||||
|
||||
/*
|
||||
* A guess that may well be corrected later.
|
||||
*/
|
||||
stdoff = 0;
|
||||
save = 0;
|
||||
zp = &zpfirst[i];
|
||||
usestart = i > 0 && (zp - 1)->z_untiltime > min_time;
|
||||
useuntil = i < (zonecount - 1);
|
||||
if (useuntil && zp->z_untiltime <= min_time)
|
||||
continue;
|
||||
gmtoff = zp->z_gmtoff;
|
||||
stdoff = zp->z_stdoff;
|
||||
eat(zp->z_filename, zp->z_linenum);
|
||||
*startbuf = '\0';
|
||||
startoff = zp->z_gmtoff;
|
||||
startoff = zp->z_stdoff;
|
||||
if (zp->z_nrules == 0)
|
||||
{
|
||||
stdoff = zp->z_stdoff;
|
||||
doabbr(startbuf, zp, NULL, zp->z_isdst, stdoff, false);
|
||||
type = addtype(oadd(zp->z_gmtoff, stdoff),
|
||||
save = zp->z_save;
|
||||
doabbr(startbuf, zp, NULL, zp->z_isdst, save, false);
|
||||
type = addtype(oadd(zp->z_stdoff, save),
|
||||
startbuf, zp->z_isdst, startttisstd,
|
||||
startttisgmt);
|
||||
startttisut);
|
||||
if (usestart)
|
||||
{
|
||||
addtt(starttime, type);
|
||||
@ -3109,16 +3138,16 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
|
||||
if (useuntil)
|
||||
{
|
||||
/*
|
||||
* Turn untiltime into UT assuming the current gmtoff
|
||||
* and stdoff values.
|
||||
* Turn untiltime into UT assuming the current stdoff
|
||||
* and save values.
|
||||
*/
|
||||
untiltime = zp->z_untiltime;
|
||||
if (!zp->z_untilrule.r_todisgmt)
|
||||
untiltime = tadd(untiltime,
|
||||
-gmtoff);
|
||||
if (!zp->z_untilrule.r_todisstd)
|
||||
if (!zp->z_untilrule.r_todisut)
|
||||
untiltime = tadd(untiltime,
|
||||
-stdoff);
|
||||
if (!zp->z_untilrule.r_todisstd)
|
||||
untiltime = tadd(untiltime,
|
||||
-save);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3133,9 +3162,9 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
|
||||
continue;
|
||||
eats(zp->z_filename, zp->z_linenum,
|
||||
rp->r_filename, rp->r_linenum);
|
||||
offset = rp->r_todisgmt ? 0 : gmtoff;
|
||||
offset = rp->r_todisut ? 0 : stdoff;
|
||||
if (!rp->r_todisstd)
|
||||
offset = oadd(offset, stdoff);
|
||||
offset = oadd(offset, save);
|
||||
jtime = rp->r_temp;
|
||||
if (jtime == min_time ||
|
||||
jtime == max_time)
|
||||
@ -3166,41 +3195,46 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
|
||||
rp->r_todo = false;
|
||||
if (useuntil && ktime >= untiltime)
|
||||
break;
|
||||
stdoff = rp->r_stdoff;
|
||||
save = rp->r_save;
|
||||
if (usestart && ktime == starttime)
|
||||
usestart = false;
|
||||
if (usestart)
|
||||
{
|
||||
if (ktime < starttime)
|
||||
{
|
||||
startoff = oadd(zp->z_gmtoff,
|
||||
stdoff);
|
||||
startoff = oadd(zp->z_stdoff,
|
||||
save);
|
||||
doabbr(startbuf, zp,
|
||||
rp->r_abbrvar,
|
||||
rp->r_isdst,
|
||||
rp->r_stdoff,
|
||||
rp->r_save,
|
||||
false);
|
||||
continue;
|
||||
}
|
||||
if (*startbuf == '\0' &&
|
||||
startoff == oadd(zp->z_gmtoff,
|
||||
stdoff))
|
||||
if (*startbuf == '\0'
|
||||
&& startoff == oadd(zp->z_stdoff,
|
||||
save))
|
||||
{
|
||||
doabbr(startbuf,
|
||||
zp,
|
||||
rp->r_abbrvar,
|
||||
rp->r_isdst,
|
||||
rp->r_stdoff,
|
||||
rp->r_save,
|
||||
false);
|
||||
}
|
||||
}
|
||||
eats(zp->z_filename, zp->z_linenum,
|
||||
rp->r_filename, rp->r_linenum);
|
||||
doabbr(ab, zp, rp->r_abbrvar,
|
||||
rp->r_isdst, rp->r_stdoff, false);
|
||||
offset = oadd(zp->z_gmtoff, rp->r_stdoff);
|
||||
rp->r_isdst, rp->r_save, false);
|
||||
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,
|
||||
rp->r_todisstd, rp->r_todisgmt);
|
||||
rp->r_todisstd, rp->r_todisut);
|
||||
if (defaulttype < 0 && !rp->r_isdst)
|
||||
defaulttype = type;
|
||||
if (rp->r_hiyear == ZIC_MAX
|
||||
@ -3208,6 +3242,7 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
|
||||
&& ktime < attypes[lastatmax].at))
|
||||
lastatmax = timecnt;
|
||||
addtt(ktime, type);
|
||||
prevrp = rp;
|
||||
}
|
||||
}
|
||||
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"));
|
||||
else
|
||||
{
|
||||
bool isdst = startoff != zp->z_gmtoff;
|
||||
bool isdst = startoff != zp->z_stdoff;
|
||||
|
||||
type = addtype(startoff, startbuf, isdst,
|
||||
startttisstd, startttisgmt);
|
||||
startttisstd, startttisut);
|
||||
if (defaulttype < 0 && !isdst)
|
||||
defaulttype = type;
|
||||
addtt(starttime, type);
|
||||
@ -3238,12 +3273,12 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
|
||||
if (useuntil)
|
||||
{
|
||||
startttisstd = zp->z_untilrule.r_todisstd;
|
||||
startttisgmt = zp->z_untilrule.r_todisgmt;
|
||||
startttisut = zp->z_untilrule.r_todisut;
|
||||
starttime = zp->z_untiltime;
|
||||
if (!startttisstd)
|
||||
starttime = tadd(starttime, -save);
|
||||
if (!startttisut)
|
||||
starttime = tadd(starttime, -stdoff);
|
||||
if (!startttisgmt)
|
||||
starttime = tadd(starttime, -gmtoff);
|
||||
}
|
||||
}
|
||||
if (defaulttype < 0)
|
||||
@ -3295,21 +3330,30 @@ addtt(zic_t starttime, int type)
|
||||
}
|
||||
|
||||
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,
|
||||
j;
|
||||
|
||||
/*
|
||||
* See if there's already an entry for this zone type. If so, just return
|
||||
* its index.
|
||||
*/
|
||||
for (i = 0; i < typecnt; ++i)
|
||||
if (!(-1L - 2147483647L <= utoff && utoff <= 2147483647L))
|
||||
{
|
||||
if (gmtoff == gmtoffs[i] && isdst == isdsts[i] &&
|
||||
strcmp(abbr, &chars[abbrinds[i]]) == 0 &&
|
||||
ttisstd == ttisstds[i] &&
|
||||
ttisgmt == ttisgmts[i])
|
||||
error(_("UT offset out of range"));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (!want_bloat())
|
||||
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"));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (!(-1L - 2147483647L <= gmtoff && gmtoff <= 2147483647L))
|
||||
{
|
||||
error(_("UT offset out of range"));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
gmtoffs[i] = gmtoff;
|
||||
i = typecnt++;
|
||||
utoffs[i] = utoff;
|
||||
isdsts[i] = isdst;
|
||||
ttisstds[i] = ttisstd;
|
||||
ttisgmts[i] = ttisgmt;
|
||||
|
||||
for (j = 0; j < charcnt; ++j)
|
||||
if (strcmp(&chars[j], abbr) == 0)
|
||||
break;
|
||||
if (j == charcnt)
|
||||
newabbr(abbr);
|
||||
abbrinds[i] = j;
|
||||
++typecnt;
|
||||
ttisuts[i] = ttisut;
|
||||
desigidx[i] = j;
|
||||
return i;
|
||||
}
|
||||
|
||||
@ -3671,9 +3704,9 @@ byword(const char *word, const struct lookup *table)
|
||||
return NULL; /* multiple inexact matches */
|
||||
}
|
||||
|
||||
/* Warn about any backward-compatibility issue with pre-2017c zic. */
|
||||
if (foundlp)
|
||||
if (foundlp && noise)
|
||||
{
|
||||
/* Warn about any backward-compatibility issue with pre-2017c zic. */
|
||||
bool pre_2017c_match = false;
|
||||
|
||||
for (lp = table; lp->l_word; lp++)
|
||||
|
Loading…
x
Reference in New Issue
Block a user