|
|
|
@ -541,7 +541,8 @@ 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 ] [ filename ... ]\n\n"
|
|
|
|
|
"\t[ -t localtime-link ] [ -L leapseconds ] [ -r '[@lo][/@hi]' ] \\\n"
|
|
|
|
|
"\t[ filename ... ]\n\n"
|
|
|
|
|
"Report bugs to %s.\n"),
|
|
|
|
|
progname, progname, PACKAGE_BUGREPORT);
|
|
|
|
|
if (status == EXIT_SUCCESS)
|
|
|
|
@ -573,6 +574,50 @@ change_directory(char const *dir)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define TIME_T_BITS_IN_FILE 64
|
|
|
|
|
|
|
|
|
|
/* The minimum and maximum values representable in a TZif file. */
|
|
|
|
|
static zic_t const min_time = MINVAL(zic_t, TIME_T_BITS_IN_FILE);
|
|
|
|
|
static zic_t const max_time = MAXVAL(zic_t, TIME_T_BITS_IN_FILE);
|
|
|
|
|
|
|
|
|
|
/* The minimum, and one less than the maximum, values specified by
|
|
|
|
|
the -r option. These default to MIN_TIME and MAX_TIME. */
|
|
|
|
|
static zic_t lo_time = MINVAL(zic_t, TIME_T_BITS_IN_FILE);
|
|
|
|
|
static zic_t hi_time = MAXVAL(zic_t, TIME_T_BITS_IN_FILE);
|
|
|
|
|
|
|
|
|
|
/* Set the time range of the output to TIMERANGE.
|
|
|
|
|
Return true if successful. */
|
|
|
|
|
static bool
|
|
|
|
|
timerange_option(char *timerange)
|
|
|
|
|
{
|
|
|
|
|
int64 lo = min_time,
|
|
|
|
|
hi = max_time;
|
|
|
|
|
char *lo_end = timerange,
|
|
|
|
|
*hi_end;
|
|
|
|
|
|
|
|
|
|
if (*timerange == '@')
|
|
|
|
|
{
|
|
|
|
|
errno = 0;
|
|
|
|
|
lo = strtoimax(timerange + 1, &lo_end, 10);
|
|
|
|
|
if (lo_end == timerange + 1 || (lo == INTMAX_MAX && errno == ERANGE))
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
hi_end = lo_end;
|
|
|
|
|
if (lo_end[0] == '/' && lo_end[1] == '@')
|
|
|
|
|
{
|
|
|
|
|
errno = 0;
|
|
|
|
|
hi = strtoimax(lo_end + 2, &hi_end, 10);
|
|
|
|
|
if (hi_end == lo_end + 2 || hi == INTMAX_MIN)
|
|
|
|
|
return false;
|
|
|
|
|
hi -= !(hi == INTMAX_MAX && errno == ERANGE);
|
|
|
|
|
}
|
|
|
|
|
if (*hi_end || hi < lo || max_time < lo || hi < min_time)
|
|
|
|
|
return false;
|
|
|
|
|
lo_time = lo < min_time ? min_time : lo;
|
|
|
|
|
hi_time = max_time < hi ? max_time : hi;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const char *psxrules;
|
|
|
|
|
static const char *lcltime;
|
|
|
|
|
static const char *directory;
|
|
|
|
@ -587,6 +632,7 @@ main(int argc, char **argv)
|
|
|
|
|
k;
|
|
|
|
|
ptrdiff_t i,
|
|
|
|
|
j;
|
|
|
|
|
bool timerange_given = false;
|
|
|
|
|
|
|
|
|
|
#ifndef WIN32
|
|
|
|
|
umask(umask(S_IWGRP | S_IWOTH) | (S_IWGRP | S_IWOTH));
|
|
|
|
@ -609,7 +655,7 @@ main(int argc, char **argv)
|
|
|
|
|
{
|
|
|
|
|
usage(stdout, EXIT_SUCCESS);
|
|
|
|
|
}
|
|
|
|
|
while ((c = getopt(argc, argv, "d:l:L:p:Pst:vy:")) != EOF && c != -1)
|
|
|
|
|
while ((c = getopt(argc, argv, "d:l:L:p:Pr:st:vy:")) != EOF && c != -1)
|
|
|
|
|
switch (c)
|
|
|
|
|
{
|
|
|
|
|
default:
|
|
|
|
@ -690,6 +736,23 @@ main(int argc, char **argv)
|
|
|
|
|
print_abbrevs = true;
|
|
|
|
|
print_cutoff = time(NULL);
|
|
|
|
|
break;
|
|
|
|
|
case 'r':
|
|
|
|
|
if (timerange_given)
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
_("%s: More than one -r option specified\n"),
|
|
|
|
|
progname);
|
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
if (!timerange_option(optarg))
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
_("%s: invalid time range: %s\n"),
|
|
|
|
|
progname, optarg);
|
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
timerange_given = true;
|
|
|
|
|
break;
|
|
|
|
|
case 's':
|
|
|
|
|
warning(_("-s ignored"));
|
|
|
|
|
break;
|
|
|
|
@ -996,11 +1059,6 @@ dolink(char const *fromfield, char const *tofield, bool staysymlink)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define TIME_T_BITS_IN_FILE 64
|
|
|
|
|
|
|
|
|
|
static zic_t const min_time = MINVAL(zic_t, TIME_T_BITS_IN_FILE);
|
|
|
|
|
static zic_t const max_time = MAXVAL(zic_t, TIME_T_BITS_IN_FILE);
|
|
|
|
|
|
|
|
|
|
/* Return true if NAME is a directory. */
|
|
|
|
|
static bool
|
|
|
|
|
itsdir(char const *name)
|
|
|
|
@ -1897,12 +1955,17 @@ puttzcode(const int32 val, FILE *const fp)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
puttzcode64(const zic_t val, FILE *const fp)
|
|
|
|
|
puttzcodepass(zic_t val, FILE *fp, int pass)
|
|
|
|
|
{
|
|
|
|
|
char buf[8];
|
|
|
|
|
if (pass == 1)
|
|
|
|
|
puttzcode(val, fp);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
char buf[8];
|
|
|
|
|
|
|
|
|
|
convert64(val, buf);
|
|
|
|
|
fwrite(buf, sizeof buf, 1, fp);
|
|
|
|
|
convert64(val, buf);
|
|
|
|
|
fwrite(buf, sizeof buf, 1, fp);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
@ -1949,6 +2012,42 @@ swaptypes(int i, int j)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct timerange
|
|
|
|
|
{
|
|
|
|
|
int defaulttype;
|
|
|
|
|
ptrdiff_t base,
|
|
|
|
|
count;
|
|
|
|
|
int leapbase,
|
|
|
|
|
leapcount;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static struct timerange
|
|
|
|
|
limitrange(struct timerange r, zic_t lo, zic_t hi,
|
|
|
|
|
zic_t const *ats, unsigned char const *types)
|
|
|
|
|
{
|
|
|
|
|
while (0 < r.count && ats[r.base] < lo)
|
|
|
|
|
{
|
|
|
|
|
r.defaulttype = types[r.base];
|
|
|
|
|
r.count--;
|
|
|
|
|
r.base++;
|
|
|
|
|
}
|
|
|
|
|
while (0 < r.leapcount && trans[r.leapbase] < lo)
|
|
|
|
|
{
|
|
|
|
|
r.leapcount--;
|
|
|
|
|
r.leapbase++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (hi < ZIC_MAX)
|
|
|
|
|
{
|
|
|
|
|
while (0 < r.count && hi + 1 < ats[r.base + r.count - 1])
|
|
|
|
|
r.count--;
|
|
|
|
|
while (0 < r.leapcount && hi + 1 < trans[r.leapbase + r.leapcount - 1])
|
|
|
|
|
r.leapcount--;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
writezone(const char *const name, const char *const string, char version,
|
|
|
|
|
int defaulttype)
|
|
|
|
@ -1956,10 +2055,6 @@ writezone(const char *const name, const char *const string, char version,
|
|
|
|
|
FILE *fp;
|
|
|
|
|
ptrdiff_t i,
|
|
|
|
|
j;
|
|
|
|
|
int leapcnt32,
|
|
|
|
|
leapi32;
|
|
|
|
|
ptrdiff_t timecnt32,
|
|
|
|
|
timei32;
|
|
|
|
|
int pass;
|
|
|
|
|
static const struct tzhead tzh0;
|
|
|
|
|
static struct tzhead tzh;
|
|
|
|
@ -1975,6 +2070,9 @@ writezone(const char *const name, const char *const string, char version,
|
|
|
|
|
zic_t *ats = emalloc(MAXALIGN(size_product(nats, sizeof *ats + 1)));
|
|
|
|
|
void *typesptr = ats + nats;
|
|
|
|
|
unsigned char *types = typesptr;
|
|
|
|
|
struct timerange rangeall,
|
|
|
|
|
range32,
|
|
|
|
|
range64;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Sort.
|
|
|
|
@ -2061,35 +2159,12 @@ writezone(const char *const name, const char *const string, char version,
|
|
|
|
|
timecnt++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Figure out 32-bit-limited starts and counts.
|
|
|
|
|
*/
|
|
|
|
|
timecnt32 = timecnt;
|
|
|
|
|
timei32 = 0;
|
|
|
|
|
leapcnt32 = leapcnt;
|
|
|
|
|
leapi32 = 0;
|
|
|
|
|
while (0 < timecnt32 && PG_INT32_MAX < ats[timecnt32 - 1])
|
|
|
|
|
--timecnt32;
|
|
|
|
|
while (1 < timecnt32 && ats[timei32] < PG_INT32_MIN
|
|
|
|
|
&& ats[timei32 + 1] <= PG_INT32_MIN)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* Discard too-low transitions, except keep any last too-low
|
|
|
|
|
* transition if no transition is exactly at PG_INT32_MIN. The kept
|
|
|
|
|
* transition will be output as an PG_INT32_MIN "transition"
|
|
|
|
|
* appropriate for buggy 32-bit clients that do not use time type 0
|
|
|
|
|
* for timestamps before the first transition; see below.
|
|
|
|
|
*/
|
|
|
|
|
--timecnt32;
|
|
|
|
|
++timei32;
|
|
|
|
|
}
|
|
|
|
|
while (0 < leapcnt32 && PG_INT32_MAX < trans[leapcnt32 - 1])
|
|
|
|
|
--leapcnt32;
|
|
|
|
|
while (0 < leapcnt32 && trans[leapi32] < PG_INT32_MIN)
|
|
|
|
|
{
|
|
|
|
|
--leapcnt32;
|
|
|
|
|
++leapi32;
|
|
|
|
|
}
|
|
|
|
|
rangeall.defaulttype = defaulttype;
|
|
|
|
|
rangeall.base = rangeall.leapbase = 0;
|
|
|
|
|
rangeall.count = timecnt;
|
|
|
|
|
rangeall.leapcount = leapcnt;
|
|
|
|
|
range64 = limitrange(rangeall, lo_time, hi_time, ats, types);
|
|
|
|
|
range32 = limitrange(range64, PG_INT32_MIN, PG_INT32_MAX, ats, types);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Remove old file, if any, to snap links.
|
|
|
|
@ -2130,6 +2205,11 @@ writezone(const char *const name, const char *const string, char version,
|
|
|
|
|
int thisleapi,
|
|
|
|
|
thisleapcnt,
|
|
|
|
|
thisleaplim;
|
|
|
|
|
int currenttype,
|
|
|
|
|
thisdefaulttype;
|
|
|
|
|
bool locut,
|
|
|
|
|
hicut;
|
|
|
|
|
zic_t lo;
|
|
|
|
|
int old0;
|
|
|
|
|
char omittype[TZ_MAX_TYPES];
|
|
|
|
|
int typemap[TZ_MAX_TYPES];
|
|
|
|
@ -2141,36 +2221,79 @@ writezone(const char *const name, const char *const string, char version,
|
|
|
|
|
|
|
|
|
|
if (pass == 1)
|
|
|
|
|
{
|
|
|
|
|
thistimei = timei32;
|
|
|
|
|
thistimecnt = timecnt32;
|
|
|
|
|
/*
|
|
|
|
|
* Arguably the default time type in the 32-bit data should be
|
|
|
|
|
* range32.defaulttype, which is suited for timestamps just before
|
|
|
|
|
* PG_INT32_MIN. However, zic traditionally used the time type of
|
|
|
|
|
* the indefinite past instead. Internet RFC 8532 says readers
|
|
|
|
|
* should ignore 32-bit data, so this discrepancy matters only to
|
|
|
|
|
* obsolete readers where the traditional type might be more
|
|
|
|
|
* appropriate even if it's "wrong". So, use the historical zic
|
|
|
|
|
* value, unless -r specifies a low cutoff that excludes some
|
|
|
|
|
* 32-bit timestamps.
|
|
|
|
|
*/
|
|
|
|
|
thisdefaulttype = (lo_time <= PG_INT32_MIN
|
|
|
|
|
? range64.defaulttype
|
|
|
|
|
: range32.defaulttype);
|
|
|
|
|
|
|
|
|
|
thistimei = range32.base;
|
|
|
|
|
thistimecnt = range32.count;
|
|
|
|
|
toomanytimes = thistimecnt >> 31 >> 1 != 0;
|
|
|
|
|
thisleapi = leapi32;
|
|
|
|
|
thisleapcnt = leapcnt32;
|
|
|
|
|
thisleapi = range32.leapbase;
|
|
|
|
|
thisleapcnt = range32.leapcount;
|
|
|
|
|
locut = PG_INT32_MIN < lo_time;
|
|
|
|
|
hicut = hi_time < PG_INT32_MAX;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
thistimei = 0;
|
|
|
|
|
thistimecnt = timecnt;
|
|
|
|
|
thisdefaulttype = range64.defaulttype;
|
|
|
|
|
thistimei = range64.base;
|
|
|
|
|
thistimecnt = range64.count;
|
|
|
|
|
toomanytimes = thistimecnt >> 31 >> 31 >> 2 != 0;
|
|
|
|
|
thisleapi = 0;
|
|
|
|
|
thisleapcnt = leapcnt;
|
|
|
|
|
thisleapi = range64.leapbase;
|
|
|
|
|
thisleapcnt = range64.leapcount;
|
|
|
|
|
locut = min_time < lo_time;
|
|
|
|
|
hicut = hi_time < max_time;
|
|
|
|
|
}
|
|
|
|
|
if (toomanytimes)
|
|
|
|
|
error(_("too many transition times"));
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Keep the last too-low transition if no transition is exactly at LO.
|
|
|
|
|
* The kept transition will be output as a LO "transition"; see
|
|
|
|
|
* "Output a LO_TIME transition" below. This is needed when the
|
|
|
|
|
* output is truncated at the start, and is also useful when catering
|
|
|
|
|
* to buggy 32-bit clients that do not use time type 0 for timestamps
|
|
|
|
|
* before the first transition.
|
|
|
|
|
*/
|
|
|
|
|
if (0 < thistimei && ats[thistimei] != lo_time)
|
|
|
|
|
{
|
|
|
|
|
thistimei--;
|
|
|
|
|
thistimecnt++;
|
|
|
|
|
locut = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
thistimelim = thistimei + thistimecnt;
|
|
|
|
|
thisleaplim = thisleapi + thisleapcnt;
|
|
|
|
|
if (thistimecnt != 0)
|
|
|
|
|
{
|
|
|
|
|
if (ats[thistimei] == lo_time)
|
|
|
|
|
locut = false;
|
|
|
|
|
if (hi_time < ZIC_MAX && ats[thistimelim - 1] == hi_time + 1)
|
|
|
|
|
hicut = false;
|
|
|
|
|
}
|
|
|
|
|
memset(omittype, true, typecnt);
|
|
|
|
|
omittype[defaulttype] = false;
|
|
|
|
|
omittype[thisdefaulttype] = false;
|
|
|
|
|
for (i = thistimei; i < thistimelim; i++)
|
|
|
|
|
omittype[types[i]] = false;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Reorder types to make DEFAULTTYPE type 0. Use TYPEMAP to swap OLD0
|
|
|
|
|
* and DEFAULTTYPE so that DEFAULTTYPE appears as type 0 in the output
|
|
|
|
|
* instead of OLD0. TYPEMAP also omits unused types.
|
|
|
|
|
* Reorder types to make THISDEFAULTTYPE type 0. Use TYPEMAP to swap
|
|
|
|
|
* OLD0 and THISDEFAULTTYPE so that THISDEFAULTTYPE appears as type 0
|
|
|
|
|
* in the output instead of OLD0. TYPEMAP also omits unused types.
|
|
|
|
|
*/
|
|
|
|
|
old0 = strlen(omittype);
|
|
|
|
|
swaptypes(old0, defaulttype);
|
|
|
|
|
swaptypes(old0, thisdefaulttype);
|
|
|
|
|
|
|
|
|
|
#ifndef LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH
|
|
|
|
|
|
|
|
|
@ -2231,8 +2354,8 @@ writezone(const char *const name, const char *const string, char version,
|
|
|
|
|
thistypecnt = 0;
|
|
|
|
|
for (i = old0; i < typecnt; i++)
|
|
|
|
|
if (!omittype[i])
|
|
|
|
|
typemap[i == old0 ? defaulttype
|
|
|
|
|
: i == defaulttype ? old0 : i]
|
|
|
|
|
typemap[i == old0 ? thisdefaulttype
|
|
|
|
|
: i == thisdefaulttype ? old0 : i]
|
|
|
|
|
= thistypecnt++;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < sizeof indmap / sizeof indmap[0]; ++i)
|
|
|
|
@ -2264,7 +2387,7 @@ writezone(const char *const name, const char *const string, char version,
|
|
|
|
|
convert(thistypecnt, tzh.tzh_ttisgmtcnt);
|
|
|
|
|
convert(thistypecnt, tzh.tzh_ttisstdcnt);
|
|
|
|
|
convert(thisleapcnt, tzh.tzh_leapcnt);
|
|
|
|
|
convert(thistimecnt, tzh.tzh_timecnt);
|
|
|
|
|
convert(locut + thistimecnt + hicut, tzh.tzh_timecnt);
|
|
|
|
|
convert(thistypecnt, tzh.tzh_typecnt);
|
|
|
|
|
convert(thischarcnt, tzh.tzh_charcnt);
|
|
|
|
|
DO(tzh_magic);
|
|
|
|
@ -2314,24 +2437,33 @@ writezone(const char *const name, const char *const string, char version,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i = thistimei; i < thistimelim; ++i)
|
|
|
|
|
if (pass == 1)
|
|
|
|
|
/*
|
|
|
|
|
* Output a LO_TIME transition if needed; see limitrange. But do not
|
|
|
|
|
* go below the minimum representable value for this pass.
|
|
|
|
|
*/
|
|
|
|
|
lo = pass == 1 && lo_time < PG_INT32_MIN ? PG_INT32_MIN : lo_time;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Output an PG_INT32_MIN "transition" if appropriate; see
|
|
|
|
|
* above.
|
|
|
|
|
*/
|
|
|
|
|
puttzcode(((ats[i] < PG_INT32_MIN) ?
|
|
|
|
|
PG_INT32_MIN : ats[i]), fp);
|
|
|
|
|
else
|
|
|
|
|
puttzcode64(ats[i], fp);
|
|
|
|
|
if (locut)
|
|
|
|
|
puttzcodepass(lo, fp, pass);
|
|
|
|
|
for (i = thistimei; i < thistimelim; ++i)
|
|
|
|
|
{
|
|
|
|
|
unsigned char uc;
|
|
|
|
|
zic_t at = ats[i] < lo ? lo : ats[i];
|
|
|
|
|
|
|
|
|
|
uc = typemap[types[i]];
|
|
|
|
|
fwrite(&uc, sizeof uc, 1, fp);
|
|
|
|
|
puttzcodepass(at, fp, pass);
|
|
|
|
|
}
|
|
|
|
|
if (hicut)
|
|
|
|
|
puttzcodepass(hi_time + 1, fp, pass);
|
|
|
|
|
currenttype = 0;
|
|
|
|
|
if (locut)
|
|
|
|
|
putc(currenttype, fp);
|
|
|
|
|
for (i = thistimei; i < thistimelim; ++i)
|
|
|
|
|
{
|
|
|
|
|
currenttype = typemap[types[i]];
|
|
|
|
|
putc(currenttype, fp);
|
|
|
|
|
}
|
|
|
|
|
if (hicut)
|
|
|
|
|
putc(currenttype, fp);
|
|
|
|
|
|
|
|
|
|
for (i = old0; i < typecnt; i++)
|
|
|
|
|
if (!omittype[i])
|
|
|
|
|
{
|
|
|
|
@ -2370,10 +2502,7 @@ writezone(const char *const name, const char *const string, char version,
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
todo = trans[i];
|
|
|
|
|
if (pass == 1)
|
|
|
|
|
puttzcode(todo, fp);
|
|
|
|
|
else
|
|
|
|
|
puttzcode64(todo, fp);
|
|
|
|
|
puttzcodepass(todo, fp, pass);
|
|
|
|
|
puttzcode(corr[i], fp);
|
|
|
|
|
}
|
|
|
|
|
for (i = old0; i < typecnt; i++)
|
|
|
|
@ -2382,7 +2511,7 @@ writezone(const char *const name, const char *const string, char version,
|
|
|
|
|
for (i = old0; i < typecnt; i++)
|
|
|
|
|
if (!omittype[i])
|
|
|
|
|
putc(ttisgmts[i], fp);
|
|
|
|
|
swaptypes(old0, defaulttype);
|
|
|
|
|
swaptypes(old0, thisdefaulttype);
|
|
|
|
|
}
|
|
|
|
|
fprintf(fp, "\n%s\n", string);
|
|
|
|
|
close_file(fp, directory, name);
|
|
|
|
@ -2636,6 +2765,14 @@ stringzone(char *result, struct zone const *zpfirst, ptrdiff_t zonecount)
|
|
|
|
|
dstr;
|
|
|
|
|
|
|
|
|
|
result[0] = '\0';
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Internet RFC 8536 section 5.1 says to use an empty TZ string if future
|
|
|
|
|
* timestamps are truncated.
|
|
|
|
|
*/
|
|
|
|
|
if (hi_time < max_time)
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
zp = zpfirst + zonecount - 1;
|
|
|
|
|
stdrp = dstrp = NULL;
|
|
|
|
|
for (i = 0; i < zp->z_nrules; ++i)
|
|
|
|
@ -3131,12 +3268,13 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
|
|
|
|
|
xr.r_dycode = DC_DOM;
|
|
|
|
|
xr.r_dayofmonth = 1;
|
|
|
|
|
xr.r_tod = 0;
|
|
|
|
|
for (lastat = &attypes[0], i = 1; i < timecnt; i++)
|
|
|
|
|
for (lastat = attypes, i = 1; i < timecnt; i++)
|
|
|
|
|
if (attypes[i].at > lastat->at)
|
|
|
|
|
lastat = &attypes[i];
|
|
|
|
|
if (lastat->at < rpytime(&xr, max_year - 1))
|
|
|
|
|
if (!lastat || lastat->at < rpytime(&xr, max_year - 1))
|
|
|
|
|
{
|
|
|
|
|
addtt(rpytime(&xr, max_year + 1), typecnt - 1);
|
|
|
|
|
addtt(rpytime(&xr, max_year + 1),
|
|
|
|
|
lastat ? lastat->type : defaulttype);
|
|
|
|
|
attypes[timecnt - 1].dontmerge = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|