Zic on 64-bit systems
Olson, Arthur David (NIH/NCI)
olsona at dc37a.nci.nih.gov
Tue Dec 7 20:11:12 UTC 2004
The last round of changes made zdump work on systems with variant time_t
types and made zic compilable on such systems.
The name of the game in this round is to make zic work on systems with
variant time_t types.
The easy way out (adopted below) is to forego (as much as possible) the use
of time_t in zic.
I've also included a change to localtime.c to cope with situations where
time_t is unsigned on the running system but the data file being used
contains signed transition times (and vice versa). I'm hoping this makes it
more acceptable to adopt the new tactic of having zic always produce files
with signed transition times (even on systems with signed time_t values).
(Of course there are bigger fish to fry later to extend the time zone
package so that 64-bit transition times can be handled.
I'm hoping we can tweak the current system as much as possible before
beginning the design discussion needed before frying the bigger fish.)
--ado
------- zic.c -------
*** /tmp/geta22008 Tue Dec 7 14:49:46 2004
--- /tmp/getb22008 Tue Dec 7 14:49:46 2004
***************
*** 1,5 ****
! static char elsieid[] = "@(#)zic.c 7.117";
#include "private.h"
#include "locale.h"
#include "tzfile.h"
--- 1,11 ----
! static char elsieid[] = "@(#)zic.c 7.118";
+ /*
+ ** Regardless of the type of time_t, we do our work using this type.
+ */
+
+ typedef long zic_t;
+
#include "private.h"
#include "locale.h"
#include "tzfile.h"
***************
*** 50,56 ****
const char * r_abbrvar; /* variable part of abbreviation */
int r_todo; /* a rule to do (used in outzone) */
! time_t r_temp; /* used in outzone */
};
/*
--- 56,62 ----
const char * r_abbrvar; /* variable part of abbreviation */
int r_todo; /* a rule to do (used in outzone) */
! zic_t r_temp; /* used in outzone */
};
/*
***************
*** 76,82 ****
int z_nrules;
struct rule z_untilrule;
! time_t z_untiltime;
};
extern int getopt P((int argc, char * const argv[],
--- 82,88 ----
int z_nrules;
struct rule z_untilrule;
! zic_t z_untiltime;
};
extern int getopt P((int argc, char * const argv[],
***************
*** 85,94 ****
extern char * optarg;
extern int optind;
! static void addtt P((time_t starttime, int type));
static int addtype P((long gmtoff, const char * abbr, int isdst,
int ttisstd, int ttisgmt));
! static void leapadd P((time_t t, int positive, int rolling, int count));
static void adjleap P((void));
static void associate P((void));
static int ciequal P((const char * ap, const char * bp));
--- 91,100 ----
extern char * optarg;
extern int optind;
! static void addtt P((zic_t starttime, int type));
static int addtype P((long gmtoff, const char * abbr, int isdst,
int ttisstd, int ttisgmt));
! static void leapadd P((zic_t t, int positive, int rolling, int count));
static void adjleap P((void));
static void associate P((void));
static int ciequal P((const char * ap, const char * bp));
***************
*** 121,133 ****
static void outzone P((const struct zone * zp, int ntzones));
static void puttzcode P((long code, FILE * fp));
static int rcomp P((const void * leftp, const void * rightp));
! static time_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 void setboundaries P((void));
! static time_t tadd P((time_t t1, long t2));
static void usage P((void));
static void writezone P((const char * name));
static int yearistype P((int year, const char * type));
--- 127,139 ----
static void outzone P((const struct zone * zp, int ntzones));
static void puttzcode P((long 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 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));
static int yearistype P((int year, const char * type));
***************
*** 141,150 ****
static const char * filename;
static int leapcnt;
static int linenum;
! static time_t max_time;
static int max_year;
static int max_year_representable;
! static time_t min_time;
static int min_year;
static int min_year_representable;
static int noise;
--- 147,156 ----
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;
***************
*** 334,340 ****
};
static struct attype {
! time_t at;
unsigned char type;
} attypes[TZ_MAX_TIMES];
static long gmtoffs[TZ_MAX_TYPES];
--- 340,346 ----
};
static struct attype {
! zic_t at;
unsigned char type;
} attypes[TZ_MAX_TIMES];
static long gmtoffs[TZ_MAX_TYPES];
***************
*** 343,349 ****
static char ttisstds[TZ_MAX_TYPES];
static char ttisgmts[TZ_MAX_TYPES];
static char chars[TZ_MAX_CHARS];
! static time_t trans[TZ_MAX_LEAPS];
static long corr[TZ_MAX_LEAPS];
static char roll[TZ_MAX_LEAPS];
--- 349,355 ----
static char ttisstds[TZ_MAX_TYPES];
static char ttisgmts[TZ_MAX_TYPES];
static char chars[TZ_MAX_CHARS];
! static zic_t trans[TZ_MAX_LEAPS];
static long corr[TZ_MAX_LEAPS];
static char roll[TZ_MAX_LEAPS];
***************
*** 665,671 ****
*/
#define MAX_BITS_IN_FILE 32
! #define TIME_T_BITS_IN_FILE ((TYPE_BIT(time_t) < MAX_BITS_IN_FILE) ?
TYPE_BIT(time_t) : MAX_BITS_IN_FILE)
static void
setboundaries P((void))
--- 671,678 ----
*/
#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))
***************
*** 672,678 ****
{
register int i;
! if (TYPE_SIGNED(time_t)) {
min_time = -1;
for (i = 0; i < TIME_T_BITS_IN_FILE - 1; ++i)
min_time *= 2;
--- 679,685 ----
{
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;
***************
*** 686,693 ****
max_time *= 2;
--max_time;
}
! min_year = TM_YEAR_BASE + gmtime(&min_time)->tm_year;
! max_year = TM_YEAR_BASE + gmtime(&max_time)->tm_year;
min_year_representable = min_year;
max_year_representable = max_year;
}
--- 693,706 ----
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;
}
***************
*** 1113,1119 ****
register int i, j;
int year, month, day;
long dayoff, tod;
! time_t t;
if (nfields != LEAP_FIELDS) {
error(_("wrong number of fields on Leap line"));
--- 1126,1132 ----
register int i, j;
int year, month, day;
long dayoff, tod;
! zic_t t;
if (nfields != LEAP_FIELDS) {
error(_("wrong number of fields on Leap line"));
***************
*** 1157,1163 ****
return;
}
dayoff = oadd(dayoff, eitol(day - 1));
! if (dayoff < 0 && !TYPE_SIGNED(time_t)) {
error(_("time before zero"));
return;
}
--- 1170,1176 ----
return;
}
dayoff = oadd(dayoff, eitol(day - 1));
! if (dayoff < 0 && !TYPE_SIGNED(zic_t)) {
error(_("time before zero"));
return;
}
***************
*** 1169,1175 ****
error(_("time too large"));
return;
}
! t = (time_t) dayoff * SECSPERDAY;
tod = gethms(fields[LP_TIME], _("invalid time of day"), FALSE);
cp = fields[LP_CORR];
{
--- 1182,1188 ----
error(_("time too large"));
return;
}
! t = (zic_t) dayoff * SECSPERDAY;
tod = gethms(fields[LP_TIME], _("invalid time of day"), FALSE);
cp = fields[LP_CORR];
{
***************
*** 1431,1437 ****
register int i, j;
static char * fullname;
static struct tzhead tzh;
! time_t ats[TZ_MAX_TIMES];
unsigned char types[TZ_MAX_TIMES];
/*
--- 1444,1450 ----
register int i, j;
static char * fullname;
static struct tzhead tzh;
! zic_t ats[TZ_MAX_TIMES];
unsigned char types[TZ_MAX_TIMES];
/*
***************
*** 1596,1602 ****
register struct rule * rp;
register int i, j;
register int usestart, useuntil;
! register time_t starttime, untiltime;
register long gmtoff;
register long stdoff;
register int year;
--- 1609,1615 ----
register struct rule * rp;
register int i, j;
register int usestart, useuntil;
! register zic_t starttime, untiltime;
register long gmtoff;
register long stdoff;
register int year;
***************
*** 1665,1671 ****
}
for ( ; ; ) {
register int k;
! register time_t jtime, ktime;
register long offset;
char buf[BUFSIZ];
--- 1678,1684 ----
}
for ( ; ; ) {
register int k;
! register zic_t jtime, ktime;
register long offset;
char buf[BUFSIZ];
***************
*** 1777,1783 ****
static void
addtt(starttime, type)
! const time_t starttime;
int type;
{
if (starttime <= min_time ||
--- 1790,1796 ----
static void
addtt(starttime, type)
! const zic_t starttime;
int type;
{
if (starttime <= min_time ||
***************
*** 1861,1867 ****
static void
leapadd(t, positive, rolling, count)
! const time_t t;
const int positive;
const int rolling;
int count;
--- 1874,1880 ----
static void
leapadd(t, positive, rolling, count)
! const zic_t t;
const int positive;
const int rolling;
int count;
***************
*** 2049,2060 ****
return t;
}
! static time_t
tadd(t1, t2)
! const time_t t1;
const long t2;
{
! register time_t t;
if (t1 == max_time && t2 > 0)
return max_time;
--- 2062,2073 ----
return t;
}
! static zic_t
tadd(t1, t2)
! const zic_t t1;
const long t2;
{
! register zic_t t;
if (t1 == max_time && t2 > 0)
return max_time;
***************
*** 2073,2079 ****
** 1970, 00:00 LOCAL time - in that year that the rule refers to.
*/
! static time_t
rpytime(rp, wantedy)
register const struct rule * const rp;
register const int wantedy;
--- 2086,2092 ----
** 1970, 00:00 LOCAL time - in that year that the rule refers to.
*/
! static zic_t
rpytime(rp, wantedy)
register const struct rule * const rp;
register const int wantedy;
***************
*** 2080,2086 ****
{
register int y, m, i;
register long dayoff; /* with a nod to Margaret O.
*/
! register time_t t;
if (wantedy == INT_MIN)
return min_time;
--- 2093,2099 ----
{
register int y, m, i;
register long dayoff; /* with a nod to Margaret O.
*/
! register zic_t t;
if (wantedy == INT_MIN)
return min_time;
***************
*** 2147,2159 ****
warning(_("rule goes past start/end of
month--will not work with pre-2004 versions of zic"));
}
}
! if (dayoff < 0 && !TYPE_SIGNED(time_t))
return min_time;
if (dayoff < min_time / SECSPERDAY)
return min_time;
if (dayoff > max_time / SECSPERDAY)
return max_time;
! t = (time_t) dayoff * SECSPERDAY;
return tadd(t, rp->r_tod);
}
--- 2160,2172 ----
warning(_("rule goes past start/end of
month--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)
return max_time;
! t = (zic_t) dayoff * SECSPERDAY;
return tadd(t, rp->r_tod);
}
------- localtime.c -------
*** /tmp/geta22026 Tue Dec 7 14:49:46 2004
--- /tmp/getb22026 Tue Dec 7 14:49:46 2004
***************
*** 2,10 ****
** XXX--do the right thing if time_t is double and
** the value fed to gmtime or localtime is very very negative or
** very very positive (which causes problems with the days-and-rem logic).
- ** Also: what of systems where time_t is unsigned
- ** (in particular when used on date files generated on systems where
- ** time_t is signed).
*/
/*
--- 2,7 ----
***************
*** 14,20 ****
#ifndef lint
#ifndef NOID
! static char elsieid[] = "@(#)localtime.c 7.82";
#endif /* !defined NOID */
#endif /* !defined lint */
--- 11,17 ----
#ifndef lint
#ifndef NOID
! static char elsieid[] = "@(#)localtime.c 7.83";
#endif /* !defined NOID */
#endif /* !defined lint */
***************
*** 418,423 ****
--- 415,447 ----
return -1;
}
}
+ /*
+ ** Out-of-sort ats should mean we're running on a
+ ** signed time_t system but using a data file with
+ ** unsigned values (or vice versa).
+ */
+ for (i = 0; i < sp->timecnt - 2; ++i)
+ if (sp->ats[i] > sp->ats[i + 1]) {
+ ++i;
+ if (TYPE_SIGNED(time_t)) {
+ /*
+ ** Ignore the end (easy).
+ */
+ sp->timecnt = i;
+ } else {
+ /*
+ ** Ignore the beginning (harder).
+ */
+ register int j;
+
+ for (j = 0; j + i < sp->timecnt;
++j) {
+ sp->ats[j] = sp->ats[j + i];
+ sp->types[j] = sp->types[j +
i];
+ }
+ sp->timecnt = j;
+ }
+ break;
+ }
}
return 0;
}
More information about the tz
mailing list