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