proposed zic.c change to cope with "32 < sizeof (time_t)"

Paul Eggert eggert at twinsun.com
Sun Oct 22 05:17:14 UTC 1995


Here are three minor suggestions about the proposed change.
First, it should have a comment somewhere about the 32-bit limitation.
Second, it computes at run-time values that are computable at compile-time.
Third, it assumes two's complement arithmetic; this is a safe
assumption these days, but it shouldn't hurt to switch to expressions
like `max_time = ~ (time_t) 0 - min_time', which should work with both
one's and two's complement arithmetic.

Here is a proposed patch.

===================================================================
RCS file: RCS/zic.c,v
retrieving revision 1995.3.0.1
retrieving revision 1995.3.0.2
diff -c -r1995.3.0.1 -r1995.3.0.2
*** zic.c	1995/10/21 05:58:47	1995.3.0.1
--- zic.c	1995/10/22 01:53:33	1995.3.0.2
***************
*** 127,136 ****
  static const char *	filename;
  static int		leapcnt;
  static int		linenum;
- static int		max_int;
  static time_t		max_time;
  static int		max_year;
- static int		min_int;
  static time_t		min_time;
  static int		min_year;
  static int		noise;
--- 127,134 ----
***************
*** 139,145 ****
  static const char *	progname;
  static int		timecnt;
  static int		typecnt;
- static int		tt_signed;
  
  /*
  ** Line codes.
--- 137,142 ----
***************
*** 567,621 ****
  	ifree(toname);
  }
  
  #define MAX_BITS_IN_FILE	32
  
  static void
  setboundaries P((void))
  {
! 	register time_t	bit;
! 	register int	nbits;
! 	register int	bii;
! 
! 	nbits = 0;
! 	for (bit = 1; bit > 0; bit <<= 1)
! 		++nbits;
! 	tt_signed = (bit != 0);
! 	if (tt_signed)
! 		++nbits;
! 	if (tt_signed) {
! 		if (nbits <= MAX_BITS_IN_FILE) {
! 			min_time = bit;
! 			max_time = bit;
! 			++max_time;
! 			max_time = -max_time;
! 		} else {
! 			max_time = 1;
! 			max_time <<= (MAX_BITS_IN_FILE - 1);
! 			--max_time;
! 			min_time = max_time;
! 			--min_time;
! 		}
  		if (sflag)
  			min_time = 0;
  	} else {
  		min_time = 0;
! 		if (nbits <= MAX_BITS_IN_FILE)
! 			max_time = ~(time_t) 0;
! 		else {
! 			max_time = 1;
! 			max_time <<= MAX_BITS_IN_FILE;
! 			--max_time;
! 		}
! 		if (sflag)
! 			max_time >>= 1;
  	}
  	min_year = TM_YEAR_BASE + gmtime(&min_time)->tm_year;
  	max_year = TM_YEAR_BASE + gmtime(&max_time)->tm_year;
- 
- 	for (bii = 1; bii > 0; bii <<= 1)
- 		continue;
- 	min_int = bii;
- 	max_int = -1 - bii;
  }
  
  static int
--- 564,604 ----
  	ifree(toname);
  }
  
+ #ifndef INT_MIN
+ #define INT_MIN (~0 << (sizeof (int) * CHAR_BIT - 1))
+ #endif
+ #ifndef INT_MAX
+ #define INT_MAX (~0 - INT_MIN)
+ #endif
+ 
+ #define TIME_T_SIGNED ((time_t) -1 < 0)
+ #define TIME_T_BIT (sizeof (time_t) * CHAR_BIT)
+ 
+ /* 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 (TIME_T_BIT < MAX_BITS_IN_FILE \
+ 			     ? TIME_T_BIT : MAX_BITS_IN_FILE)
  
  static void
  setboundaries P((void))
  {
! 	if (TIME_T_SIGNED) {
! 		min_time = ~ (time_t) 0;
! 		min_time <<= TIME_T_BITS_IN_FILE - 1;
! 		max_time = ~ (time_t) 0 - min_time;
  		if (sflag)
  			min_time = 0;
  	} else {
  		min_time = 0;
! 		max_time = 2 - sflag;
! 		max_time <<= TIME_T_BITS_IN_FILE - 1;
! 		--max_time;
  	}
  	min_year = TM_YEAR_BASE + gmtime(&min_time)->tm_year;
  	max_year = TM_YEAR_BASE + gmtime(&max_time)->tm_year;
  }
  
  static int
***************
*** 1050,1056 ****
  			return;
  	}
  	dayoff = oadd(dayoff, eitol(day - 1));
! 	if (dayoff < 0 && !tt_signed) {
  		error("time before zero");
  		return;
  	}
--- 1033,1039 ----
  			return;
  	}
  	dayoff = oadd(dayoff, eitol(day - 1));
! 	if (!TIME_T_SIGNED && dayoff < 0) {
  		error("time before zero");
  		return;
  	}
***************
*** 1173,1182 ****
  	lp = byword(cp, begin_years);
  	if (lp != NULL) switch ((int) lp->l_value) {
  		case YR_MINIMUM:
! 			rp->r_loyear = min_int;
  			break;
  		case YR_MAXIMUM:
! 			rp->r_loyear = max_int;
  			break;
  		default:	/* "cannot happen" */
  			(void) fprintf(stderr,
--- 1156,1165 ----
  	lp = byword(cp, begin_years);
  	if (lp != NULL) switch ((int) lp->l_value) {
  		case YR_MINIMUM:
! 			rp->r_loyear = INT_MIN;
  			break;
  		case YR_MAXIMUM:
! 			rp->r_loyear = INT_MAX;
  			break;
  		default:	/* "cannot happen" */
  			(void) fprintf(stderr,
***************
*** 1190,1199 ****
  	cp = hiyearp;
  	if ((lp = byword(cp, end_years)) != NULL) switch ((int) lp->l_value) {
  		case YR_MINIMUM:
! 			rp->r_hiyear = min_int;
  			break;
  		case YR_MAXIMUM:
! 			rp->r_hiyear = max_int;
  			break;
  		case YR_ONLY:
  			rp->r_hiyear = rp->r_loyear;
--- 1173,1182 ----
  	cp = hiyearp;
  	if ((lp = byword(cp, end_years)) != NULL) switch ((int) lp->l_value) {
  		case YR_MINIMUM:
! 			rp->r_hiyear = INT_MIN;
  			break;
  		case YR_MAXIMUM:
! 			rp->r_hiyear = INT_MAX;
  			break;
  		case YR_ONLY:
  			rp->r_hiyear = rp->r_loyear;
***************
*** 1859,1867 ****
  	register long	dayoff;			/* with a nod to Margaret O. */
  	register time_t	t;
  
! 	if (wantedy == min_int)
  		return min_time;
! 	if (wantedy == max_int)
  		return max_time;
  	dayoff = 0;
  	m = TM_JANUARY;
--- 1842,1850 ----
  	register long	dayoff;			/* with a nod to Margaret O. */
  	register time_t	t;
  
! 	if (wantedy == INT_MIN)
  		return min_time;
! 	if (wantedy == INT_MAX)
  		return max_time;
  	dayoff = 0;
  	m = TM_JANUARY;
***************
*** 1924,1930 ****
  			(void) exit(EXIT_FAILURE);
  		}
  	}
! 	if (dayoff < 0 && !tt_signed)
  		return min_time;
  	t = (time_t) dayoff * SECSPERDAY;
  	/*
--- 1907,1913 ----
  			(void) exit(EXIT_FAILURE);
  		}
  	}
! 	if (!TIME_T_SIGNED && dayoff < 0)
  		return min_time;
  	t = (time_t) dayoff * SECSPERDAY;
  	/*



More information about the tz mailing list