version 1.74, 2019/04/04 18:18:31 |
version 1.75, 2019/07/03 15:50:16 |
|
|
** This file is in the public domain, so clarified as of |
** This file is in the public domain, so clarified as of |
** 2006-07-17 by Arthur David Olson. |
** 2006-07-17 by Arthur David Olson. |
*/ |
*/ |
|
/* Compile .zi time zone data into TZif binary files. */ |
|
|
#if HAVE_NBTOOL_CONFIG_H |
#if HAVE_NBTOOL_CONFIG_H |
#include "nbtool_config.h" |
#include "nbtool_config.h" |
|
|
int r_wday; |
int r_wday; |
|
|
zic_t r_tod; /* time from midnight */ |
zic_t r_tod; /* time from midnight */ |
bool r_todisstd; /* above is standard time if 1 */ |
bool r_todisstd; /* is r_tod standard time? */ |
/* or wall clock time if 0 */ |
bool r_todisut; /* is r_tod UT? */ |
bool r_todisgmt; /* above is GMT if 1 */ |
|
/* or local time if 0 */ |
|
bool r_isdst; /* is this daylight saving time? */ |
bool r_isdst; /* is this daylight saving time? */ |
zic_t r_stdoff; /* offset from default time (which is |
zic_t r_save; /* offset from standard time */ |
usually standard time) */ |
|
const char * r_abbrvar; /* variable part of abbreviation */ |
const char * r_abbrvar; /* variable part of abbreviation */ |
|
|
bool r_todo; /* a rule to do (used in outzone) */ |
bool r_todo; /* a rule to do (used in outzone) */ |
|
|
lineno z_linenum; |
lineno z_linenum; |
|
|
const char * z_name; |
const char * z_name; |
zic_t z_gmtoff; |
zic_t z_stdoff; |
char * z_rule; |
char * z_rule; |
const char * z_format; |
const char * z_format; |
char z_format_specifier; |
char z_format_specifier; |
|
|
bool z_isdst; |
bool z_isdst; |
zic_t z_stdoff; |
zic_t z_save; |
|
|
struct rule * z_rules; |
struct rule * z_rules; |
ptrdiff_t z_nrules; |
ptrdiff_t z_nrules; |
Line 171 static void associate(void); |
|
Line 169 static void associate(void); |
|
static void dolink(const char *, const char *, bool); |
static void dolink(const char *, const char *, bool); |
static char ** getfields(char * buf); |
static char ** getfields(char * buf); |
static zic_t gethms(const char * string, const char * errstring); |
static zic_t gethms(const char * string, const char * errstring); |
static zic_t getstdoff(char *, bool *); |
static zic_t getsave(char *, bool *); |
static void infile(const char * filename); |
static void infile(const char * filename); |
static void inleap(char ** fields, int nfields); |
static void inleap(char ** fields, int nfields); |
static void inlink(char ** fields, int nfields); |
static void inlink(char ** fields, int nfields); |
Line 242 static int typecnt; |
|
Line 240 static int typecnt; |
|
*/ |
*/ |
|
|
#define ZF_NAME 1 |
#define ZF_NAME 1 |
#define ZF_GMTOFF 2 |
#define ZF_STDOFF 2 |
#define ZF_RULE 3 |
#define ZF_RULE 3 |
#define ZF_FORMAT 4 |
#define ZF_FORMAT 4 |
#define ZF_TILYEAR 5 |
#define ZF_TILYEAR 5 |
Line 256 static int typecnt; |
|
Line 254 static int typecnt; |
|
** Which fields are which on a Zone continuation line. |
** Which fields are which on a Zone continuation line. |
*/ |
*/ |
|
|
#define ZFC_GMTOFF 0 |
#define ZFC_STDOFF 0 |
#define ZFC_RULE 1 |
#define ZFC_RULE 1 |
#define ZFC_FORMAT 2 |
#define ZFC_FORMAT 2 |
#define ZFC_TILYEAR 3 |
#define ZFC_TILYEAR 3 |
Line 277 static int typecnt; |
|
Line 275 static int typecnt; |
|
#define RF_MONTH 5 |
#define RF_MONTH 5 |
#define RF_DAY 6 |
#define RF_DAY 6 |
#define RF_TOD 7 |
#define RF_TOD 7 |
#define RF_STDOFF 8 |
#define RF_SAVE 8 |
#define RF_ABBRVAR 9 |
#define RF_ABBRVAR 9 |
#define RULE_FIELDS 10 |
#define RULE_FIELDS 10 |
|
|
Line 418 static struct attype { |
|
Line 416 static struct attype { |
|
bool dontmerge; |
bool dontmerge; |
unsigned char type; |
unsigned char type; |
} * attypes; |
} * attypes; |
static zic_t gmtoffs[TZ_MAX_TYPES]; |
static zic_t utoffs[TZ_MAX_TYPES]; |
static char isdsts[TZ_MAX_TYPES]; |
static char isdsts[TZ_MAX_TYPES]; |
static unsigned char abbrinds[TZ_MAX_TYPES]; |
static unsigned char desigidx[TZ_MAX_TYPES]; |
static bool ttisstds[TZ_MAX_TYPES]; |
static bool ttisstds[TZ_MAX_TYPES]; |
static bool ttisgmts[TZ_MAX_TYPES]; |
static bool ttisuts[TZ_MAX_TYPES]; |
static char chars[TZ_MAX_CHARS]; |
static char chars[TZ_MAX_CHARS]; |
static zic_t trans[TZ_MAX_LEAPS]; |
static zic_t trans[TZ_MAX_LEAPS]; |
static zic_t corr[TZ_MAX_LEAPS]; |
static zic_t corr[TZ_MAX_LEAPS]; |
Line 584 usage(FILE *stream, int status) |
|
Line 582 usage(FILE *stream, int status) |
|
{ |
{ |
fprintf(stream, |
fprintf(stream, |
_("%s: usage is %s [ --version ] [ --help ] [ -v ] \\\n" |
_("%s: usage is %s [ --version ] [ --help ] [ -v ] \\\n" |
"\t[ -l localtime ] [ -p posixrules ] [ -d directory ] \\\n" |
"\t[ -b {slim|fat} ] [ -d directory ] [ -l localtime ]" |
"\t[ -t localtime-link ] [ -L leapseconds ] [ -r '[@lo][/@hi]' ] \\\n" |
" [ -L leapseconds ] \\\n" |
|
"\t[ -p posixrules ] [ -r '[@lo][/@hi]' ] [ -t localtime-link ] \\\n" |
"\t[ filename ... ]\n\n" |
"\t[ filename ... ]\n\n" |
"Report bugs to %s.\n"), |
"Report bugs to %s.\n"), |
progname, progname, REPORT_BUGS_TO); |
progname, progname, REPORT_BUGS_TO); |
Line 660 static const char * leapsec; |
|
Line 659 static const char * leapsec; |
|
static const char * tzdefault; |
static const char * tzdefault; |
static const char * yitcommand; |
static const char * yitcommand; |
|
|
|
/* -1 if the TZif output file should be slim, 0 if default, 1 if the |
|
output should be fat for backward compatibility. Currently the |
|
default is fat, although this may change. */ |
|
static int bloat; |
|
|
|
static bool |
|
want_bloat(void) |
|
{ |
|
return 0 <= bloat; |
|
} |
|
|
|
#ifndef ZIC_BLOAT_DEFAULT |
|
# define ZIC_BLOAT_DEFAULT "fat" |
|
#endif |
|
|
int |
int |
main(int argc, char **argv) |
main(int argc, char **argv) |
{ |
{ |
Line 691 main(int argc, char **argv) |
|
Line 705 main(int argc, char **argv) |
|
} else if (strcmp(argv[k], "--help") == 0) { |
} else if (strcmp(argv[k], "--help") == 0) { |
usage(stdout, EXIT_SUCCESS); |
usage(stdout, EXIT_SUCCESS); |
} |
} |
while ((c = getopt(argc, argv, "d:l:L:p:r:st:vy:")) != EOF && c != -1) |
while ((c = getopt(argc, argv, "b:d:l:L:p:r:st:vy:")) != EOF && c != -1) |
switch (c) { |
switch (c) { |
default: |
default: |
usage(stderr, EXIT_FAILURE); |
usage(stderr, EXIT_FAILURE); |
|
case 'b': |
|
if (strcmp(optarg, "slim") == 0) { |
|
if (0 < bloat) |
|
error(_("incompatible -b options")); |
|
bloat = -1; |
|
} else if (strcmp(optarg, "fat") == 0) { |
|
if (bloat < 0) |
|
error(_("incompatible -b options")); |
|
bloat = 1; |
|
} else |
|
error(_("invalid option: -b '%s'"), optarg); |
|
break; |
case 'd': |
case 'd': |
if (directory == NULL) |
if (directory == NULL) |
directory = optarg; |
directory = optarg; |
Line 780 _("%s: invalid time range: %s\n"), |
|
Line 806 _("%s: invalid time range: %s\n"), |
|
} |
} |
if (optind == argc - 1 && strcmp(argv[optind], "=") == 0) |
if (optind == argc - 1 && strcmp(argv[optind], "=") == 0) |
usage(stderr, EXIT_FAILURE); /* usage message by request */ |
usage(stderr, EXIT_FAILURE); /* usage message by request */ |
|
if (bloat == 0) |
|
bloat = strcmp(ZIC_BLOAT_DEFAULT, "slim") == 0 ? -1 : 1; |
if (directory == NULL) |
if (directory == NULL) |
directory = TZDIR; |
directory = TZDIR; |
if (tzdefault == NULL) |
if (tzdefault == NULL) |
Line 1078 associate(void) |
|
Line 1106 associate(void) |
|
{ |
{ |
struct zone * zp; |
struct zone * zp; |
struct rule * rp; |
struct rule * rp; |
ptrdiff_t base, out; |
ptrdiff_t i, j, base, out; |
int i, j; |
|
|
|
if (nrules != 0) { |
if (nrules != 0) { |
qsort(rules, (size_t)nrules, sizeof *rules, rcomp); |
qsort(rules, (size_t)nrules, sizeof *rules, rcomp); |
Line 1134 associate(void) |
|
Line 1161 associate(void) |
|
** Maybe we have a local standard time offset. |
** Maybe we have a local standard time offset. |
*/ |
*/ |
eat(zp->z_filename, zp->z_linenum); |
eat(zp->z_filename, zp->z_linenum); |
zp->z_stdoff = getstdoff(zp->z_rule, &zp->z_isdst); |
zp->z_save = getsave(zp->z_rule, &zp->z_isdst); |
/* |
/* |
** Note, though, that if there's no rule, |
** Note, though, that if there's no rule, |
** a '%s' in the format is a bad thing. |
** a '%s' in the format is a bad thing. |
Line 1292 warning(_("values over 24 hours not hand |
|
Line 1319 warning(_("values over 24 hours not hand |
|
} |
} |
|
|
static zic_t |
static zic_t |
getstdoff(char *field, bool *isdst) |
getsave(char *field, bool *isdst) |
{ |
{ |
int dst = -1; |
int dst = -1; |
zic_t stdoff; |
zic_t save; |
size_t fieldlen = strlen(field); |
size_t fieldlen = strlen(field); |
if (fieldlen != 0) { |
if (fieldlen != 0) { |
char *ep = field + fieldlen - 1; |
char *ep = field + fieldlen - 1; |
Line 1304 getstdoff(char *field, bool *isdst) |
|
Line 1331 getstdoff(char *field, bool *isdst) |
|
case 's': dst = 0; *ep = '\0'; break; |
case 's': dst = 0; *ep = '\0'; break; |
} |
} |
} |
} |
stdoff = gethms(field, _("invalid saved time")); |
save = gethms(field, _("invalid saved time")); |
*isdst = dst < 0 ? stdoff != 0 : dst; |
*isdst = dst < 0 ? save != 0 : dst; |
return stdoff; |
return save; |
} |
} |
|
|
static void |
static void |
Line 1329 inrule(char **fields, int nfields) |
|
Line 1356 inrule(char **fields, int nfields) |
|
} |
} |
r.r_filename = filename; |
r.r_filename = filename; |
r.r_linenum = linenum; |
r.r_linenum = linenum; |
r.r_stdoff = getstdoff(fields[RF_STDOFF], &r.r_isdst); |
r.r_save = getsave(fields[RF_SAVE], &r.r_isdst); |
rulesub(&r, fields[RF_LOYEAR], fields[RF_HIYEAR], fields[RF_COMMAND], |
rulesub(&r, fields[RF_LOYEAR], fields[RF_HIYEAR], fields[RF_COMMAND], |
fields[RF_MONTH], fields[RF_DAY], fields[RF_TOD]); |
fields[RF_MONTH], fields[RF_DAY], fields[RF_TOD]); |
r.r_name = ecpyalloc(fields[RF_NAME]); |
r.r_name = ecpyalloc(fields[RF_NAME]); |
Line 1390 inzsub(char **fields, int nfields, bool |
|
Line 1417 inzsub(char **fields, int nfields, bool |
|
char * cp; |
char * cp; |
char * cp1; |
char * cp1; |
static struct zone z; |
static struct zone z; |
int i_gmtoff, i_rule, i_format; |
int i_stdoff, i_rule, i_format; |
int i_untilyear, i_untilmonth; |
int i_untilyear, i_untilmonth; |
int i_untilday, i_untiltime; |
int i_untilday, i_untiltime; |
bool hasuntil; |
bool hasuntil; |
|
|
if (iscont) { |
if (iscont) { |
i_gmtoff = ZFC_GMTOFF; |
i_stdoff = ZFC_STDOFF; |
i_rule = ZFC_RULE; |
i_rule = ZFC_RULE; |
i_format = ZFC_FORMAT; |
i_format = ZFC_FORMAT; |
i_untilyear = ZFC_TILYEAR; |
i_untilyear = ZFC_TILYEAR; |
Line 1407 inzsub(char **fields, int nfields, bool |
|
Line 1434 inzsub(char **fields, int nfields, bool |
|
} else if (!namecheck(fields[ZF_NAME])) |
} else if (!namecheck(fields[ZF_NAME])) |
return false; |
return false; |
else { |
else { |
i_gmtoff = ZF_GMTOFF; |
i_stdoff = ZF_STDOFF; |
i_rule = ZF_RULE; |
i_rule = ZF_RULE; |
i_format = ZF_FORMAT; |
i_format = ZF_FORMAT; |
i_untilyear = ZF_TILYEAR; |
i_untilyear = ZF_TILYEAR; |
Line 1418 inzsub(char **fields, int nfields, bool |
|
Line 1445 inzsub(char **fields, int nfields, bool |
|
} |
} |
z.z_filename = filename; |
z.z_filename = filename; |
z.z_linenum = linenum; |
z.z_linenum = linenum; |
z.z_gmtoff = gethms(fields[i_gmtoff], _("invalid UT offset")); |
z.z_stdoff = gethms(fields[i_stdoff], _("invalid UT offset")); |
if ((cp = strchr(fields[i_format], '%')) != 0) { |
if ((cp = strchr(fields[i_format], '%')) != 0) { |
if ((*++cp != 's' && *cp != 'z') || strchr(cp, '%') |
if ((*++cp != 's' && *cp != 'z') || strchr(cp, '%') |
|| strchr(fields[i_format], '/')) { |
|| strchr(fields[i_format], '/')) { |
Line 1611 rulesub(struct rule *rp, const char *loy |
|
Line 1638 rulesub(struct rule *rp, const char *loy |
|
} |
} |
rp->r_month = lp->l_value; |
rp->r_month = lp->l_value; |
rp->r_todisstd = false; |
rp->r_todisstd = false; |
rp->r_todisgmt = false; |
rp->r_todisut = false; |
dp = ecpyalloc(timep); |
dp = ecpyalloc(timep); |
if (*dp != '\0') { |
if (*dp != '\0') { |
ep = dp + strlen(dp) - 1; |
ep = dp + strlen(dp) - 1; |
switch (lowerit(*ep)) { |
switch (lowerit(*ep)) { |
case 's': /* Standard */ |
case 's': /* Standard */ |
rp->r_todisstd = true; |
rp->r_todisstd = true; |
rp->r_todisgmt = false; |
rp->r_todisut = false; |
*ep = '\0'; |
*ep = '\0'; |
break; |
break; |
case 'w': /* Wall */ |
case 'w': /* Wall */ |
rp->r_todisstd = false; |
rp->r_todisstd = false; |
rp->r_todisgmt = false; |
rp->r_todisut = false; |
*ep = '\0'; |
*ep = '\0'; |
break; |
break; |
case 'g': /* Greenwich */ |
case 'g': /* Greenwich */ |
case 'u': /* Universal */ |
case 'u': /* Universal */ |
case 'z': /* Zulu */ |
case 'z': /* Zulu */ |
rp->r_todisstd = true; |
rp->r_todisstd = true; |
rp->r_todisgmt = true; |
rp->r_todisut = true; |
*ep = '\0'; |
*ep = '\0'; |
break; |
break; |
} |
} |
Line 1797 atcomp(const void *avp, const void *bvp) |
|
Line 1824 atcomp(const void *avp, const void *bvp) |
|
return (a < b) ? -1 : (a > b); |
return (a < b) ? -1 : (a > b); |
} |
} |
|
|
static void |
|
swaptypes(int i, int j) |
|
{ |
|
{ zic_t t = gmtoffs[i]; gmtoffs[i] = gmtoffs[j]; gmtoffs[j] = t; } |
|
{ char t = isdsts[i]; isdsts[i] = isdsts[j]; isdsts[j] = t; } |
|
{ unsigned char t = abbrinds[i]; abbrinds[i] = abbrinds[j]; |
|
abbrinds[j] = t; } |
|
{ bool t = ttisstds[i]; ttisstds[i] = ttisstds[j]; ttisstds[j] = t; } |
|
{ bool t = ttisgmts[i]; ttisgmts[i] = ttisgmts[j]; ttisgmts[j] = t; } |
|
} |
|
|
|
struct timerange { |
struct timerange { |
int defaulttype; |
int defaulttype; |
ptrdiff_t base, count; |
ptrdiff_t base, count; |
Line 1874 writezone(const char *const name, const |
|
Line 1890 writezone(const char *const name, const |
|
toi = 0; |
toi = 0; |
fromi = 0; |
fromi = 0; |
for ( ; fromi < timecnt; ++fromi) { |
for ( ; fromi < timecnt; ++fromi) { |
if (toi != 0 && ((attypes[fromi].at + |
if (toi != 0 |
gmtoffs[attypes[toi - 1].type]) <= |
&& ((attypes[fromi].at |
(attypes[toi - 1].at + gmtoffs[toi == 1 ? 0 |
+ utoffs[attypes[toi - 1].type]) |
: attypes[toi - 2].type]))) { |
<= (attypes[toi - 1].at |
|
+ utoffs[toi == 1 ? 0 |
|
: attypes[toi - 2].type]))) { |
attypes[toi - 1].type = |
attypes[toi - 1].type = |
attypes[fromi].type; |
attypes[fromi].type; |
continue; |
continue; |
} |
} |
if (toi == 0 |
if (toi == 0 |
|| attypes[fromi].dontmerge |
|| attypes[fromi].dontmerge |
|| attypes[toi - 1].type != attypes[fromi].type) |
|| (utoffs[attypes[toi - 1].type] |
|
!= utoffs[attypes[fromi].type]) |
|
|| (isdsts[attypes[toi - 1].type] |
|
!= isdsts[attypes[fromi].type]) |
|
|| (desigidx[attypes[toi - 1].type] |
|
!= desigidx[attypes[fromi].type])) |
attypes[toi++] = attypes[fromi]; |
attypes[toi++] = attypes[fromi]; |
} |
} |
timecnt = toi; |
timecnt = toi; |
Line 1927 writezone(const char *const name, const |
|
Line 1950 writezone(const char *const name, const |
|
seconds, as the idea is to insert a transition just before |
seconds, as the idea is to insert a transition just before |
32-bit time_t rolls around, and this occurs at a slightly |
32-bit time_t rolls around, and this occurs at a slightly |
different moment if transitions are leap-second corrected. */ |
different moment if transitions are leap-second corrected. */ |
if (WORK_AROUND_QTBUG_53071 && timecnt != 0 |
if (WORK_AROUND_QTBUG_53071 && timecnt != 0 && want_bloat() |
&& ats[timecnt - 1] < y2038_boundary - 1 && strchr(string, '<')) { |
&& ats[timecnt - 1] < y2038_boundary - 1 && strchr(string, '<')) { |
ats[timecnt] = y2038_boundary - 1; |
ats[timecnt] = y2038_boundary - 1; |
types[timecnt] = types[timecnt - 1]; |
types[timecnt] = types[timecnt - 1]; |
Line 1976 writezone(const char *const name, const |
|
Line 1999 writezone(const char *const name, const |
|
int old0; |
int old0; |
char omittype[TZ_MAX_TYPES]; |
char omittype[TZ_MAX_TYPES]; |
int typemap[TZ_MAX_TYPES]; |
int typemap[TZ_MAX_TYPES]; |
int thistypecnt; |
int thistypecnt, stdcnt, utcnt; |
char thischars[TZ_MAX_CHARS]; |
char thischars[TZ_MAX_CHARS]; |
int thischarcnt; |
int thischarcnt; |
bool toomanytimes; |
bool toomanytimes; |
Line 2048 writezone(const char *const name, const |
|
Line 2071 writezone(const char *const name, const |
|
THISDEFAULTTYPE appears as type 0 in the output instead |
THISDEFAULTTYPE appears as type 0 in the output instead |
of OLD0. TYPEMAP also omits unused types. */ |
of OLD0. TYPEMAP also omits unused types. */ |
old0 = strlen(omittype); |
old0 = strlen(omittype); |
swaptypes(old0, thisdefaulttype); |
|
|
|
#ifndef LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH |
#ifndef LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH |
/* |
/* |
Line 2059 writezone(const char *const name, const |
|
Line 2081 writezone(const char *const name, const |
|
** (to help get global "altzone" and "timezone" variables |
** (to help get global "altzone" and "timezone" variables |
** set correctly). |
** set correctly). |
*/ |
*/ |
{ |
if (want_bloat()) { |
int mrudst, mrustd, hidst, histd, type; |
int mrudst, mrustd, hidst, histd, type; |
|
|
hidst = histd = mrudst = mrustd = -1; |
hidst = histd = mrudst = mrustd = -1; |
Line 2067 writezone(const char *const name, const |
|
Line 2089 writezone(const char *const name, const |
|
if (isdsts[types[i]]) |
if (isdsts[types[i]]) |
mrudst = types[i]; |
mrudst = types[i]; |
else mrustd = types[i]; |
else mrustd = types[i]; |
for (i = old0; i < typecnt; i++) |
for (i = old0; i < typecnt; i++) { |
if (!omittype[i]) { |
int h = (i == old0 ? thisdefaulttype |
if (isdsts[i]) |
: i == thisdefaulttype ? old0 : i); |
hidst = i; |
if (!omittype[h]) { |
else histd = i; |
if (isdsts[h]) |
} |
hidst = i; |
|
else |
|
histd = i; |
|
} |
|
} |
if (hidst >= 0 && mrudst >= 0 && hidst != mrudst && |
if (hidst >= 0 && mrudst >= 0 && hidst != mrudst && |
gmtoffs[hidst] != gmtoffs[mrudst]) { |
utoffs[hidst] != utoffs[mrudst]) { |
isdsts[mrudst] = -1; |
isdsts[mrudst] = -1; |
type = addtype(gmtoffs[mrudst], |
type = addtype(utoffs[mrudst], |
&chars[abbrinds[mrudst]], |
&chars[desigidx[mrudst]], |
true, |
true, |
ttisstds[mrudst], |
ttisstds[mrudst], |
ttisgmts[mrudst]); |
ttisuts[mrudst]); |
isdsts[mrudst] = 1; |
isdsts[mrudst] = 1; |
omittype[type] = false; |
omittype[type] = false; |
} |
} |
if (histd >= 0 && mrustd >= 0 && histd != mrustd && |
if (histd >= 0 && mrustd >= 0 && histd != mrustd && |
gmtoffs[histd] != gmtoffs[mrustd]) { |
utoffs[histd] != utoffs[mrustd]) { |
isdsts[mrustd] = -1; |
isdsts[mrustd] = -1; |
type = addtype(gmtoffs[mrustd], |
type = addtype(utoffs[mrustd], |
&chars[abbrinds[mrustd]], |
&chars[desigidx[mrustd]], |
false, |
false, |
ttisstds[mrustd], |
ttisstds[mrustd], |
ttisgmts[mrustd]); |
ttisuts[mrustd]); |
isdsts[mrustd] = 0; |
isdsts[mrustd] = 0; |
omittype[type] = true; |
omittype[type] = false; |
} |
} |
} |
} |
#endif /* !defined LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH */ |
#endif /* !defined LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH */ |
Line 2106 writezone(const char *const name, const |
|
Line 2132 writezone(const char *const name, const |
|
|
|
for (i = 0; i < (int)(sizeof indmap / sizeof indmap[0]); ++i) |
for (i = 0; i < (int)(sizeof indmap / sizeof indmap[0]); ++i) |
indmap[i] = -1; |
indmap[i] = -1; |
thischarcnt = 0; |
thischarcnt = stdcnt = utcnt = 0; |
for (i = old0; i < typecnt; i++) { |
for (i = old0; i < typecnt; i++) { |
char * thisabbr; |
char * thisabbr; |
|
|
if (omittype[i]) |
if (omittype[i]) |
continue; |
continue; |
if (indmap[abbrinds[i]] >= 0) |
if (ttisstds[i]) |
|
stdcnt = thistypecnt; |
|
if (ttisuts[i]) |
|
utcnt = thistypecnt; |
|
if (indmap[desigidx[i]] >= 0) |
continue; |
continue; |
thisabbr = &chars[abbrinds[i]]; |
thisabbr = &chars[desigidx[i]]; |
for (j = 0; j < thischarcnt; ++j) |
for (j = 0; j < thischarcnt; ++j) |
if (strcmp(&thischars[j], thisabbr) == 0) |
if (strcmp(&thischars[j], thisabbr) == 0) |
break; |
break; |
Line 2122 writezone(const char *const name, const |
|
Line 2152 writezone(const char *const name, const |
|
strcpy(&thischars[thischarcnt], thisabbr); |
strcpy(&thischars[thischarcnt], thisabbr); |
thischarcnt += strlen(thisabbr) + 1; |
thischarcnt += strlen(thisabbr) + 1; |
} |
} |
indmap[abbrinds[i]] = j; |
indmap[desigidx[i]] = j; |
|
} |
|
if (pass == 1 && !want_bloat()) { |
|
utcnt = stdcnt = thisleapcnt = 0; |
|
thistimecnt = - locut - hicut; |
|
thistypecnt = thischarcnt = 1; |
|
thistimelim = thistimei; |
} |
} |
#define DO(field) fwrite(tzh.field, sizeof tzh.field, (size_t) 1, fp) |
#define DO(field) fwrite(tzh.field, sizeof tzh.field, (size_t) 1, fp) |
tzh = tzh0; |
tzh = tzh0; |
memcpy(tzh.tzh_magic, TZ_MAGIC, sizeof tzh.tzh_magic); |
memcpy(tzh.tzh_magic, TZ_MAGIC, sizeof tzh.tzh_magic); |
tzh.tzh_version[0] = version; |
tzh.tzh_version[0] = version; |
convert(thistypecnt, tzh.tzh_ttisgmtcnt); |
convert(utcnt, tzh.tzh_ttisutcnt); |
convert(thistypecnt, tzh.tzh_ttisstdcnt); |
convert(stdcnt, tzh.tzh_ttisstdcnt); |
convert(thisleapcnt, tzh.tzh_leapcnt); |
convert(thisleapcnt, tzh.tzh_leapcnt); |
convert(locut + thistimecnt + hicut, tzh.tzh_timecnt); |
convert(locut + thistimecnt + hicut, tzh.tzh_timecnt); |
convert(thistypecnt, tzh.tzh_typecnt); |
convert(thistypecnt, tzh.tzh_typecnt); |
Line 2137 writezone(const char *const name, const |
|
Line 2173 writezone(const char *const name, const |
|
DO(tzh_magic); |
DO(tzh_magic); |
DO(tzh_version); |
DO(tzh_version); |
DO(tzh_reserved); |
DO(tzh_reserved); |
DO(tzh_ttisgmtcnt); |
DO(tzh_ttisutcnt); |
DO(tzh_ttisstdcnt); |
DO(tzh_ttisstdcnt); |
DO(tzh_leapcnt); |
DO(tzh_leapcnt); |
DO(tzh_timecnt); |
DO(tzh_timecnt); |
DO(tzh_typecnt); |
DO(tzh_typecnt); |
DO(tzh_charcnt); |
DO(tzh_charcnt); |
#undef DO |
#undef DO |
|
if (pass == 1 && !want_bloat()) { |
|
/* Output a minimal data block with just one time type. */ |
|
puttzcode(0, fp); /* utoff */ |
|
putc(0, fp); /* dst */ |
|
putc(0, fp); /* index of abbreviation */ |
|
putc(0, fp); /* empty-string abbreviation */ |
|
continue; |
|
} |
|
|
/* Output a LO_TIME transition if needed; see limitrange. |
/* Output a LO_TIME transition if needed; see limitrange. |
But do not go below the minimum representable value |
But do not go below the minimum representable value |
for this pass. */ |
for this pass. */ |
Line 2167 writezone(const char *const name, const |
|
Line 2212 writezone(const char *const name, const |
|
if (hicut) |
if (hicut) |
putc(currenttype, fp); |
putc(currenttype, fp); |
|
|
for (i = old0; i < typecnt; i++) |
for (i = old0; i < typecnt; i++) { |
if (!omittype[i]) { |
int h = (i == old0 ? thisdefaulttype |
puttzcode(gmtoffs[i], fp); |
: i == thisdefaulttype ? old0 : i); |
putc(isdsts[i], fp); |
if (!omittype[h]) { |
putc((unsigned char) indmap[abbrinds[i]], fp); |
puttzcode(utoffs[h], fp); |
} |
putc(isdsts[h], fp); |
|
putc(indmap[desigidx[h]], fp); |
|
} |
|
} |
if (thischarcnt != 0) |
if (thischarcnt != 0) |
fwrite(thischars, sizeof thischars[0], |
fwrite(thischars, sizeof thischars[0], |
(size_t) thischarcnt, fp); |
(size_t) thischarcnt, fp); |
Line 2194 writezone(const char *const name, const |
|
Line 2242 writezone(const char *const name, const |
|
++j; |
++j; |
j = types[j - 1]; |
j = types[j - 1]; |
} |
} |
todo = tadd(trans[i], -gmtoffs[j]); |
todo = tadd(trans[i], -utoffs[j]); |
} else todo = trans[i]; |
} else todo = trans[i]; |
puttzcodepass(todo, fp, pass); |
puttzcodepass(todo, fp, pass); |
puttzcode(corr[i], fp); |
puttzcode(corr[i], fp); |
} |
} |
for (i = old0; i < typecnt; i++) |
if (stdcnt != 0) |
|
for (i = old0; i < typecnt; i++) |
if (!omittype[i]) |
if (!omittype[i]) |
putc(ttisstds[i], fp); |
putc(ttisstds[i], fp); |
for (i = old0; i < typecnt; i++) |
if (utcnt != 0) |
|
for (i = old0; i < typecnt; i++) |
if (!omittype[i]) |
if (!omittype[i]) |
putc(ttisgmts[i], fp); |
putc(ttisuts[i], fp); |
swaptypes(old0, thisdefaulttype); |
|
} |
} |
fprintf(fp, "\n%s\n", string); |
fprintf(fp, "\n%s\n", string); |
close_file(fp, directory, name); |
close_file(fp, directory, name); |
Line 2250 abbroffset(char *buf, zic_t offset) |
|
Line 2299 abbroffset(char *buf, zic_t offset) |
|
|
|
static size_t |
static size_t |
doabbr(char *abbr, int abbrlen, struct zone const *zp, const char *letters, |
doabbr(char *abbr, int abbrlen, struct zone const *zp, const char *letters, |
bool isdst, zic_t stdoff, bool doquotes) |
bool isdst, zic_t save, bool doquotes) |
{ |
{ |
char * cp; |
char * cp; |
char * slashp; |
char * slashp; |
Line 2261 doabbr(char *abbr, int abbrlen, struct z |
|
Line 2310 doabbr(char *abbr, int abbrlen, struct z |
|
if (slashp == NULL) { |
if (slashp == NULL) { |
char letterbuf[PERCENT_Z_LEN_BOUND + 1]; |
char letterbuf[PERCENT_Z_LEN_BOUND + 1]; |
if (zp->z_format_specifier == 'z') |
if (zp->z_format_specifier == 'z') |
letters = abbroffset(letterbuf, zp->z_gmtoff + stdoff); |
letters = abbroffset(letterbuf, zp->z_stdoff + save); |
else if (!letters) |
else if (!letters) |
letters = "%s"; |
letters = "%s"; |
snprintf(abbr, abbrlen, format, letters); |
snprintf(abbr, abbrlen, format, letters); |
Line 2326 stringoffset(char *result, zic_t offset) |
|
Line 2375 stringoffset(char *result, zic_t offset) |
|
} |
} |
|
|
static int |
static int |
stringrule(char *result, const struct rule *const rp, const zic_t dstoff, |
stringrule(char *result, struct rule *const rp, zic_t save, const zic_t stdoff) |
const zic_t gmtoff) |
|
{ |
{ |
zic_t tod = rp->r_tod; |
zic_t tod = rp->r_tod; |
int compat = 0; |
int compat = 0; |
Line 2374 stringrule(char *result, const struct ru |
|
Line 2422 stringrule(char *result, const struct ru |
|
result += sprintf(result, "M%d.%d.%d", |
result += sprintf(result, "M%d.%d.%d", |
rp->r_month + 1, week, wday); |
rp->r_month + 1, week, wday); |
} |
} |
if (rp->r_todisgmt) |
if (rp->r_todisut) |
tod += gmtoff; |
tod += stdoff; |
if (rp->r_todisstd && !rp->r_isdst) |
if (rp->r_todisstd && !rp->r_isdst) |
tod += dstoff; |
tod += save; |
if (tod != 2 * SECSPERMIN * MINSPERHOUR) { |
if (tod != 2 * SECSPERMIN * MINSPERHOUR) { |
*result++ = '/'; |
*result++ = '/'; |
if (! stringoffset(result, tod)) |
if (! stringoffset(result, tod)) |
Line 2407 rule_cmp(struct rule const *a, struct ru |
|
Line 2455 rule_cmp(struct rule const *a, struct ru |
|
return a->r_dayofmonth - b->r_dayofmonth; |
return a->r_dayofmonth - b->r_dayofmonth; |
} |
} |
|
|
enum { YEAR_BY_YEAR_ZONE = 1 }; |
|
|
|
static int |
static int |
stringzone(char *result, const int resultlen, const struct zone *const zpfirst, |
stringzone(char *result, int resultlen, const struct zone *const zpfirst, |
const int zonecount) |
const int zonecount) |
{ |
{ |
const struct zone * zp; |
const struct zone * zp; |
Line 2464 stringzone(char *result, const int resul |
|
Line 2510 stringzone(char *result, const int resul |
|
if (rule_cmp(stdrp, rp) < 0) |
if (rule_cmp(stdrp, rp) < 0) |
stdrp = rp; |
stdrp = rp; |
} |
} |
/* |
|
** Horrid special case: if year is 2037, |
|
** presume this is a zone handled on a year-by-year basis; |
|
** do not try to apply a rule to the zone. |
|
*/ |
|
if (stdrp != NULL && stdrp->r_hiyear == 2037) |
|
return YEAR_BY_YEAR_ZONE; |
|
|
|
if (stdrp != NULL && stdrp->r_isdst) { |
if (stdrp != NULL && stdrp->r_isdst) { |
/* Perpetual DST. */ |
/* Perpetual DST. */ |
dstr.r_month = TM_JANUARY; |
dstr.r_month = TM_JANUARY; |
dstr.r_dycode = DC_DOM; |
dstr.r_dycode = DC_DOM; |
dstr.r_dayofmonth = 1; |
dstr.r_dayofmonth = 1; |
dstr.r_tod = 0; |
dstr.r_tod = 0; |
dstr.r_todisstd = dstr.r_todisgmt = false; |
dstr.r_todisstd = dstr.r_todisut = false; |
dstr.r_isdst = stdrp->r_isdst; |
dstr.r_isdst = stdrp->r_isdst; |
dstr.r_stdoff = stdrp->r_stdoff; |
dstr.r_save = stdrp->r_save; |
dstr.r_abbrvar = stdrp->r_abbrvar; |
dstr.r_abbrvar = stdrp->r_abbrvar; |
stdr.r_month = TM_DECEMBER; |
stdr.r_month = TM_DECEMBER; |
stdr.r_dycode = DC_DOM; |
stdr.r_dycode = DC_DOM; |
stdr.r_dayofmonth = 31; |
stdr.r_dayofmonth = 31; |
stdr.r_tod = SECSPERDAY + stdrp->r_stdoff; |
stdr.r_tod = SECSPERDAY + stdrp->r_save; |
stdr.r_todisstd = stdr.r_todisgmt = false; |
stdr.r_todisstd = stdr.r_todisut = false; |
stdr.r_isdst = false; |
stdr.r_isdst = false; |
stdr.r_stdoff = 0; |
stdr.r_save = 0; |
stdr.r_abbrvar |
stdr.r_abbrvar |
= (stdabbrrp ? stdabbrrp->r_abbrvar : ""); |
= (stdabbrrp ? stdabbrrp->r_abbrvar : ""); |
dstrp = &dstr; |
dstrp = &dstr; |
Line 2499 stringzone(char *result, const int resul |
|
Line 2537 stringzone(char *result, const int resul |
|
return -1; |
return -1; |
abbrvar = (stdrp == NULL) ? "" : stdrp->r_abbrvar; |
abbrvar = (stdrp == NULL) ? "" : stdrp->r_abbrvar; |
len = doabbr(result, resultlen, zp, abbrvar, false, 0, true); |
len = doabbr(result, resultlen, zp, abbrvar, false, 0, true); |
offsetlen = stringoffset(result + len, -zp->z_gmtoff); |
offsetlen = stringoffset(result + len, -zp->z_stdoff); |
if (! offsetlen) { |
if (! offsetlen) { |
result[0] = '\0'; |
result[0] = '\0'; |
return -1; |
return -1; |
Line 2508 stringzone(char *result, const int resul |
|
Line 2546 stringzone(char *result, const int resul |
|
if (dstrp == NULL) |
if (dstrp == NULL) |
return compat; |
return compat; |
len += doabbr(result + len, resultlen - len, zp, dstrp->r_abbrvar, |
len += doabbr(result + len, resultlen - len, zp, dstrp->r_abbrvar, |
dstrp->r_isdst, dstrp->r_stdoff, true); |
dstrp->r_isdst, dstrp->r_save, true); |
if (dstrp->r_stdoff != SECSPERMIN * MINSPERHOUR) { |
if (dstrp->r_save != SECSPERMIN * MINSPERHOUR) { |
offsetlen = stringoffset(result + len, |
offsetlen = stringoffset(result + len, |
-(zp->z_gmtoff + dstrp->r_stdoff)); |
- (zp->z_stdoff + dstrp->r_save)); |
if (! offsetlen) { |
if (! offsetlen) { |
result[0] = '\0'; |
result[0] = '\0'; |
return -1; |
return -1; |
Line 2519 stringzone(char *result, const int resul |
|
Line 2557 stringzone(char *result, const int resul |
|
len += offsetlen; |
len += offsetlen; |
} |
} |
result[len++] = ','; |
result[len++] = ','; |
c = stringrule(result + len, dstrp, dstrp->r_stdoff, zp->z_gmtoff); |
c = stringrule(result + len, dstrp, dstrp->r_save, zp->z_stdoff); |
if (c < 0) { |
if (c < 0) { |
result[0] = '\0'; |
result[0] = '\0'; |
return -1; |
return -1; |
Line 2528 stringzone(char *result, const int resul |
|
Line 2566 stringzone(char *result, const int resul |
|
compat = c; |
compat = c; |
len += strlen(result + len); |
len += strlen(result + len); |
result[len++] = ','; |
result[len++] = ','; |
c = stringrule(result + len, stdrp, dstrp->r_stdoff, zp->z_gmtoff); |
c = stringrule(result + len, stdrp, dstrp->r_save, zp->z_stdoff); |
if (c < 0) { |
if (c < 0) { |
result[0] = '\0'; |
result[0] = '\0'; |
return -1; |
return -1; |
Line 2546 outzone(const struct zone *zpfirst, ptrd |
|
Line 2584 outzone(const struct zone *zpfirst, ptrd |
|
ptrdiff_t i, j; |
ptrdiff_t i, j; |
bool usestart, useuntil; |
bool usestart, useuntil; |
zic_t starttime, untiltime; |
zic_t starttime, untiltime; |
zic_t gmtoff; |
|
zic_t stdoff; |
zic_t stdoff; |
|
zic_t save; |
zic_t year; |
zic_t year; |
zic_t startoff; |
zic_t startoff; |
bool startttisstd; |
bool startttisstd; |
bool startttisgmt; |
bool startttisut; |
int type; |
int type; |
char * startbuf; |
char * startbuf; |
char * ab; |
char * ab; |
Line 2561 outzone(const struct zone *zpfirst, ptrd |
|
Line 2599 outzone(const struct zone *zpfirst, ptrd |
|
bool prodstic; /* all rules are min to max */ |
bool prodstic; /* all rules are min to max */ |
int compat; |
int compat; |
bool do_extend; |
bool do_extend; |
int version; |
char version; |
ptrdiff_t lastatmax = -1; |
ptrdiff_t lastatmax = -1; |
zic_t one = 1; |
zic_t one = 1; |
zic_t y2038_boundary = one << 31; |
zic_t y2038_boundary = one << 31; |
Line 2587 outzone(const struct zone *zpfirst, ptrd |
|
Line 2625 outzone(const struct zone *zpfirst, ptrd |
|
** for noting the need to unconditionally initialize startttisstd. |
** for noting the need to unconditionally initialize startttisstd. |
*/ |
*/ |
startttisstd = false; |
startttisstd = false; |
startttisgmt = false; |
startttisut = false; |
min_year = max_year = EPOCH_YEAR; |
min_year = max_year = EPOCH_YEAR; |
if (leapseen) { |
if (leapseen) { |
updateminmax(leapminyear); |
updateminmax(leapminyear); |
Line 2612 outzone(const struct zone *zpfirst, ptrd |
|
Line 2650 outzone(const struct zone *zpfirst, ptrd |
|
*/ |
*/ |
compat = stringzone(envvar, max_envvar_len + 1, zpfirst, zonecount); |
compat = stringzone(envvar, max_envvar_len + 1, zpfirst, zonecount); |
version = compat < 2013 ? ZIC_VERSION_PRE_2013 : ZIC_VERSION; |
version = compat < 2013 ? ZIC_VERSION_PRE_2013 : ZIC_VERSION; |
do_extend = compat < 0 || compat == YEAR_BY_YEAR_ZONE; |
do_extend = compat < 0; |
if (noise) { |
if (noise) { |
if (!*envvar) |
if (!*envvar) |
warning("%s %s", |
warning("%s %s", |
_("no POSIX environment variable for zone"), |
_("no POSIX environment variable for zone"), |
zpfirst->z_name); |
zpfirst->z_name); |
else if (compat != 0 && compat != YEAR_BY_YEAR_ZONE) { |
else if (compat != 0) { |
/* Circa-COMPAT clients, and earlier clients, might |
/* Circa-COMPAT clients, and earlier clients, might |
not work for this zone when given dates before |
not work for this zone when given dates before |
1970 or after 2038. */ |
1970 or after 2038. */ |
Line 2660 outzone(const struct zone *zpfirst, ptrd |
|
Line 2698 outzone(const struct zone *zpfirst, ptrd |
|
max_year = min_year + years_of_observations; |
max_year = min_year + years_of_observations; |
} |
} |
} |
} |
/* |
|
** For the benefit of older systems, |
|
** generate data from 1900 through 2038. |
|
*/ |
|
if (min_year > 1900) |
|
min_year = 1900; |
|
max_year0 = max_year; |
max_year0 = max_year; |
if (max_year < 2038) |
if (want_bloat()) { |
|
/* 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; |
max_year = 2038; |
|
} |
|
|
for (i = 0; i < zonecount; ++i) { |
for (i = 0; i < zonecount; ++i) { |
|
struct rule *prevrp = NULL; |
/* |
/* |
** A guess that may well be corrected later. |
** A guess that may well be corrected later. |
*/ |
*/ |
stdoff = 0; |
save = 0; |
zp = &zpfirst[i]; |
zp = &zpfirst[i]; |
usestart = i > 0 && (zp - 1)->z_untiltime > min_time; |
usestart = i > 0 && (zp - 1)->z_untiltime > min_time; |
useuntil = i < (zonecount - 1); |
useuntil = i < (zonecount - 1); |
if (useuntil && zp->z_untiltime <= min_time) |
if (useuntil && zp->z_untiltime <= min_time) |
continue; |
continue; |
gmtoff = zp->z_gmtoff; |
stdoff = zp->z_stdoff; |
eat(zp->z_filename, zp->z_linenum); |
eat(zp->z_filename, zp->z_linenum); |
*startbuf = '\0'; |
*startbuf = '\0'; |
startoff = zp->z_gmtoff; |
startoff = zp->z_stdoff; |
if (zp->z_nrules == 0) { |
if (zp->z_nrules == 0) { |
stdoff = zp->z_stdoff; |
save = zp->z_save; |
doabbr(startbuf, max_abbr_len + 1, zp, |
doabbr(startbuf, max_abbr_len + 1, |
NULL, zp->z_isdst, stdoff, false); |
zp, NULL, zp->z_isdst, save, false); |
type = addtype(oadd(zp->z_gmtoff, stdoff), |
type = addtype(oadd(zp->z_stdoff, save), |
startbuf, zp->z_isdst, startttisstd, |
startbuf, zp->z_isdst, startttisstd, |
startttisgmt); |
startttisut); |
if (usestart) { |
if (usestart) { |
addtt(starttime, type); |
addtt(starttime, type); |
usestart = false; |
usestart = false; |
Line 2725 outzone(const struct zone *zpfirst, ptrd |
|
Line 2765 outzone(const struct zone *zpfirst, ptrd |
|
if (useuntil) { |
if (useuntil) { |
/* |
/* |
** Turn untiltime into UT |
** Turn untiltime into UT |
** assuming the current gmtoff and |
** assuming the current stdoff and |
** stdoff values. |
** save values. |
*/ |
*/ |
untiltime = zp->z_untiltime; |
untiltime = zp->z_untiltime; |
if (!zp->z_untilrule.r_todisgmt) |
if (!zp->z_untilrule.r_todisut) |
untiltime = tadd(untiltime, |
untiltime = tadd(untiltime, |
-gmtoff); |
-stdoff); |
if (!zp->z_untilrule.r_todisstd) |
if (!zp->z_untilrule.r_todisstd) |
untiltime = tadd(untiltime, |
untiltime = tadd(untiltime, |
-stdoff); |
-save); |
} |
} |
/* |
/* |
** Find the rule (of those to do, if any) |
** Find the rule (of those to do, if any) |
Line 2747 outzone(const struct zone *zpfirst, ptrd |
|
Line 2787 outzone(const struct zone *zpfirst, ptrd |
|
continue; |
continue; |
eats(zp->z_filename, zp->z_linenum, |
eats(zp->z_filename, zp->z_linenum, |
rp->r_filename, rp->r_linenum); |
rp->r_filename, rp->r_linenum); |
offset = rp->r_todisgmt ? 0 : gmtoff; |
offset = rp->r_todisut ? 0 : stdoff; |
if (!rp->r_todisstd) |
if (!rp->r_todisstd) |
offset = oadd(offset, stdoff); |
offset = oadd(offset, save); |
jtime = rp->r_temp; |
jtime = rp->r_temp; |
if (jtime == min_time || |
if (jtime == min_time || |
jtime == max_time) |
jtime == max_time) |
Line 2776 outzone(const struct zone *zpfirst, ptrd |
|
Line 2816 outzone(const struct zone *zpfirst, ptrd |
|
rp->r_todo = false; |
rp->r_todo = false; |
if (useuntil && ktime >= untiltime) |
if (useuntil && ktime >= untiltime) |
break; |
break; |
stdoff = rp->r_stdoff; |
save = rp->r_save; |
if (usestart && ktime == starttime) |
if (usestart && ktime == starttime) |
usestart = false; |
usestart = false; |
if (usestart) { |
if (usestart) { |
if (ktime < starttime) { |
if (ktime < starttime) { |
startoff = oadd(zp->z_gmtoff, |
startoff = oadd(zp->z_stdoff, |
stdoff); |
save); |
doabbr(startbuf, |
doabbr(startbuf, |
max_abbr_len + 1, |
max_abbr_len + 1, |
zp, |
zp, |
rp->r_abbrvar, |
rp->r_abbrvar, |
rp->r_isdst, |
rp->r_isdst, |
rp->r_stdoff, |
rp->r_save, |
false); |
false); |
continue; |
continue; |
} |
} |
if (*startbuf == '\0' && |
if (*startbuf == '\0' |
startoff == oadd(zp->z_gmtoff, |
&& startoff == oadd(zp->z_stdoff, |
stdoff)) { |
save)) { |
doabbr(startbuf, |
doabbr(startbuf, |
max_abbr_len + 1, |
max_abbr_len + 1, |
zp, |
zp, |
rp->r_abbrvar, |
rp->r_abbrvar, |
rp->r_isdst, |
rp->r_isdst, |
rp->r_stdoff, |
rp->r_save, |
false); |
false); |
} |
} |
} |
} |
eats(zp->z_filename, zp->z_linenum, |
eats(zp->z_filename, zp->z_linenum, |
rp->r_filename, rp->r_linenum); |
rp->r_filename, rp->r_linenum); |
doabbr(ab, max_abbr_len + 1, zp, rp->r_abbrvar, |
doabbr(ab, max_abbr_len + 1, zp, rp->r_abbrvar, |
rp->r_isdst, rp->r_stdoff, false); |
rp->r_isdst, rp->r_save, false); |
offset = oadd(zp->z_gmtoff, rp->r_stdoff); |
offset = oadd(zp->z_stdoff, rp->r_save); |
|
if (!want_bloat() && !useuntil && !do_extend |
|
&& prevrp |
|
&& rp->r_hiyear == ZIC_MAX |
|
&& prevrp->r_hiyear == ZIC_MAX) |
|
break; |
type = addtype(offset, ab, rp->r_isdst, |
type = addtype(offset, ab, rp->r_isdst, |
rp->r_todisstd, rp->r_todisgmt); |
rp->r_todisstd, rp->r_todisut); |
if (defaulttype < 0 && !rp->r_isdst) |
if (defaulttype < 0 && !rp->r_isdst) |
defaulttype = type; |
defaulttype = type; |
if (rp->r_hiyear == ZIC_MAX |
if (rp->r_hiyear == ZIC_MAX |
Line 2818 outzone(const struct zone *zpfirst, ptrd |
|
Line 2863 outzone(const struct zone *zpfirst, ptrd |
|
&& ktime < attypes[lastatmax].at)) |
&& ktime < attypes[lastatmax].at)) |
lastatmax = timecnt; |
lastatmax = timecnt; |
addtt(ktime, type); |
addtt(ktime, type); |
|
prevrp = rp; |
} |
} |
} |
} |
if (usestart) { |
if (usestart) { |
Line 2831 outzone(const struct zone *zpfirst, ptrd |
|
Line 2877 outzone(const struct zone *zpfirst, ptrd |
|
if (*startbuf == '\0') |
if (*startbuf == '\0') |
error(_("can't determine time zone abbreviation to use just after until time")); |
error(_("can't determine time zone abbreviation to use just after until time")); |
else { |
else { |
bool isdst = startoff != zp->z_gmtoff; |
bool isdst = startoff != zp->z_stdoff; |
type = addtype(startoff, startbuf, isdst, |
type = addtype(startoff, startbuf, isdst, |
startttisstd, startttisgmt); |
startttisstd, startttisut); |
if (defaulttype < 0 && !isdst) |
if (defaulttype < 0 && !isdst) |
defaulttype = type; |
defaulttype = type; |
addtt(starttime, type); |
addtt(starttime, type); |
Line 2844 error(_("can't determine time zone abbre |
|
Line 2890 error(_("can't determine time zone abbre |
|
*/ |
*/ |
if (useuntil) { |
if (useuntil) { |
startttisstd = zp->z_untilrule.r_todisstd; |
startttisstd = zp->z_untilrule.r_todisstd; |
startttisgmt = zp->z_untilrule.r_todisgmt; |
startttisut = zp->z_untilrule.r_todisut; |
starttime = zp->z_untiltime; |
starttime = zp->z_untiltime; |
if (!startttisstd) |
if (!startttisstd) |
starttime = tadd(starttime, -stdoff); |
starttime = tadd(starttime, -save); |
if (!startttisgmt) |
if (!startttisut) |
starttime = tadd(starttime, -gmtoff); |
starttime = tadd(starttime, -stdoff); |
} |
} |
} |
} |
if (defaulttype < 0) |
if (defaulttype < 0) |
Line 2900 addtt(zic_t starttime, int type) |
|
Line 2946 addtt(zic_t starttime, int type) |
|
} |
} |
|
|
static int |
static int |
addtype(zic_t gmtoff, char const *abbr, bool isdst, bool ttisstd, bool ttisgmt) |
addtype(zic_t utoff, char const *abbr, bool isdst, bool ttisstd, bool ttisut) |
{ |
{ |
int i, j; |
int i, j; |
|
|
/* |
if (! (-1L - 2147483647L <= utoff && utoff <= 2147483647L)) { |
** See if there's already an entry for this zone type. |
error(_("UT offset out of range")); |
** If so, just return its index. |
exit(EXIT_FAILURE); |
*/ |
} |
for (i = 0; i < typecnt; ++i) { |
if (!want_bloat()) |
if (gmtoff == gmtoffs[i] && isdst == isdsts[i] && |
ttisstd = ttisut = false; |
strcmp(abbr, &chars[abbrinds[i]]) == 0 && |
|
ttisstd == ttisstds[i] && |
for (j = 0; j < charcnt; ++j) |
ttisgmt == ttisgmts[i]) |
if (strcmp(&chars[j], abbr) == 0) |
return i; |
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; |
} |
} |
/* |
/* |
** There isn't one; add a new one, unless there are already too |
** There isn't one; add a new one, unless there are already too |
Line 2923 addtype(zic_t gmtoff, char const *abbr, |
|
Line 2977 addtype(zic_t gmtoff, char const *abbr, |
|
error(_("too many local time types")); |
error(_("too many local time types")); |
exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
} |
} |
if (! (-1L - 2147483647L <= gmtoff && gmtoff <= 2147483647L)) { |
i = typecnt++; |
error(_("UT offset out of range")); |
utoffs[i] = utoff; |
exit(EXIT_FAILURE); |
|
} |
|
gmtoffs[i] = gmtoff; |
|
isdsts[i] = isdst; |
isdsts[i] = isdst; |
ttisstds[i] = ttisstd; |
ttisstds[i] = ttisstd; |
ttisgmts[i] = ttisgmt; |
ttisuts[i] = ttisut; |
|
desigidx[i] = j; |
for (j = 0; j < charcnt; ++j) |
|
if (strcmp(&chars[j], abbr) == 0) |
|
break; |
|
if (j == charcnt) |
|
newabbr(abbr); |
|
abbrinds[i] = j; |
|
++typecnt; |
|
return i; |
return i; |
} |
} |
|
|
Line 3159 byword(const char *word, const struct lo |
|
Line 3203 byword(const char *word, const struct lo |
|
else return NULL; /* multiple inexact matches */ |
else return NULL; /* multiple inexact matches */ |
} |
} |
|
|
/* Warn about any backward-compatibility issue with pre-2017c zic. */ |
if (foundlp && noise) { |
if (foundlp) { |
/* Warn about any backward-compatibility issue with pre-2017c zic. */ |
bool pre_2017c_match = false; |
bool pre_2017c_match = false; |
for (lp = table; lp->l_word; lp++) |
for (lp = table; lp->l_word; lp++) |
if (itsabbr(word, lp->l_word)) { |
if (itsabbr(word, lp->l_word)) { |