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; /*