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:
Tom Lane 2019-07-17 18:26:23 -04:00
parent fec0778c80
commit f285322f9c
5 changed files with 306 additions and 268 deletions

View File

@ -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.

View File

@ -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;
}

View File

@ -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

View File

@ -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.
*/
/*

View File

@ -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,10 +2088,12 @@ 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
: attypes[toi - 2].type])))
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 =
attypes[fromi].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])
{
int h = (i == old0 ? thisdefaulttype
: i == thisdefaulttype ? old0 : i);
if (!omittype[h])
{
if (isdsts[i])
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,12 +2496,17 @@ writezone(const char *const name, const char *const string, char version,
putc(currenttype, fp);
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);
putc(isdsts[i], fp);
putc((unsigned char) indmap[abbrinds[i]], fp);
puttzcode(utoffs[h], fp);
putc(isdsts[h], fp);
putc(indmap[desigidx[h]], fp);
}
}
if (thischarcnt != 0)
fwrite(thischars, sizeof thischars[0],
thischarcnt, fp);
@ -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);
}
for (i = old0; i < typecnt; i++)
if (!omittype[i])
putc(ttisstds[i], fp);
for (i = old0; i < typecnt; i++)
if (!omittype[i])
putc(ttisgmts[i], fp);
swaptypes(old0, thisdefaulttype);
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(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;
}
}
/*
* 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;
if (want_bloat())
{
/*
* 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)
{
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,22 +3330,31 @@ 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])
return 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++)