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
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);
&& 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 */
+ charcnt /* chars */
+ leapcnt * (stored + 4) /* lsinfos */
+ ttisstdcnt /* ttisstds */
- + ttisgmtcnt)) /* ttisgmts */
+ + ttisutcnt)) /* ttisuts */
return EINVAL;
sp->leapcnt = leapcnt;
sp->timecnt = timecnt;
{
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++;
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++;
}
}
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;
}
{
strcpy(sp->chars + j, tsabbr);
charcnt = j + tsabbrlen + 1;
- ts->ttis[i].tt_abbrind = j;
+ ts->ttis[i].tt_desigidx = j;
gotabbr++;
}
}
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;
}
if (!sp->ttis[j].tt_isdst)
{
theirstdoffset =
- -sp->ttis[j].tt_gmtoff;
+ -sp->ttis[j].tt_utoff;
break;
}
}
if (sp->ttis[j].tt_isdst)
{
theirdstoffset =
- -sp->ttis[j].tt_gmtoff;
+ -sp->ttis[j].tt_utoff;
break;
}
}
{
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 */
}
theirstdoffset;
}
}
- theiroffset = -sp->ttis[j].tt_gmtoff;
+ theiroffset = -sp->ttis[j].tt_utoff;
if (sp->ttis[j].tt_isdst)
theirdstoffset = theiroffset;
else
/*
* 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 = (char *) &sp->chars[ttisp->tt_abbrind];
+ result->tm_zone = (char *) &sp->chars[ttisp->tt_desigidx];
}
return result;
}
break;
}
ttisp = &sp->ttis[i];
- *before_gmtoff = ttisp->tt_gmtoff;
+ *before_gmtoff = ttisp->tt_utoff;
*before_isdst = ttisp->tt_isdst;
return 0;
}
/* 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;
}
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;
}
}
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;
}
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;
}
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;
}
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;
}
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) */
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;
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);
*/
#define ZF_NAME 1
-#define ZF_GMTOFF 2
+#define ZF_STDOFF 2
#define ZF_RULE 3
#define ZF_FORMAT 4
#define ZF_TILYEAR 5
* 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
#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
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];
{
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);
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)
{
{
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);
}
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)
* 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
}
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)
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
}
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]);
char *cp;
char *cp1;
static struct zone z;
- int i_gmtoff,
+ int i_stdoff,
i_rule,
i_format;
int i_untilyear,
if (iscont)
{
- i_gmtoff = ZFC_GMTOFF;
+ i_stdoff = ZFC_STDOFF;
i_rule = ZFC_RULE;
i_format = ZFC_FORMAT;
i_untilyear = ZFC_TILYEAR;
return false;
else
{
- i_gmtoff = ZF_GMTOFF;
+ i_stdoff = ZF_STDOFF;
i_rule = ZF_RULE;
i_format = ZF_FORMAT;
i_untilyear = ZF_TILYEAR;
}
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, '%')
}
rp->r_month = lp->l_value;
rp->r_todisstd = false;
- rp->r_todisgmt = false;
+ rp->r_todisut = false;
dp = ecpyalloc(timep);
if (*dp != '\0')
{
{
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;
}
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;
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;
}
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;
* 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;
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;
* 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
* 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,
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;
}
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;
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);
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)
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" : "");
}
}
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" : "");
}
}
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);
++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);
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;
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);
}
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;
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++ = '/';
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)
{
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. */
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;
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';
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';
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';
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';
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;
* startttisstd.
*/
startttisstd = false;
- startttisgmt = false;
+ startttisut = false;
min_year = max_year = EPOCH_YEAR;
if (leapseen)
{
*/
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
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);
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)
+ if (!zp->z_untilrule.r_todisut)
untiltime = tadd(untiltime,
- -gmtoff);
+ -stdoff);
if (!zp->z_untilrule.r_todisstd)
untiltime = tadd(untiltime,
- -stdoff);
+ -save);
}
/*
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)
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
&& ktime < attypes[lastatmax].at))
lastatmax = timecnt;
addtt(ktime, type);
+ prevrp = rp;
}
}
if (usestart)
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);
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)
}
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))
+ {
+ 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 (gmtoff == gmtoffs[i] && isdst == isdsts[i] &&
- strcmp(abbr, &chars[abbrinds[i]]) == 0 &&
- ttisstd == ttisstds[i] &&
- ttisgmt == ttisgmts[i])
- return i;
+ /* 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;
}
/*
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;
}
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++)