mirror of
https://sourceware.org/git/glibc.git
synced 2025-08-08 17:42:12 +03:00
.
This commit is contained in:
705
timezone/zic.c
705
timezone/zic.c
@@ -1,18 +1,15 @@
|
||||
static char elsieid[] = "@(#)zic.c 7.128";
|
||||
|
||||
/*
|
||||
** This file is in the public domain, so clarified as of
|
||||
** 2006-07-17 by Arthur David Olson.
|
||||
** Regardless of the type of time_t, we do our work using this type.
|
||||
*/
|
||||
|
||||
static char elsieid[] = "@(#)zic.c 8.7";
|
||||
typedef int zic_t;
|
||||
|
||||
#include "private.h"
|
||||
#include "locale.h"
|
||||
#include "tzfile.h"
|
||||
|
||||
#define ZIC_VERSION '2'
|
||||
|
||||
typedef int_fast64_t zic_t;
|
||||
|
||||
#ifndef ZIC_MAX_ABBR_LEN_WO_WARN
|
||||
#define ZIC_MAX_ABBR_LEN_WO_WARN 6
|
||||
#endif /* !defined ZIC_MAX_ABBR_LEN_WO_WARN */
|
||||
@@ -39,11 +36,6 @@ typedef int_fast64_t zic_t;
|
||||
#define isascii(x) 1
|
||||
#endif
|
||||
|
||||
#define OFFSET_STRLEN_MAXIMUM (7 + INT_STRLEN_MAXIMUM(long))
|
||||
#define RULE_STRLEN_MAXIMUM 8 /* "Mdd.dd.d" */
|
||||
|
||||
#define end(cp) (strchr((cp), '\0'))
|
||||
|
||||
struct rule {
|
||||
const char * r_filename;
|
||||
int r_linenum;
|
||||
@@ -52,8 +44,6 @@ struct rule {
|
||||
int r_loyear; /* for example, 1986 */
|
||||
int r_hiyear; /* for example, 1986 */
|
||||
const char * r_yrtype;
|
||||
int r_lowasnum;
|
||||
int r_hiwasnum;
|
||||
|
||||
int r_month; /* 0..11 */
|
||||
|
||||
@@ -113,10 +103,9 @@ static void adjleap P((void));
|
||||
static void associate P((void));
|
||||
static int ciequal P((const char * ap, const char * bp));
|
||||
static void convert P((long val, char * buf));
|
||||
static void convert64 P((zic_t val, char * buf));
|
||||
static void dolink P((const char * fromfile, const char * tofile));
|
||||
static void doabbr P((char * abbr, const char * format,
|
||||
const char * letters, int isdst, int doquotes));
|
||||
const char * letters, int isdst));
|
||||
static void eat P((const char * name, int num));
|
||||
static void eats P((const char * name, int num,
|
||||
const char * rname, int rnum));
|
||||
@@ -132,7 +121,6 @@ static void inrule P((char ** fields, int nfields));
|
||||
static int inzcont P((char ** fields, int nfields));
|
||||
static int inzone P((char ** fields, int nfields));
|
||||
static int inzsub P((char ** fields, int nfields, int iscont));
|
||||
static int is32 P((zic_t x));
|
||||
static int itsabbr P((const char * abbr, const char * word));
|
||||
static int itsdir P((const char * name));
|
||||
static int lowerit P((int c));
|
||||
@@ -142,22 +130,16 @@ static void newabbr P((const char * abbr));
|
||||
static long oadd P((long t1, long t2));
|
||||
static void outzone P((const struct zone * zp, int ntzones));
|
||||
static void puttzcode P((long code, FILE * fp));
|
||||
static void puttzcode64 P((zic_t code, FILE * fp));
|
||||
static int rcomp P((const void * leftp, const void * rightp));
|
||||
static zic_t rpytime P((const struct rule * rp, int wantedy));
|
||||
static void rulesub P((struct rule * rp,
|
||||
const char * loyearp, const char * hiyearp,
|
||||
const char * typep, const char * monthp,
|
||||
const char * dayp, const char * timep));
|
||||
static int stringoffset P((char * result, long offset));
|
||||
static int stringrule P((char * result, const struct rule * rp,
|
||||
long dstoff, long gmtoff));
|
||||
static void stringzone P((char * result,
|
||||
const struct zone * zp, int ntzones));
|
||||
static void setboundaries P((void));
|
||||
static zic_t tadd P((zic_t t1, long t2));
|
||||
static void usage P((void));
|
||||
static void writezone P((const char * name, const char * string));
|
||||
static void writezone P((const char * name));
|
||||
static int yearistype P((int year, const char * type));
|
||||
|
||||
#if !HAVE_STRERROR
|
||||
@@ -168,16 +150,13 @@ static int charcnt;
|
||||
static int errors;
|
||||
static const char * filename;
|
||||
static int leapcnt;
|
||||
static int leapseen;
|
||||
static int leapminyear;
|
||||
static int leapmaxyear;
|
||||
static int linenum;
|
||||
static int max_abbrvar_len;
|
||||
static int max_format_len;
|
||||
static zic_t max_time;
|
||||
static int max_year;
|
||||
static int max_year_representable;
|
||||
static zic_t min_time;
|
||||
static int min_year;
|
||||
static int min_year_representable;
|
||||
static int noise;
|
||||
static const char * rfilename;
|
||||
static int rlinenum;
|
||||
@@ -474,7 +453,7 @@ static void
|
||||
usage P((void))
|
||||
{
|
||||
(void) fprintf(stderr, _("%s: usage is %s \
|
||||
[ --version ] [ -v ] [ -l localtime ] [ -p posixrules ] \\\n\
|
||||
[ --version ] [ -s ] [ -v ] [ -l localtime ] [ -p posixrules ] \\\n\
|
||||
\t[ -d directory ] [ -L leapseconds ] [ -y yearistype ] [ filename ... ]\n"),
|
||||
progname, progname);
|
||||
exit(EXIT_FAILURE);
|
||||
@@ -485,6 +464,7 @@ static const char * lcltime;
|
||||
static const char * directory;
|
||||
static const char * leapsec;
|
||||
static const char * yitcommand;
|
||||
static int sflag = FALSE;
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
@@ -506,11 +486,6 @@ char * argv[];
|
||||
(void) textdomain(TZ_DOMAIN);
|
||||
#endif /* HAVE_GETTEXT */
|
||||
progname = argv[0];
|
||||
if (TYPE_BIT(zic_t) < 64) {
|
||||
(void) fprintf(stderr, "%s: %s\n", progname,
|
||||
_("wild compilation-time specification of zic_t"));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
for (i = 1; i < argc; ++i)
|
||||
if (strcmp(argv[i], "--version") == 0) {
|
||||
(void) printf("%s\n", elsieid);
|
||||
@@ -574,7 +549,7 @@ _("%s: More than one -L option specified\n"),
|
||||
noise = TRUE;
|
||||
break;
|
||||
case 's':
|
||||
(void) printf("%s: -s ignored\n", progname);
|
||||
sflag = TRUE;
|
||||
break;
|
||||
}
|
||||
if (optind == argc - 1 && strcmp(argv[optind], "=") == 0)
|
||||
@@ -696,17 +671,54 @@ warning(_("hard link failed, symbolic link used"));
|
||||
ifree(toname);
|
||||
}
|
||||
|
||||
#define TIME_T_BITS_IN_FILE 64
|
||||
#ifndef INT_MAX
|
||||
#define INT_MAX ((int) (((unsigned)~0)>>1))
|
||||
#endif /* !defined INT_MAX */
|
||||
|
||||
#ifndef INT_MIN
|
||||
#define INT_MIN ((int) ~(((unsigned)~0)>>1))
|
||||
#endif /* !defined INT_MIN */
|
||||
|
||||
/*
|
||||
** The tz file format currently allows at most 32-bit quantities.
|
||||
** This restriction should be removed before signed 32-bit values
|
||||
** wrap around in 2038, but unfortunately this will require a
|
||||
** change to the tz file format.
|
||||
*/
|
||||
|
||||
#define MAX_BITS_IN_FILE 32
|
||||
#define TIME_T_BITS_IN_FILE ((TYPE_BIT(zic_t) < MAX_BITS_IN_FILE) ? \
|
||||
TYPE_BIT(zic_t) : MAX_BITS_IN_FILE)
|
||||
|
||||
static void
|
||||
setboundaries P((void))
|
||||
{
|
||||
register int i;
|
||||
|
||||
min_time = -1;
|
||||
for (i = 0; i < TIME_T_BITS_IN_FILE - 1; ++i)
|
||||
min_time *= 2;
|
||||
max_time = -(min_time + 1);
|
||||
if (TYPE_SIGNED(zic_t)) {
|
||||
min_time = -1;
|
||||
for (i = 0; i < TIME_T_BITS_IN_FILE - 1; ++i)
|
||||
min_time *= 2;
|
||||
max_time = -(min_time + 1);
|
||||
if (sflag)
|
||||
min_time = 0;
|
||||
} else {
|
||||
min_time = 0;
|
||||
max_time = 2 - sflag;
|
||||
for (i = 0; i < TIME_T_BITS_IN_FILE - 1; ++i)
|
||||
max_time *= 2;
|
||||
--max_time;
|
||||
}
|
||||
{
|
||||
time_t t;
|
||||
|
||||
t = (time_t) min_time;
|
||||
min_year = TM_YEAR_BASE + gmtime(&t)->tm_year;
|
||||
t = (time_t) max_time;
|
||||
max_year = TM_YEAR_BASE + gmtime(&t)->tm_year;
|
||||
}
|
||||
min_year_representable = min_year;
|
||||
max_year_representable = max_year;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -981,8 +993,6 @@ const int nfields;
|
||||
fields[RF_MONTH], fields[RF_DAY], fields[RF_TOD]);
|
||||
r.r_name = ecpyalloc(fields[RF_NAME]);
|
||||
r.r_abbrvar = ecpyalloc(fields[RF_ABBRVAR]);
|
||||
if (max_abbrvar_len < strlen(r.r_abbrvar))
|
||||
max_abbrvar_len = strlen(r.r_abbrvar);
|
||||
rules = (struct rule *) (void *) erealloc((char *) rules,
|
||||
(int) ((nrules + 1) * sizeof *rules));
|
||||
rules[nrules++] = r;
|
||||
@@ -1088,8 +1098,6 @@ const int iscont;
|
||||
}
|
||||
z.z_rule = ecpyalloc(fields[i_rule]);
|
||||
z.z_format = ecpyalloc(fields[i_format]);
|
||||
if (max_format_len < strlen(z.z_format))
|
||||
max_format_len = strlen(z.z_format);
|
||||
hasuntil = nfields > i_untilyear;
|
||||
if (hasuntil) {
|
||||
z.z_untilrule.r_filename = filename;
|
||||
@@ -1151,11 +1159,6 @@ const int nfields;
|
||||
error(_("invalid leaping year"));
|
||||
return;
|
||||
}
|
||||
if (!leapseen || leapmaxyear < year)
|
||||
leapmaxyear = year;
|
||||
if (!leapseen || leapminyear > year)
|
||||
leapminyear = year;
|
||||
leapseen = TRUE;
|
||||
j = EPOCH_YEAR;
|
||||
while (j != year) {
|
||||
if (year > j) {
|
||||
@@ -1310,8 +1313,7 @@ const char * const timep;
|
||||
*/
|
||||
cp = loyearp;
|
||||
lp = byword(cp, begin_years);
|
||||
rp->r_lowasnum = lp == NULL;
|
||||
if (!rp->r_lowasnum) switch ((int) lp->l_value) {
|
||||
if (lp != NULL) switch ((int) lp->l_value) {
|
||||
case YR_MINIMUM:
|
||||
rp->r_loyear = INT_MIN;
|
||||
break;
|
||||
@@ -1326,11 +1328,14 @@ const char * const timep;
|
||||
} else if (sscanf(cp, scheck(cp, "%d"), &rp->r_loyear) != 1) {
|
||||
error(_("invalid starting year"));
|
||||
return;
|
||||
} else if (noise) {
|
||||
if (rp->r_loyear < min_year_representable)
|
||||
warning(_("starting year too low to be represented"));
|
||||
else if (rp->r_loyear > max_year_representable)
|
||||
warning(_("starting year too high to be represented"));
|
||||
}
|
||||
cp = hiyearp;
|
||||
lp = byword(cp, end_years);
|
||||
rp->r_hiwasnum = lp == NULL;
|
||||
if (!rp->r_hiwasnum) switch ((int) lp->l_value) {
|
||||
if ((lp = byword(cp, end_years)) != NULL) switch ((int) lp->l_value) {
|
||||
case YR_MINIMUM:
|
||||
rp->r_hiyear = INT_MIN;
|
||||
break;
|
||||
@@ -1348,6 +1353,11 @@ const char * const timep;
|
||||
} else if (sscanf(cp, scheck(cp, "%d"), &rp->r_hiyear) != 1) {
|
||||
error(_("invalid ending year"));
|
||||
return;
|
||||
} else if (noise) {
|
||||
if (rp->r_loyear < min_year_representable)
|
||||
warning(_("ending year too low to be represented"));
|
||||
else if (rp->r_loyear > max_year_representable)
|
||||
warning(_("ending year too high to be represented"));
|
||||
}
|
||||
if (rp->r_loyear > rp->r_hiyear) {
|
||||
error(_("starting year greater than ending year"));
|
||||
@@ -1362,6 +1372,8 @@ const char * const timep;
|
||||
}
|
||||
rp->r_yrtype = ecpyalloc(typep);
|
||||
}
|
||||
if (rp->r_loyear < min_year && rp->r_loyear > 0)
|
||||
min_year = rp->r_loyear;
|
||||
/*
|
||||
** Day work.
|
||||
** Accept things such as:
|
||||
@@ -1415,24 +1427,12 @@ const long val;
|
||||
char * const buf;
|
||||
{
|
||||
register int i;
|
||||
register int shift;
|
||||
register long shift;
|
||||
|
||||
for (i = 0, shift = 24; i < 4; ++i, shift -= 8)
|
||||
buf[i] = val >> shift;
|
||||
}
|
||||
|
||||
static void
|
||||
convert64(val, buf)
|
||||
const zic_t val;
|
||||
char * const buf;
|
||||
{
|
||||
register int i;
|
||||
register int shift;
|
||||
|
||||
for (i = 0, shift = 56; i < 8; ++i, shift -= 8)
|
||||
buf[i] = val >> shift;
|
||||
}
|
||||
|
||||
static void
|
||||
puttzcode(val, fp)
|
||||
const long val;
|
||||
@@ -1444,50 +1444,28 @@ FILE * const fp;
|
||||
(void) fwrite((void *) buf, (size_t) sizeof buf, (size_t) 1, fp);
|
||||
}
|
||||
|
||||
static void
|
||||
puttzcode64(val, fp)
|
||||
const zic_t val;
|
||||
FILE * const fp;
|
||||
{
|
||||
char buf[8];
|
||||
|
||||
convert64(val, buf);
|
||||
(void) fwrite((void *) buf, (size_t) sizeof buf, (size_t) 1, fp);
|
||||
}
|
||||
|
||||
static int
|
||||
atcomp(avp, bvp)
|
||||
const void * avp;
|
||||
const void * bvp;
|
||||
void * avp;
|
||||
void * bvp;
|
||||
{
|
||||
const zic_t a = ((const struct attype *) avp)->at;
|
||||
const zic_t b = ((const struct attype *) bvp)->at;
|
||||
|
||||
return (a < b) ? -1 : (a > b);
|
||||
}
|
||||
|
||||
static int
|
||||
is32(x)
|
||||
const zic_t x;
|
||||
{
|
||||
return INT32_MIN <= x && x <= INT32_MAX;
|
||||
if (((struct attype *) avp)->at < ((struct attype *) bvp)->at)
|
||||
return -1;
|
||||
else if (((struct attype *) avp)->at > ((struct attype *) bvp)->at)
|
||||
return 1;
|
||||
else return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
writezone(name, string)
|
||||
writezone(name)
|
||||
const char * const name;
|
||||
const char * const string;
|
||||
{
|
||||
register FILE * fp;
|
||||
register int i, j;
|
||||
register int leapcnt32, leapi32;
|
||||
register int timecnt32, timei32;
|
||||
register int pass;
|
||||
static char * fullname;
|
||||
static const struct tzhead tzh0;
|
||||
static struct tzhead tzh;
|
||||
zic_t ats[TZ_MAX_TIMES];
|
||||
unsigned char types[TZ_MAX_TIMES];
|
||||
register FILE * fp;
|
||||
register int i, j;
|
||||
static char * fullname;
|
||||
static struct tzhead tzh;
|
||||
zic_t ats[TZ_MAX_TIMES];
|
||||
unsigned char types[TZ_MAX_TIMES];
|
||||
|
||||
/*
|
||||
** Sort.
|
||||
@@ -1531,36 +1509,6 @@ const char * const string;
|
||||
ats[i] = attypes[i].at;
|
||||
types[i] = attypes[i].type;
|
||||
}
|
||||
/*
|
||||
** Correct for leap seconds.
|
||||
*/
|
||||
for (i = 0; i < timecnt; ++i) {
|
||||
j = leapcnt;
|
||||
while (--j >= 0)
|
||||
if (ats[i] > trans[j] - corr[j]) {
|
||||
ats[i] = tadd(ats[i], corr[j]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
** Figure out 32-bit-limited starts and counts.
|
||||
*/
|
||||
timecnt32 = timecnt;
|
||||
timei32 = 0;
|
||||
leapcnt32 = leapcnt;
|
||||
leapi32 = 0;
|
||||
while (timecnt32 > 0 && !is32(ats[timecnt32 - 1]))
|
||||
--timecnt32;
|
||||
while (timecnt32 > 0 && !is32(ats[timei32])) {
|
||||
--timecnt32;
|
||||
++timei32;
|
||||
}
|
||||
while (leapcnt32 > 0 && !is32(trans[leapcnt32 - 1]))
|
||||
--leapcnt32;
|
||||
while (leapcnt32 > 0 && !is32(trans[leapi32])) {
|
||||
--leapcnt32;
|
||||
++leapi32;
|
||||
}
|
||||
fullname = erealloc(fullname,
|
||||
(int) (strlen(directory) + 1 + strlen(name) + 1));
|
||||
(void) sprintf(fullname, "%s/%s", directory, name);
|
||||
@@ -1585,150 +1533,67 @@ const char * const string;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
for (pass = 1; pass <= 2; ++pass) {
|
||||
register int thistimei, thistimecnt;
|
||||
register int thisleapi, thisleapcnt;
|
||||
register int thistimelim, thisleaplim;
|
||||
int writetype[TZ_MAX_TIMES];
|
||||
int typemap[TZ_MAX_TYPES];
|
||||
register int thistypecnt;
|
||||
char thischars[TZ_MAX_CHARS];
|
||||
char thischarcnt;
|
||||
int indmap[TZ_MAX_CHARS];
|
||||
|
||||
if (pass == 1) {
|
||||
thistimei = timei32;
|
||||
thistimecnt = timecnt32;
|
||||
thisleapi = leapi32;
|
||||
thisleapcnt = leapcnt32;
|
||||
} else {
|
||||
thistimei = 0;
|
||||
thistimecnt = timecnt;
|
||||
thisleapi = 0;
|
||||
thisleapcnt = leapcnt;
|
||||
}
|
||||
thistimelim = thistimei + thistimecnt;
|
||||
thisleaplim = thisleapi + thisleapcnt;
|
||||
for (i = 0; i < typecnt; ++i)
|
||||
writetype[i] = thistimecnt == timecnt;
|
||||
if (thistimecnt == 0) {
|
||||
/*
|
||||
** No transition times fall in the current
|
||||
** (32- or 64-bit) window.
|
||||
*/
|
||||
if (typecnt != 0)
|
||||
writetype[typecnt - 1] = TRUE;
|
||||
} else {
|
||||
for (i = thistimei - 1; i < thistimelim; ++i)
|
||||
if (i >= 0)
|
||||
writetype[types[i]] = TRUE;
|
||||
/*
|
||||
** For America/Godthab and Antarctica/Palmer
|
||||
*/
|
||||
if (thistimei == 0)
|
||||
writetype[0] = TRUE;
|
||||
}
|
||||
thistypecnt = 0;
|
||||
for (i = 0; i < typecnt; ++i)
|
||||
typemap[i] = writetype[i] ? thistypecnt++ : -1;
|
||||
for (i = 0; i < sizeof indmap / sizeof indmap[0]; ++i)
|
||||
indmap[i] = -1;
|
||||
thischarcnt = 0;
|
||||
for (i = 0; i < typecnt; ++i) {
|
||||
register char * thisabbr;
|
||||
|
||||
if (!writetype[i])
|
||||
continue;
|
||||
if (indmap[abbrinds[i]] >= 0)
|
||||
continue;
|
||||
thisabbr = &chars[abbrinds[i]];
|
||||
for (j = 0; j < thischarcnt; ++j)
|
||||
if (strcmp(&thischars[j], thisabbr) == 0)
|
||||
break;
|
||||
if (j == thischarcnt) {
|
||||
(void) strcpy(&thischars[(int) thischarcnt],
|
||||
thisabbr);
|
||||
thischarcnt += strlen(thisabbr) + 1;
|
||||
}
|
||||
indmap[abbrinds[i]] = j;
|
||||
}
|
||||
convert(eitol(typecnt), tzh.tzh_ttisgmtcnt);
|
||||
convert(eitol(typecnt), tzh.tzh_ttisstdcnt);
|
||||
convert(eitol(leapcnt), tzh.tzh_leapcnt);
|
||||
convert(eitol(timecnt), tzh.tzh_timecnt);
|
||||
convert(eitol(typecnt), tzh.tzh_typecnt);
|
||||
convert(eitol(charcnt), tzh.tzh_charcnt);
|
||||
(void) strncpy(tzh.tzh_magic, TZ_MAGIC, sizeof tzh.tzh_magic);
|
||||
#define DO(field) (void) fwrite((void *) tzh.field, \
|
||||
(size_t) sizeof tzh.field, (size_t) 1, fp)
|
||||
tzh = tzh0;
|
||||
(void) strncpy(tzh.tzh_magic, TZ_MAGIC, sizeof tzh.tzh_magic);
|
||||
tzh.tzh_version[0] = ZIC_VERSION;
|
||||
convert(eitol(thistypecnt), tzh.tzh_ttisgmtcnt);
|
||||
convert(eitol(thistypecnt), tzh.tzh_ttisstdcnt);
|
||||
convert(eitol(thisleapcnt), tzh.tzh_leapcnt);
|
||||
convert(eitol(thistimecnt), tzh.tzh_timecnt);
|
||||
convert(eitol(thistypecnt), tzh.tzh_typecnt);
|
||||
convert(eitol(thischarcnt), tzh.tzh_charcnt);
|
||||
DO(tzh_magic);
|
||||
DO(tzh_version);
|
||||
DO(tzh_reserved);
|
||||
DO(tzh_ttisgmtcnt);
|
||||
DO(tzh_ttisstdcnt);
|
||||
DO(tzh_leapcnt);
|
||||
DO(tzh_timecnt);
|
||||
DO(tzh_typecnt);
|
||||
DO(tzh_charcnt);
|
||||
DO(tzh_magic);
|
||||
DO(tzh_reserved);
|
||||
DO(tzh_ttisgmtcnt);
|
||||
DO(tzh_ttisstdcnt);
|
||||
DO(tzh_leapcnt);
|
||||
DO(tzh_timecnt);
|
||||
DO(tzh_typecnt);
|
||||
DO(tzh_charcnt);
|
||||
#undef DO
|
||||
for (i = thistimei; i < thistimelim; ++i)
|
||||
if (pass == 1)
|
||||
puttzcode((long) ats[i], fp);
|
||||
else puttzcode64(ats[i], fp);
|
||||
for (i = thistimei; i < thistimelim; ++i) {
|
||||
unsigned char uc;
|
||||
|
||||
uc = typemap[types[i]];
|
||||
(void) fwrite((void *) &uc,
|
||||
(size_t) sizeof uc,
|
||||
(size_t) 1,
|
||||
fp);
|
||||
}
|
||||
for (i = 0; i < typecnt; ++i)
|
||||
if (writetype[i]) {
|
||||
puttzcode(gmtoffs[i], fp);
|
||||
(void) putc(isdsts[i], fp);
|
||||
(void) putc((unsigned char) indmap[abbrinds[i]], fp);
|
||||
for (i = 0; i < timecnt; ++i) {
|
||||
j = leapcnt;
|
||||
while (--j >= 0)
|
||||
if (ats[i] >= trans[j]) {
|
||||
ats[i] = tadd(ats[i], corr[j]);
|
||||
break;
|
||||
}
|
||||
if (thischarcnt != 0)
|
||||
(void) fwrite((void *) thischars,
|
||||
(size_t) sizeof thischars[0],
|
||||
(size_t) thischarcnt, fp);
|
||||
for (i = thisleapi; i < thisleaplim; ++i) {
|
||||
register zic_t todo;
|
||||
|
||||
if (roll[i]) {
|
||||
if (timecnt == 0 || trans[i] < ats[0]) {
|
||||
j = 0;
|
||||
while (isdsts[j])
|
||||
if (++j >= typecnt) {
|
||||
j = 0;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
j = 1;
|
||||
while (j < timecnt &&
|
||||
trans[i] >= ats[j])
|
||||
++j;
|
||||
j = types[j - 1];
|
||||
}
|
||||
todo = tadd(trans[i], -gmtoffs[j]);
|
||||
} else todo = trans[i];
|
||||
if (pass == 1)
|
||||
puttzcode((long) todo, fp);
|
||||
else puttzcode64(todo, fp);
|
||||
puttzcode(corr[i], fp);
|
||||
}
|
||||
for (i = 0; i < typecnt; ++i)
|
||||
if (writetype[i])
|
||||
(void) putc(ttisstds[i], fp);
|
||||
for (i = 0; i < typecnt; ++i)
|
||||
if (writetype[i])
|
||||
(void) putc(ttisgmts[i], fp);
|
||||
puttzcode((long) ats[i], fp);
|
||||
}
|
||||
(void) fprintf(fp, "\n%s\n", string);
|
||||
if (timecnt > 0)
|
||||
(void) fwrite((void *) types, (size_t) sizeof types[0],
|
||||
(size_t) timecnt, fp);
|
||||
for (i = 0; i < typecnt; ++i) {
|
||||
puttzcode((long) gmtoffs[i], fp);
|
||||
(void) putc(isdsts[i], fp);
|
||||
(void) putc(abbrinds[i], fp);
|
||||
}
|
||||
if (charcnt != 0)
|
||||
(void) fwrite((void *) chars, (size_t) sizeof chars[0],
|
||||
(size_t) charcnt, fp);
|
||||
for (i = 0; i < leapcnt; ++i) {
|
||||
if (roll[i]) {
|
||||
if (timecnt == 0 || trans[i] < ats[0]) {
|
||||
j = 0;
|
||||
while (isdsts[j])
|
||||
if (++j >= typecnt) {
|
||||
j = 0;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
j = 1;
|
||||
while (j < timecnt && trans[i] >= ats[j])
|
||||
++j;
|
||||
j = types[j - 1];
|
||||
}
|
||||
puttzcode((long) tadd(trans[i], -gmtoffs[j]), fp);
|
||||
} else puttzcode((long) trans[i], fp);
|
||||
puttzcode((long) corr[i], fp);
|
||||
}
|
||||
for (i = 0; i < typecnt; ++i)
|
||||
(void) putc(ttisstds[i], fp);
|
||||
for (i = 0; i < typecnt; ++i)
|
||||
(void) putc(ttisgmts[i], fp);
|
||||
if (ferror(fp) || fclose(fp)) {
|
||||
(void) fprintf(stderr, _("%s: Error writing %s\n"),
|
||||
progname, fullname);
|
||||
@@ -1737,223 +1602,21 @@ const char * const string;
|
||||
}
|
||||
|
||||
static void
|
||||
doabbr(abbr, format, letters, isdst, doquotes)
|
||||
doabbr(abbr, format, letters, isdst)
|
||||
char * const abbr;
|
||||
const char * const format;
|
||||
const char * const letters;
|
||||
const int isdst;
|
||||
const int doquotes;
|
||||
{
|
||||
register char * cp;
|
||||
register char * slashp;
|
||||
register int len;
|
||||
|
||||
slashp = strchr(format, '/');
|
||||
if (slashp == NULL) {
|
||||
if (strchr(format, '/') == NULL) {
|
||||
if (letters == NULL)
|
||||
(void) strcpy(abbr, format);
|
||||
else (void) sprintf(abbr, format, letters);
|
||||
} else if (isdst) {
|
||||
(void) strcpy(abbr, slashp + 1);
|
||||
} else {
|
||||
if (slashp > format)
|
||||
(void) strncpy(abbr, format,
|
||||
(unsigned) (slashp - format));
|
||||
abbr[slashp - format] = '\0';
|
||||
}
|
||||
if (!doquotes)
|
||||
return;
|
||||
for (cp = abbr; *cp != '\0'; ++cp)
|
||||
if (strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ", *cp) == NULL &&
|
||||
strchr("abcdefghijklmnopqrstuvwxyz", *cp) == NULL)
|
||||
break;
|
||||
len = strlen(abbr);
|
||||
if (len > 0 && *cp == '\0')
|
||||
return;
|
||||
abbr[len + 2] = '\0';
|
||||
abbr[len + 1] = '>';
|
||||
for ( ; len > 0; --len)
|
||||
abbr[len] = abbr[len - 1];
|
||||
abbr[0] = '<';
|
||||
}
|
||||
|
||||
static void
|
||||
updateminmax(x)
|
||||
const int x;
|
||||
{
|
||||
if (min_year > x)
|
||||
min_year = x;
|
||||
if (max_year < x)
|
||||
max_year = x;
|
||||
}
|
||||
|
||||
static int
|
||||
stringoffset(result, offset)
|
||||
char * result;
|
||||
long offset;
|
||||
{
|
||||
register int hours;
|
||||
register int minutes;
|
||||
register int seconds;
|
||||
|
||||
result[0] = '\0';
|
||||
if (offset < 0) {
|
||||
(void) strcpy(result, "-");
|
||||
offset = -offset;
|
||||
}
|
||||
seconds = offset % SECSPERMIN;
|
||||
offset /= SECSPERMIN;
|
||||
minutes = offset % MINSPERHOUR;
|
||||
offset /= MINSPERHOUR;
|
||||
hours = offset;
|
||||
if (hours >= HOURSPERDAY) {
|
||||
result[0] = '\0';
|
||||
return -1;
|
||||
}
|
||||
(void) sprintf(end(result), "%d", hours);
|
||||
if (minutes != 0 || seconds != 0) {
|
||||
(void) sprintf(end(result), ":%02d", minutes);
|
||||
if (seconds != 0)
|
||||
(void) sprintf(end(result), ":%02d", seconds);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
stringrule(result, rp, dstoff, gmtoff)
|
||||
char * result;
|
||||
const struct rule * const rp;
|
||||
const long dstoff;
|
||||
const long gmtoff;
|
||||
{
|
||||
register long tod;
|
||||
|
||||
result = end(result);
|
||||
if (rp->r_dycode == DC_DOM) {
|
||||
register int month, total;
|
||||
|
||||
if (rp->r_dayofmonth == 29 && rp->r_month == TM_FEBRUARY)
|
||||
return -1;
|
||||
total = 0;
|
||||
for (month = 0; month < rp->r_month; ++month)
|
||||
total += len_months[0][month];
|
||||
(void) sprintf(result, "J%d", total + rp->r_dayofmonth);
|
||||
} else {
|
||||
register int week;
|
||||
|
||||
if (rp->r_dycode == DC_DOWGEQ) {
|
||||
week = 1 + rp->r_dayofmonth / DAYSPERWEEK;
|
||||
if ((week - 1) * DAYSPERWEEK + 1 != rp->r_dayofmonth)
|
||||
return -1;
|
||||
} else if (rp->r_dycode == DC_DOWLEQ) {
|
||||
if (rp->r_dayofmonth == len_months[1][rp->r_month])
|
||||
week = 5;
|
||||
else {
|
||||
week = 1 + rp->r_dayofmonth / DAYSPERWEEK;
|
||||
if (week * DAYSPERWEEK - 1 != rp->r_dayofmonth)
|
||||
return -1;
|
||||
}
|
||||
} else return -1; /* "cannot happen" */
|
||||
(void) sprintf(result, "M%d.%d.%d",
|
||||
rp->r_month + 1, week, rp->r_wday);
|
||||
}
|
||||
tod = rp->r_tod;
|
||||
if (rp->r_todisgmt)
|
||||
tod += gmtoff;
|
||||
if (rp->r_todisstd && rp->r_stdoff == 0)
|
||||
tod += dstoff;
|
||||
if (tod < 0) {
|
||||
result[0] = '\0';
|
||||
return -1;
|
||||
}
|
||||
if (tod != 2 * SECSPERMIN * MINSPERHOUR) {
|
||||
(void) strcat(result, "/");
|
||||
if (stringoffset(end(result), tod) != 0)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
stringzone(result, zpfirst, zonecount)
|
||||
char * result;
|
||||
const struct zone * const zpfirst;
|
||||
const int zonecount;
|
||||
{
|
||||
register const struct zone * zp;
|
||||
register struct rule * rp;
|
||||
register struct rule * stdrp;
|
||||
register struct rule * dstrp;
|
||||
register int i;
|
||||
register const char * abbrvar;
|
||||
|
||||
result[0] = '\0';
|
||||
zp = zpfirst + zonecount - 1;
|
||||
stdrp = dstrp = NULL;
|
||||
for (i = 0; i < zp->z_nrules; ++i) {
|
||||
rp = &zp->z_rules[i];
|
||||
if (rp->r_hiwasnum || rp->r_hiyear != INT_MAX)
|
||||
continue;
|
||||
if (rp->r_yrtype != NULL)
|
||||
continue;
|
||||
if (rp->r_stdoff == 0) {
|
||||
if (stdrp == NULL)
|
||||
stdrp = rp;
|
||||
else return;
|
||||
} else {
|
||||
if (dstrp == NULL)
|
||||
dstrp = rp;
|
||||
else return;
|
||||
}
|
||||
}
|
||||
if (stdrp == NULL && dstrp == NULL) {
|
||||
/*
|
||||
** There are no rules running through "max".
|
||||
** Let's find the latest rule.
|
||||
*/
|
||||
for (i = 0; i < zp->z_nrules; ++i) {
|
||||
rp = &zp->z_rules[i];
|
||||
if (stdrp == NULL || rp->r_hiyear > stdrp->r_hiyear ||
|
||||
(rp->r_hiyear == stdrp->r_hiyear &&
|
||||
rp->r_month > stdrp->r_month))
|
||||
stdrp = rp;
|
||||
}
|
||||
if (stdrp != NULL && stdrp->r_stdoff != 0)
|
||||
return; /* We end up in DST (a POSIX no-no). */
|
||||
/*
|
||||
** 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;
|
||||
}
|
||||
if (stdrp == NULL && zp->z_nrules != 0)
|
||||
return;
|
||||
abbrvar = (stdrp == NULL) ? "" : stdrp->r_abbrvar;
|
||||
doabbr(result, zp->z_format, abbrvar, FALSE, TRUE);
|
||||
if (stringoffset(end(result), -zp->z_gmtoff) != 0) {
|
||||
result[0] = '\0';
|
||||
return;
|
||||
}
|
||||
if (dstrp == NULL)
|
||||
return;
|
||||
doabbr(end(result), zp->z_format, dstrp->r_abbrvar, TRUE, TRUE);
|
||||
if (dstrp->r_stdoff != SECSPERMIN * MINSPERHOUR)
|
||||
if (stringoffset(end(result),
|
||||
-(zp->z_gmtoff + dstrp->r_stdoff)) != 0) {
|
||||
result[0] = '\0';
|
||||
return;
|
||||
}
|
||||
(void) strcat(result, ",");
|
||||
if (stringrule(result, dstrp, dstrp->r_stdoff, zp->z_gmtoff) != 0) {
|
||||
result[0] = '\0';
|
||||
return;
|
||||
}
|
||||
(void) strcat(result, ",");
|
||||
if (stringrule(result, stdrp, dstrp->r_stdoff, zp->z_gmtoff) != 0) {
|
||||
result[0] = '\0';
|
||||
return;
|
||||
} else if (isdst)
|
||||
(void) strcpy(abbr, strchr(format, '/') + 1);
|
||||
else {
|
||||
(void) strcpy(abbr, format);
|
||||
*strchr(abbr, '/') = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1974,17 +1637,8 @@ const int zonecount;
|
||||
register int startttisstd;
|
||||
register int startttisgmt;
|
||||
register int type;
|
||||
register char * startbuf;
|
||||
register char * ab;
|
||||
register char * envvar;
|
||||
register int max_abbr_len;
|
||||
register int max_envvar_len;
|
||||
char startbuf[BUFSIZ];
|
||||
|
||||
max_abbr_len = 2 + max_format_len + max_abbrvar_len;
|
||||
max_envvar_len = 2 * max_abbr_len + 5 * 9;
|
||||
startbuf = emalloc(max_abbr_len + 1);
|
||||
ab = emalloc(max_abbr_len + 1);
|
||||
envvar = emalloc(max_envvar_len + 1);
|
||||
INITIALIZE(untiltime);
|
||||
INITIALIZE(starttime);
|
||||
/*
|
||||
@@ -1999,48 +1653,6 @@ const int zonecount;
|
||||
*/
|
||||
startttisstd = FALSE;
|
||||
startttisgmt = FALSE;
|
||||
min_year = max_year = EPOCH_YEAR;
|
||||
if (leapseen) {
|
||||
updateminmax(leapminyear);
|
||||
updateminmax(leapmaxyear);
|
||||
}
|
||||
for (i = 0; i < zonecount; ++i) {
|
||||
zp = &zpfirst[i];
|
||||
updateminmax(zp->z_untilrule.r_loyear);
|
||||
for (j = 0; j < zp->z_nrules; ++j) {
|
||||
rp = &zp->z_rules[j];
|
||||
if (rp->r_lowasnum)
|
||||
updateminmax(rp->r_loyear);
|
||||
if (rp->r_hiwasnum)
|
||||
updateminmax(rp->r_hiyear);
|
||||
}
|
||||
}
|
||||
/*
|
||||
** Generate lots of data if a rule can't cover all future times.
|
||||
*/
|
||||
stringzone(envvar, zpfirst, zonecount);
|
||||
if (noise && envvar[0] == '\0') {
|
||||
register char * wp;
|
||||
|
||||
wp = ecpyalloc(_("no POSIX environment variable for zone"));
|
||||
wp = ecatalloc(wp, " ");
|
||||
wp = ecatalloc(wp, zpfirst->z_name);
|
||||
warning(wp);
|
||||
ifree(wp);
|
||||
}
|
||||
if (envvar[0] == '\0') {
|
||||
if (min_year >= INT_MIN + YEARSPERREPEAT)
|
||||
min_year -= YEARSPERREPEAT;
|
||||
else min_year = INT_MIN;
|
||||
if (max_year <= INT_MAX - YEARSPERREPEAT)
|
||||
max_year += YEARSPERREPEAT;
|
||||
else max_year = INT_MAX;
|
||||
}
|
||||
/*
|
||||
** For the benefit of older systems, generate data through 2037.
|
||||
*/
|
||||
if (max_year < 2037)
|
||||
max_year = 2037;
|
||||
for (i = 0; i < zonecount; ++i) {
|
||||
/*
|
||||
** A guess that may well be corrected later.
|
||||
@@ -2058,7 +1670,7 @@ wp = ecpyalloc(_("no POSIX environment variable for zone"));
|
||||
if (zp->z_nrules == 0) {
|
||||
stdoff = zp->z_stdoff;
|
||||
doabbr(startbuf, zp->z_format,
|
||||
(char *) NULL, stdoff != 0, FALSE);
|
||||
(char *) NULL, stdoff != 0);
|
||||
type = addtype(oadd(zp->z_gmtoff, stdoff),
|
||||
startbuf, stdoff != 0, startttisstd,
|
||||
startttisgmt);
|
||||
@@ -2088,6 +1700,7 @@ wp = ecpyalloc(_("no POSIX environment variable for zone"));
|
||||
register int k;
|
||||
register zic_t jtime, ktime;
|
||||
register long offset;
|
||||
char buf[BUFSIZ];
|
||||
|
||||
INITIALIZE(ktime);
|
||||
if (useuntil) {
|
||||
@@ -2143,27 +1756,24 @@ wp = ecpyalloc(_("no POSIX environment variable for zone"));
|
||||
stdoff);
|
||||
doabbr(startbuf, zp->z_format,
|
||||
rp->r_abbrvar,
|
||||
rp->r_stdoff != 0,
|
||||
FALSE);
|
||||
rp->r_stdoff != 0);
|
||||
continue;
|
||||
}
|
||||
if (*startbuf == '\0' &&
|
||||
startoff == oadd(zp->z_gmtoff,
|
||||
stdoff)) {
|
||||
stdoff))
|
||||
doabbr(startbuf,
|
||||
zp->z_format,
|
||||
rp->r_abbrvar,
|
||||
rp->r_stdoff !=
|
||||
0,
|
||||
FALSE);
|
||||
}
|
||||
0);
|
||||
}
|
||||
eats(zp->z_filename, zp->z_linenum,
|
||||
rp->r_filename, rp->r_linenum);
|
||||
doabbr(ab, zp->z_format, rp->r_abbrvar,
|
||||
rp->r_stdoff != 0, FALSE);
|
||||
doabbr(buf, zp->z_format, rp->r_abbrvar,
|
||||
rp->r_stdoff != 0);
|
||||
offset = oadd(zp->z_gmtoff, rp->r_stdoff);
|
||||
type = addtype(offset, ab, rp->r_stdoff != 0,
|
||||
type = addtype(offset, buf, rp->r_stdoff != 0,
|
||||
rp->r_todisstd, rp->r_todisgmt);
|
||||
addtt(ktime, type);
|
||||
}
|
||||
@@ -2196,10 +1806,7 @@ error(_("can't determine time zone abbreviation to use just after until time"));
|
||||
starttime = tadd(starttime, -gmtoff);
|
||||
}
|
||||
}
|
||||
writezone(zpfirst->z_name, envvar);
|
||||
ifree(startbuf);
|
||||
ifree(ab);
|
||||
ifree(envvar);
|
||||
writezone(zpfirst->z_name);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2578,6 +2185,8 @@ register const int wantedy;
|
||||
will not work with pre-2004 versions of zic"));
|
||||
}
|
||||
}
|
||||
if (dayoff < 0 && !TYPE_SIGNED(zic_t))
|
||||
return min_time;
|
||||
if (dayoff < min_time / SECSPERDAY)
|
||||
return min_time;
|
||||
if (dayoff > max_time / SECSPERDAY)
|
||||
|
Reference in New Issue
Block a user