Below are diffs to the time zone code to cope with 64-bit time_t systems;
these reflect suggestions I've received to date. Absent negative feedback,
I'll update the ftp versions on May 2, 2005.
--ado
diff -c -r tz/localtime.c tzexp/localtime.c
*** tz/localtime.c Thu Apr 21 15:04:15 2005
--- tzexp/localtime.c Mon Apr 4 15:39:41 2005
***************
*** 5,11 ****
#ifndef lint
#ifndef NOID
! static char elsieid[] = "@(#)localtime.c 7.91";
#endif /* !defined NOID */
#endif /* !defined lint */
--- 5,11 ----
#ifndef lint
#ifndef NOID
! static char elsieid[] = "@(#)localtime.c 7.92";
#endif /* !defined NOID */
#endif /* !defined lint */
***************
*** 98,103 ****
--- 98,105 ----
int timecnt;
int typecnt;
int charcnt;
+ int goback;
+ int goahead;
time_t ats[TZ_MAX_TIMES];
unsigned char types[TZ_MAX_TIMES];
struct ttinfo ttis[TZ_MAX_TYPES];
***************
*** 123,128 ****
--- 125,131 ----
*/
static long detzcode P((const char * codep));
+ static time_t detzcode64 P((const char * codep));
static const char * getzname P((const char * strp));
static const char * getnum P((const char * strp, int * nump, int min,
int max));
***************
*** 221,226 ****
--- 224,242 ----
return result;
}
+ static time_t
+ detzcode64(codep)
+ const char * const codep;
+ {
+ register signed64_t result;
+ register int i;
+
+ result = (codep[0] & 0x80) ? ~0L : 0L;
+ for (i = 0; i < 8; ++i)
+ result = (result << 8) | (codep[i] & 0xff);
+ return (time_t) result;
+ }
+
static void
settzname P((void))
{
***************
*** 276,284 ****
register const char * name;
register struct state * const sp;
{
! register const char * p;
! register int i;
! register int fid;
if (name == NULL && (name = TZDEFAULT) == NULL)
return -1;
--- 292,308 ----
register const char * name;
register struct state * const sp;
{
! register const char * p;
! register int i;
! register int fid;
! register int stored;
! register int nread;
! union {
! struct tzhead tzhead;
! char buf[2 * sizeof(struct tzhead) +
! 2 * sizeof *sp +
! 4 * TZ_MAX_TIMES];
! } u;
if (name == NULL && (name = TZDEFAULT) == NULL)
return -1;
***************
*** 316,333 ****
if ((fid = open(name, OPEN_MODE)) == -1)
return -1;
}
! {
! struct tzhead * tzhp;
! union {
! struct tzhead tzhead;
! char buf[sizeof *sp + sizeof *tzhp];
! } u;
int ttisstdcnt;
int ttisgmtcnt;
- i = read(fid, u.buf, sizeof u.buf);
- if (close(fid) != 0)
- return -1;
ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt);
ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt);
sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt);
--- 340,352 ----
if ((fid = open(name, OPEN_MODE)) == -1)
return -1;
}
! nread = read(fid, u.buf, sizeof u.buf);
! if (close(fid) < 0 || nread <= 0)
! return -1;
! for (stored = 4; stored <= 8; stored *= 2) {
int ttisstdcnt;
int ttisgmtcnt;
ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt);
ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt);
sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt);
***************
*** 342,358 ****
(ttisstdcnt != sp->typecnt && ttisstdcnt != 0) ||
(ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0))
return -1;
! if (i - (p - u.buf) < sp->timecnt * 4 + /* ats */
sp->timecnt + /* types */
! sp->typecnt * (4 + 2) + /* ttinfos */
sp->charcnt + /* chars */
! sp->leapcnt * (4 + 4) + /* lsinfos */
ttisstdcnt + /* ttisstds */
ttisgmtcnt) /* ttisgmts */
return -1;
for (i = 0; i < sp->timecnt; ++i) {
! sp->ats[i] = detzcode(p);
! p += 4;
}
for (i = 0; i < sp->timecnt; ++i) {
sp->types[i] = (unsigned char) *p++;
--- 361,379 ----
(ttisstdcnt != sp->typecnt && ttisstdcnt != 0) ||
(ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0))
return -1;
! if (nread - (p - u.buf) <
! sp->timecnt * stored + /* ats */
sp->timecnt + /* types */
! sp->typecnt * 6 + /* ttinfos */
sp->charcnt + /* chars */
! sp->leapcnt * (stored + 4) + /* lsinfos */
ttisstdcnt + /* ttisstds */
ttisgmtcnt) /* ttisgmts */
return -1;
for (i = 0; i < sp->timecnt; ++i) {
! sp->ats[i] = (stored == 4) ?
! detzcode(p) : detzcode64(p);
! p += stored;
}
for (i = 0; i < sp->timecnt; ++i) {
sp->types[i] = (unsigned char) *p++;
***************
*** 380,387 ****
register struct lsinfo * lsisp;
lsisp = &sp->lsis[i];
! lsisp->ls_trans = detzcode(p);
! p += 4;
lsisp->ls_corr = detzcode(p);
p += 4;
}
--- 401,409 ----
register struct lsinfo * lsisp;
lsisp = &sp->lsis[i];
! lsisp->ls_trans = (stored == 4) ?
! detzcode(p) : detzcode64(p);
! p += stored;
lsisp->ls_corr = detzcode(p);
p += 4;
}
***************
*** 438,444 ****
--- 460,488 ----
}
break;
}
+ /*
+ ** If this is an old file, we're done.
+ */
+ if (u.tzhead.tzh_version[0] == '\0')
+ break;
+ /*
+ ** If this is a narrow integer time_t system, we're done.
+ */
+ if (stored >= sizeof(time_t) && TYPE_INTEGRAL(time_t))
+ break;
+ nread -= p - u.buf;
+ for (i = 0; i < nread; ++i)
+ u.buf[i] = p[i];
}
+ i = 2 * YEARSPERREPEAT;
+ sp->goback = sp->goahead = sp->timecnt > i;
+ sp->goback &= sp->types[i] == sp->types[0] &&
+ sp->ats[i] - sp->ats[0] == SECSPERREPEAT;
+ sp->goahead &=
+ sp->types[sp->timecnt - 1] ==
+ sp->types[sp->timecnt - 1 - i] &&
+ sp->ats[sp->timecnt - 1] - sp->ats[sp->timecnt - 1 - i] ==
+ SECSPERREPEAT;
return 0;
}
***************
*** 1046,1051 ****
--- 1090,1133 ----
if (sp == NULL)
return gmtsub(timep, offset, tmp);
#endif /* defined ALL_STATE */
+ if ((sp->goback && t < sp->ats[0]) ||
+ (sp->goahead && t > sp->ats[sp->timecnt - 1])) {
+ time_t newt = t;
+ register time_t seconds;
+ register time_t tcycles;
+ register signed64_t icycles;
+
+ if (t < sp->ats[0])
+ seconds = sp->ats[0] - t;
+ else seconds = t - sp->ats[sp->timecnt - 1];
+ --seconds;
+ tcycles = seconds / SECSPERREPEAT;
+ ++tcycles;
+ icycles = tcycles;
+ if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
+ return NULL;
+ seconds = icycles;
+ seconds *= SECSPERREPEAT;
+ if (t < sp->ats[0])
+ newt += seconds;
+ else newt -= seconds;
+ if (newt < sp->ats[0] ||
+ newt > sp->ats[sp->timecnt - 1])
+ return NULL; /* "cannot happen" */
+ result = localsub(&newt, offset, tmp);
+ if (result == tmp) {
+ register time_t newy;
+
+ newy = tmp->tm_year;
+ if (t < sp->ats[0])
+ newy -= icycles * YEARSPERREPEAT;
+ else newy += icycles * YEARSPERREPEAT;
+ tmp->tm_year = newy;
+ if (tmp->tm_year != newy)
+ return NULL;
+ }
+ return result;
+ }
if (sp->timecnt == 0 || t < sp->ats[0]) {
i = 0;
while (sp->ttis[i].tt_isdst)
*** tz/private.h Thu Apr 21 15:20:23 2005
--- tzexp/private.h Thu Apr 21 15:21:15 2005
***************
*** 21,30 ****
#ifndef lint
#ifndef NOID
! static char privatehid[] = "@(#)private.h 7.55";
#endif /* !defined NOID */
#endif /* !defined lint */
/*
** Defaults for preprocessor symbols.
** You can override these in your C compiler options, e.g. `-DHAVE_ADJTIME=0'.
--- 21,36 ----
#ifndef lint
#ifndef NOID
! static char privatehid[] = "@(#)private.h 7.62";
#endif /* !defined NOID */
#endif /* !defined lint */
+ #ifndef SIGNED64_T
+ #define SIGNED64_T long long
+ #endif /* !defined SIGNED64_T */
+
+ typedef SIGNED64_T signed64_t;
+
/*
** Defaults for preprocessor symbols.
** You can override these in your C compiler options, e.g. `-DHAVE_ADJTIME=0'.
***************
*** 308,313 ****
--- 314,327 ----
char *ctime_r P((time_t const *, char *));
#endif /* HAVE_INCOMPATIBLE_CTIME_R */
+ #ifndef YEARSPERREPEAT
+ #define YEARSPERREPEAT 400 /* years before a Gregorian repeat */
+ #endif /* !defined YEARSPERREPEAT */
+
+ #ifndef SECSPERREPEAT
+ #define SECSPERREPEAT 12622780800
+ #endif /* !defined SECSPERREPEAT */
+
/*
** UNIX was a registered trademark of The Open Group in 2003.
*/
diff -c -r tz/tzfile.5 tzexp/tzfile.5
*** tz/tzfile.5 Thu Apr 21 15:04:14 2005
--- tzexp/tzfile.5 Thu Apr 21 15:09:16 2005
***************
*** 9,15 ****
.IR tzset (3)
begin with the magic characters "TZif" to identify then as
time zone information files,
! followed by sixteen bytes reserved for future use,
followed by six four-byte values of type
.BR long ,
written in a ``standard'' byte order
--- 9,17 ----
.IR tzset (3)
begin with the magic characters "TZif" to identify then as
time zone information files,
! followed by a character identifying the version of the file's format
! (as of 2005, either an ASCII NUL or a '2')
! followed by fifteen bytes containing zeroes reserved for future use,
followed by six four-byte values of type
.BR long ,
written in a ``standard'' byte order
***************
*** 131,138 ****
.I tzh_timecnt
is zero or the time argument is less than the first transition time recorded
in the file.
.SH SEE ALSO
newctime(3)
! .\" @(#)tzfile.5 7.11
.\" This file is in the public domain, so clarified as of
.\" 1996-06-05 by Arthur David Olson (arthur_david_olson(a)nih.gov)
--- 133,145 ----
.I tzh_timecnt
is zero or the time argument is less than the first transition time recorded
in the file.
+ .PP
+ For version-2-format time zone files,
+ the above header and data is followed by a second header and data,
+ identical in format except that
+ eight bytes are used for each transition time or leap second time.
.SH SEE ALSO
newctime(3)
! .\" @(#)tzfile.5 7.13
.\" This file is in the public domain, so clarified as of
.\" 1996-06-05 by Arthur David Olson (arthur_david_olson(a)nih.gov)
diff -c -r tz/tzfile.h tzexp/tzfile.h
*** tz/tzfile.h Thu Apr 21 15:04:14 2005
--- tzexp/tzfile.h Thu Apr 21 15:09:17 2005
***************
*** 21,27 ****
#ifndef lint
#ifndef NOID
! static char tzfilehid[] = "@(#)tzfile.h 7.17";
#endif /* !defined NOID */
#endif /* !defined lint */
--- 21,27 ----
#ifndef lint
#ifndef NOID
! static char tzfilehid[] = "@(#)tzfile.h 7.19";
#endif /* !defined NOID */
#endif /* !defined lint */
***************
*** 49,55 ****
struct tzhead {
char tzh_magic[4]; /* TZ_MAGIC */
! char tzh_reserved[16]; /* reserved for future use */
char tzh_ttisgmtcnt[4]; /* coded number of trans. time flags */
char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */
char tzh_leapcnt[4]; /* coded number of leap seconds */
--- 49,56 ----
struct tzhead {
char tzh_magic[4]; /* TZ_MAGIC */
! char tzh_version[1]; /* '\0' or '2' as of 2005 */
! char tzh_reserved[15]; /* reserved--must be zero */
char tzh_ttisgmtcnt[4]; /* coded number of trans. time flags */
char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */
char tzh_leapcnt[4]; /* coded number of leap seconds */
***************
*** 84,101 ****
*/
/*
** In the current implementation, "tzset()" refuses to deal with files that
** exceed any of the limits below.
*/
#ifndef TZ_MAX_TIMES
! /*
! ** The TZ_MAX_TIMES value below is enough to handle a bit more than a
! ** year's worth of solar time (corrected daily to the nearest second) or
! ** 138 years of Pacific Presidential Election time
! ** (where there are three time zone transitions every fourth year).
! */
! #define TZ_MAX_TIMES 370
#endif /* !defined TZ_MAX_TIMES */
#ifndef TZ_MAX_TYPES
--- 85,102 ----
*/
/*
+ ** If tzh_version is '2' or greater, the above is followed by a second instance
+ ** of tzhead and a second instance of the data in which each coded transition
+ ** time uses 8 rather than 4 chars.
+ */
+
+ /*
** In the current implementation, "tzset()" refuses to deal with files that
** exceed any of the limits below.
*/
#ifndef TZ_MAX_TIMES
! #define TZ_MAX_TIMES 1000
#endif /* !defined TZ_MAX_TIMES */
#ifndef TZ_MAX_TYPES
diff -c -r tz/zic.8 tzexp/zic.8
*** tz/zic.8 Thu Apr 21 15:04:14 2005
--- tzexp/zic.8 Mon Apr 4 15:39:43 2005
***************
*** 21,28 ****
.B \-L
.I leapsecondfilename
] [
- .B \-s
- ] [
.B \-y
.I command
] [
--- 21,26 ----
***************
*** 86,96 ****
.IR zic )
appears in the input.
.TP
- .B \-s
- Limit time values stored in output files to values that are the same
- whether they're taken to be signed or unsigned.
- You can use this option to generate SVVS-compatible files.
- .TP
.BI "\-y " command
Use the given
.I command
--- 84,89 ----
***************
*** 421,424 ****
/usr/local/etc/zoneinfo standard directory used for created files
.SH "SEE ALSO"
newctime(3), tzfile(5), zdump(8)
! .\" @(#)zic.8 7.22
--- 414,417 ----
/usr/local/etc/zoneinfo standard directory used for created files
.SH "SEE ALSO"
newctime(3), tzfile(5), zdump(8)
! .\" @(#)zic.8 7.23
diff -c -r tz/zic.c tzexp/zic.c
*** tz/zic.c Thu Apr 21 15:04:15 2005
--- tzexp/zic.c Mon Apr 4 15:39:43 2005
***************
*** 1,15 ****
! static char elsieid[] = "@(#)zic.c 7.122";
- /*
- ** Regardless of the type of time_t, we do our work using this type.
- */
-
- typedef int zic_t;
-
#include "private.h"
#include "locale.h"
#include "tzfile.h"
#if HAVE_SYS_STAT_H
#include "sys/stat.h"
#endif
--- 1,13 ----
! static char elsieid[] = "@(#)zic.c 7.127";
#include "private.h"
#include "locale.h"
#include "tzfile.h"
+ #define ZIC_VERSION '2'
+
+ typedef signed64_t zic_t;
+
#if HAVE_SYS_STAT_H
#include "sys/stat.h"
#endif
***************
*** 40,45 ****
--- 38,45 ----
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 */
***************
*** 99,104 ****
--- 99,105 ----
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));
***************
*** 117,122 ****
--- 118,124 ----
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));
***************
*** 126,131 ****
--- 128,134 ----
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,
***************
*** 146,158 ****
static int errors;
static const char * filename;
static int leapcnt;
static int linenum;
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;
--- 149,162 ----
static int errors;
static const char * filename;
static int leapcnt;
+ static int leapseen;
+ static int leapminyear;
+ static int leapmaxyear;
static int linenum;
static zic_t max_time;
static int max_year;
static zic_t min_time;
static int min_year;
static int noise;
static const char * rfilename;
static int rlinenum;
***************
*** 449,455 ****
usage P((void))
{
(void) fprintf(stderr, _("%s: usage is %s \
! [ --version ] [ -s ] [ -v ] [ -l localtime ] [ -p posixrules ] \\\n\
\t[ -d directory ] [ -L leapseconds ] [ -y yearistype ] [ filename ... ]\n"),
progname, progname);
(void) exit(EXIT_FAILURE);
--- 453,459 ----
usage P((void))
{
(void) fprintf(stderr, _("%s: usage is %s \
! [ --version ] [ -v ] [ -l localtime ] [ -p posixrules ] \\\n\
\t[ -d directory ] [ -L leapseconds ] [ -y yearistype ] [ filename ... ]\n"),
progname, progname);
(void) exit(EXIT_FAILURE);
***************
*** 460,466 ****
static const char * directory;
static const char * leapsec;
static const char * yitcommand;
- static int sflag = FALSE;
int
main(argc, argv)
--- 464,469 ----
***************
*** 482,487 ****
--- 485,495 ----
(void) textdomain(TZ_DOMAIN);
#endif /* HAVE_GETTEXT */
progname = argv[0];
+ if (8 > sizeof(signed64_t)) {
+ (void) fprintf(stderr,
+ "%s: wild compilation-time specification of SIGNED64_T\n", progname);
+ exit(EXIT_FAILURE);
+ }
for (i = 1; i < argc; ++i)
if (strcmp(argv[i], "--version") == 0) {
(void) printf("%s\n", elsieid);
***************
*** 545,551 ****
noise = TRUE;
break;
case 's':
! sflag = TRUE;
break;
}
if (optind == argc - 1 && strcmp(argv[optind], "=") == 0)
--- 553,559 ----
noise = TRUE;
break;
case 's':
! (void) printf("%s: -s ignored\n", progname);
break;
}
if (optind == argc - 1 && strcmp(argv[optind], "=") == 0)
***************
*** 667,720 ****
ifree(toname);
}
! #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;
! 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
--- 675,691 ----
ifree(toname);
}
! #define TIME_T_BITS_IN_FILE 64
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);
}
static int
***************
*** 1155,1160 ****
--- 1126,1136 ----
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) {
***************
*** 1309,1315 ****
*/
cp = loyearp;
lp = byword(cp, begin_years);
! if (lp != NULL) switch ((int) lp->l_value) {
case YR_MINIMUM:
rp->r_loyear = INT_MIN;
break;
--- 1285,1292 ----
*/
cp = loyearp;
lp = byword(cp, begin_years);
! rp->r_lowasnum = lp == NULL;
! if (!rp->r_lowasnum) switch ((int) lp->l_value) {
case YR_MINIMUM:
rp->r_loyear = INT_MIN;
break;
***************
*** 1324,1337 ****
} 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;
! if ((lp = byword(cp, end_years)) != NULL) switch ((int) lp->l_value) {
case YR_MINIMUM:
rp->r_hiyear = INT_MIN;
break;
--- 1301,1311 ----
} else if (sscanf(cp, scheck(cp, "%d"), &rp->r_loyear) != 1) {
error(_("invalid starting year"));
return;
}
cp = hiyearp;
! lp = byword(cp, end_years);
! rp->r_hiwasnum = lp == NULL;
! if (!rp->r_hiwasnum) switch ((int) lp->l_value) {
case YR_MINIMUM:
rp->r_hiyear = INT_MIN;
break;
***************
*** 1349,1359 ****
} 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"));
--- 1323,1328 ----
***************
*** 1368,1375 ****
}
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:
--- 1337,1342 ----
***************
*** 1423,1429 ****
char * const buf;
{
register int i;
! register long shift;
for (i = 0, shift = 24; i < 4; ++i, shift -= 8)
buf[i] = val >> shift;
--- 1390,1396 ----
char * const buf;
{
register int i;
! register int shift;
for (i = 0, shift = 24; i < 4; ++i, shift -= 8)
buf[i] = val >> shift;
***************
*** 1430,1435 ****
--- 1397,1414 ----
}
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;
FILE * const fp;
***************
*** 1440,1445 ****
--- 1419,1435 ----
(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)
void * avp;
***************
*** 1452,1467 ****
else return 0;
}
static void
writezone(name)
const char * const name;
{
! 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.
--- 1442,1469 ----
else return 0;
}
+ static int
+ is32(x)
+ zic_t x;
+ {
+ x >>= 31;
+ return x == 0 || x == ~0;
+ }
+
static void
writezone(name)
const char * const name;
{
! 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];
/*
** Sort.
***************
*** 1505,1510 ****
--- 1507,1542 ----
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]) {
+ 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);
***************
*** 1529,1595 ****
(void) exit(EXIT_FAILURE);
}
}
! 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)
! 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 = 0; i < timecnt; ++i) {
! j = leapcnt;
! while (--j >= 0)
! if (ats[i] >= trans[j]) {
! ats[i] = tadd(ats[i], corr[j]);
! break;
! }
! puttzcode((long) ats[i], fp);
}
- 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);
--- 1561,1652 ----
(void) exit(EXIT_FAILURE);
}
}
! for (pass = 1; pass <= 2; ++pass) {
! register int thistimei, thistimecnt;
! register int thisleapi, thisleapcnt;
! register int thistimelim, thisleaplim;
!
! 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;
#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(typecnt), tzh.tzh_ttisgmtcnt);
! convert(eitol(typecnt), tzh.tzh_ttisstdcnt);
! convert(eitol(thisleapcnt), tzh.tzh_leapcnt);
! convert(eitol(thistimecnt), tzh.tzh_timecnt);
! convert(eitol(typecnt), tzh.tzh_typecnt);
! convert(eitol(charcnt), 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);
#undef DO
! for (i = thistimei; i < thistimelim; ++i)
! if (pass == 1)
! puttzcode((long) ats[i], fp);
! else puttzcode64(ats[i], fp);
! if (thistimecnt > 0)
! (void) fwrite((void *) &types[thistimei],
! (size_t) sizeof types[0],
! (size_t) thistimecnt,
! fp);
! for (i = 0; i < typecnt; ++i) {
! puttzcode(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 = 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(todo, fp);
! else puttzcode64(todo, fp);
! puttzcode(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);
***************
*** 1617,1622 ****
--- 1674,1689 ----
}
static void
+ updateminmax(x)
+ const int x;
+ {
+ if (min_year > x)
+ min_year = x;
+ if (max_year < x)
+ max_year = x;
+ }
+
+ static void
outzone(zpfirst, zonecount)
const struct zone * const zpfirst;
const int zonecount;
***************
*** 1649,1655 ****
--- 1716,1744 ----
*/
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);
+ }
+ }
+ 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 (i = 0; i < zonecount; ++i) {
/*
** A guess that may well be corrected later.
*/
***************
*** 2180,2187 ****
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)
--- 2269,2274 ----