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