[tz] [PATCH] Port to NetBSD, where, e.g., 'time_t' is wider than 'long'.

Paul Eggert eggert at cs.ucla.edu
Tue May 28 04:30:51 UTC 2013


Here's a proposed porting patch, which I've also pushed into the
experimental version on github.  As usual, comments welcome.

I audited the code and fixed as many width-asssumptions as I could
find, including several places where the code assumed that 'time_t'
was no wider than 'long'; this assumption is not true on 32-bit
NetBSD platforms.  This caught every problem that is already fixed
in the NetBSD zic.c, and caught quite a few more.
* Makefile: Add comments re HAVE_DOS_FILE_NAMES and HAVE_INTTYPES_H.
* date.c (checkfinal, netsettime): Don't use 'long' where 'int' will do.
* difftime.c (difftime): Mark with ATTRIBUTE_CONST.
Use uintmax_t, not unsigned long, for the widest unsigned integer type.
Use long double, not double, if time_t is wider than uintmax_t;
this can in theory help on nonstandard platforms, such as GCC
with 64-bit uintmax_t and 128-bit __int128_t.
* localtime.c (struct ttinfo.tt_gmtoff, struct rule.r_time)
(detzcode, getsecs, getoffset, gmtsub, localsub, increment_overflow32)
(normalize_overflow32, time1, time2, timesub, transtime, tzparse)
(time2sub, timeoff, gtime):
* tzfile.h (SECSPERDAY):
* zdump.c (SECSPERDAY):
* zic.c (convert, puttzcode):
Use int_fast32_t, not long, when all we care is that values up to
2**31 can be stored.  This doesn't fix any bugs, but it allows
more opportunity for compiler optimization.
(struct lsinfo.ls_corr, timesub, leapcorr):
Use int_fast64_t, not long, when values up to 2**63 can be stored.
(timesub): Make it clearer when we are truncating 0.5 to 0.
(increment_overflow32): Rename from long_increment_overflow.
All uses changed.
(normalize_overflow32): Rename from long_normalize_overflow.
All uses changed.
* private.h (HAVE_INTTYPES_H, ATTRIBUTE_CONST): New macros.
Include <inttypes.h> if HAVE_INTTYPES_H.
(INT_FAST64_MIN, INT_FAST64_MAX, SCNdFAST64, int_fast32_t, PRIdMAX)
(uintmax_t, PRIuMAX, _Noreturn):
Define to reasonable values if it's an older compiler.
* scheck.c (scheck): Add support for arbitrary formats, such as
those that SCNdFAST64 can expand to, at the price of no longer
supporting weird conversion specs like "%[%]".
* strftime.c (_fmt): Use intmax_t and uintmax_t to format time_t,
not long and unsigned long.
* zdump.c (int_fast32_t, intmax_t, PRIdMAX, SCNdMAX):
Define for pre-C99 compilers, like private.h does.
(delta, yeartot, main): Use intmax_t, not long.
(hunt): Use time_t, not long, since the diff must be nonnegative.
(tformat): Allow for time_t wider than long.
* zic.c (ZIC_MIN, ZIC_MAX, SCNdZIC): New macros.
(OFFSET_STRLEN_MAXIMUM, RULE_STRLEN_MAXIMUM): Remove.
(struct rule): Make r_loyear, r_hiyear, r_tod, r_stdoff, z_gmtoff,
z_stdoff zic_t, not long.
(addtype, gethms, oadd, rpytime, tadd, gmtoffs, corr, inleap)
(stringoffset, stringrule, outzone, addtype, adjleap, rpytime)
(LDAYSPERWEEK):
Use zic_t, not long.
(leapminyear, leapmaxyear, min_year, max_year, rulesub, updateminmax)
(outzone, rpytime):
Use zic_t, not int.
(usage): Now _Noreturn.
(main): Use S_IWGRP, not 'unix', to determine whether to call umask.
(writezone): Omit unnecessary cast.
(mkdirs): Use HAVE_DOS_FILE_NAMES, not 'unix', to determine
whether to parse DOS file anmes.
(eitol): Remove; no longer needed.
---
 Makefile    |   2 +
 date.c      |   6 +-
 difftime.c  |  21 +++----
 localtime.c | 132 ++++++++++++++++++++-------------------
 private.h   |  58 +++++++++++++++++-
 scheck.c    |  29 ++++++---
 strftime.c  |   8 +--
 tzfile.h    |   2 +-
 zdump.c     |  88 +++++++++++++++++++-------
 zic.c       | 201 ++++++++++++++++++++++++++++--------------------------------
 10 files changed, 323 insertions(+), 224 deletions(-)

diff --git a/Makefile b/Makefile
index 912bab6..2532d4d 100644
--- a/Makefile
+++ b/Makefile
@@ -101,9 +101,11 @@ LDLIBS=
 
 # Add the following to the end of the "CFLAGS=" line as needed.
 #  -DHAVE_ADJTIME=0 if `adjtime' does not exist (SVR0?)
+#  -DHAVE_DOS_FILE_NAMES if file names have drive specifiers etc. (MS-DOS)
 #  -DHAVE_GETTEXT=1 if `gettext' works (GNU, Linux, Solaris); also see LDLIBS
 #  -DHAVE_INCOMPATIBLE_CTIME_R=1 if your system's time.h declares
 #	ctime_r and asctime_r incompatibly with the POSIX standard (Solaris 8).
+#  -DHAVE_INTTYPES_H=1 if you have a pre-C99 compiler with "inttypes.h"
 #  -DHAVE_SETTIMEOFDAY=0 if settimeofday does not exist (SVR0?)
 #  -DHAVE_SETTIMEOFDAY=1 if settimeofday has just 1 arg (SVR4)
 #  -DHAVE_SETTIMEOFDAY=2 if settimeofday uses 2nd arg (4.3BSD)
diff --git a/date.c b/date.c
index b721ad9..047969f 100644
--- a/date.c
+++ b/date.c
@@ -708,8 +708,7 @@ checkfinal(const char * const	value,
 	time_t		othert;
 	struct tm	tm;
 	struct tm	othertm;
-	register int	pass;
-	register long	offset;
+	register int	pass, offset;
 
 	/*
 	** See if there's both a USG and a BSD interpretation.
@@ -807,8 +806,7 @@ iffy(const time_t thist, const time_t thatt,
 static int
 netsettime(struct timeval ntv)
 {
-	int s, length, port, timed_ack, found, err;
-	long waittime;
+	int s, length, port, timed_ack, found, err, waittime;
 	fd_set ready;
 	char hostname[MAXHOSTNAMELEN];
 	struct timeval tout;
diff --git a/difftime.c b/difftime.c
index c8c85b3..fcd18ce 100644
--- a/difftime.c
+++ b/difftime.c
@@ -7,13 +7,12 @@
 
 #include "private.h"	/* for time_t, TYPE_INTEGRAL, and TYPE_SIGNED */
 
-double
+double ATTRIBUTE_CONST
 difftime(const time_t time1, const time_t time0)
 {
 	/*
 	** If (sizeof (double) > sizeof (time_t)) simply convert and subtract
 	** (assuming that the larger type has more precision).
-	** This is the common real-world case circa 2004.
 	*/
 	if (sizeof (double) > sizeof (time_t))
 		return (double) time1 - (double) time0;
@@ -30,8 +29,8 @@ difftime(const time_t time1, const time_t time0)
 		** if the minuend is greater than or equal to the subtrahend.
 		*/
 		if (time1 >= time0)
-			return time1 - time0;
-		else	return -((double) (time0 - time1));
+			return            time1 - time0;
+		else	return -(double) (time0 - time1);
 	}
 	/*
 	** time_t is integral and signed.
@@ -42,16 +41,16 @@ difftime(const time_t time1, const time_t time0)
 		return time1 - time0;
 	/*
 	** time1 and time0 have opposite signs.
-	** Punt if unsigned long is too narrow.
+	** Punt if uintmax_t is too narrow.
+	** This suffers from double rounding; attempt to lessen that
+	** by using long double temporaries.
 	*/
-	if (sizeof (unsigned long) < sizeof (time_t))
-		return (double) time1 - (double) time0;
+	if (sizeof (uintmax_t) < sizeof (time_t))
+		return (long double) time1 - (long double) time0;
 	/*
 	** Stay calm...decent optimizers will eliminate the complexity below.
 	*/
 	if (time1 >= 0 /* && time0 < 0 */)
-		return (unsigned long) time1 +
-			(unsigned long) (-(time0 + 1)) + 1;
-	return -(double) ((unsigned long) time0 +
-		(unsigned long) (-(time1 + 1)) + 1);
+		return    (uintmax_t) time1 + (uintmax_t) (-1 - time0) + 1;
+	return -(double) ((uintmax_t) time0 + (uintmax_t) (-1 - time1) + 1);
 }
diff --git a/localtime.c b/localtime.c
index f90415e..7db8ceb 100644
--- a/localtime.c
+++ b/localtime.c
@@ -78,7 +78,7 @@ static const char	gmt[] = "GMT";
 #endif /* !defined TZDEFDST */
 
 struct ttinfo {				/* time type information */
-	long		tt_gmtoff;	/* UTC offset in seconds */
+	int_fast32_t	tt_gmtoff;	/* UTC offset in seconds */
 	int		tt_isdst;	/* used to set tm_isdst */
 	int		tt_abbrind;	/* abbreviation list index */
 	int		tt_ttisstd;	/* TRUE if transition is std time */
@@ -87,7 +87,7 @@ struct ttinfo {				/* time type information */
 
 struct lsinfo {				/* leap second information */
 	time_t		ls_trans;	/* transition time */
-	long		ls_corr;	/* correction to apply */
+	int_fast64_t	ls_corr;	/* correction to apply */
 };
 
 #define BIGGEST(a, b)	(((a) > (b)) ? (a) : (b))
@@ -120,7 +120,7 @@ struct rule {
 	int		r_day;		/* day number of rule */
 	int		r_week;		/* week number of rule */
 	int		r_mon;		/* month number of rule */
-	long		r_time;		/* transition time of rule */
+	int_fast32_t	r_time;		/* transition time of rule */
 };
 
 #define JULIAN_DAY		0	/* Jn - Julian day */
@@ -131,7 +131,7 @@ struct rule {
 ** Prototypes for static functions.
 */
 
-static long		detzcode(const char * codep);
+static int_fast32_t	detzcode(const char * codep);
 static time_t		detzcode64(const char * codep);
 static int		differ_by_repeat(time_t t1, time_t t0);
 static const char *	getzname(const char * strp) ATTRIBUTE_PURE;
@@ -139,40 +139,40 @@ static const char *	getqzname(const char * strp, const int delim)
   ATTRIBUTE_PURE;
 static const char *	getnum(const char * strp, int * nump, int min,
 				int max);
-static const char *	getsecs(const char * strp, long * secsp);
-static const char *	getoffset(const char * strp, long * offsetp);
+static const char *	getsecs(const char * strp, int_fast32_t * secsp);
+static const char *	getoffset(const char * strp, int_fast32_t * offsetp);
 static const char *	getrule(const char * strp, struct rule * rulep);
 static void		gmtload(struct state * sp);
-static struct tm *	gmtsub(const time_t * timep, long offset,
+static struct tm *	gmtsub(const time_t * timep, int_fast32_t offset,
 				struct tm * tmp);
-static struct tm *	localsub(const time_t * timep, long offset,
+static struct tm *	localsub(const time_t * timep, int_fast32_t offset,
 				struct tm * tmp);
 static int		increment_overflow(int * number, int delta);
 static int		leaps_thru_end_of(int y) ATTRIBUTE_PURE;
-static int		long_increment_overflow(long * number, int delta);
-static int		long_normalize_overflow(long * tensptr,
+static int		increment_overflow32(int_fast32_t * number, int delta);
+static int		normalize_overflow32(int_fast32_t * tensptr,
 				int * unitsptr, int base);
 static int		normalize_overflow(int * tensptr, int * unitsptr,
 				int base);
 static void		settzname(void);
 static time_t		time1(struct tm * tmp,
 				struct tm * (*funcp)(const time_t *,
-				long, struct tm *),
-				long offset);
+				int_fast32_t, struct tm *),
+				int_fast32_t offset);
 static time_t		time2(struct tm *tmp,
 				struct tm * (*funcp)(const time_t *,
-				long, struct tm*),
-				long offset, int * okayp);
+				int_fast32_t, struct tm*),
+				int_fast32_t offset, int * okayp);
 static time_t		time2sub(struct tm *tmp,
 				struct tm * (*funcp)(const time_t *,
-				long, struct tm*),
-				long offset, int * okayp, int do_norm_secs);
-static struct tm *	timesub(const time_t * timep, long offset,
+				int_fast32_t, struct tm*),
+				int_fast32_t offset, int * okayp, int do_norm_secs);
+static struct tm *	timesub(const time_t * timep, int_fast32_t offset,
 				const struct state * sp, struct tm * tmp);
 static int		tmcomp(const struct tm * atmp,
 				const struct tm * btmp);
 static time_t		transtime(time_t janfirst, int year,
-				  const struct rule * rulep, long offset)
+				  const struct rule * rulep, int_fast32_t offset)
   ATTRIBUTE_PURE;
 static int		typesequiv(const struct state * sp, int a, int b);
 static int		tzload(const char * name, struct state * sp,
@@ -224,13 +224,13 @@ int			daylight = 0;
 time_t			altzone = 0;
 #endif /* defined ALTZONE */
 
-static long
+static int_fast32_t
 detzcode(const char *const codep)
 {
-	register long	result;
-	register int	i;
+	register int_fast32_t	result;
+	register int		i;
 
-	result = (codep[0] & 0x80) ? ~0L : 0;
+	result = (codep[0] & 0x80) ? -1 : 0;
 	for (i = 0; i < 4; ++i)
 		result = (result << 8) | (codep[i] & 0xff);
 	return result;
@@ -732,7 +732,7 @@ getnum(register const char *strp, int *const nump, const int min, const int max)
 */
 
 static const char *
-getsecs(register const char *strp, long *const secsp)
+getsecs(register const char *strp, int_fast32_t *const secsp)
 {
 	int	num;
 
@@ -745,7 +745,7 @@ getsecs(register const char *strp, long *const secsp)
 	strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
 	if (strp == NULL)
 		return NULL;
-	*secsp = num * (long) SECSPERHOUR;
+	*secsp = num * (int_fast32_t) SECSPERHOUR;
 	if (*strp == ':') {
 		++strp;
 		strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
@@ -772,7 +772,7 @@ getsecs(register const char *strp, long *const secsp)
 */
 
 static const char *
-getoffset(register const char *strp, long *const offsetp)
+getoffset(register const char *strp, int_fast32_t *const offsetp)
 {
 	register int	neg = 0;
 
@@ -850,7 +850,7 @@ getrule(const char *strp, register struct rule *const rulep)
 
 static time_t
 transtime(const time_t janfirst, const int year,
-	  register const struct rule *const rulep, const long offset)
+	  register const struct rule *const rulep, const int_fast32_t offset)
 {
 	register int	leapyear;
 	register time_t	value;
@@ -948,8 +948,8 @@ tzparse(const char *name, register struct state *const sp,
 	const char *			dstname;
 	size_t				stdlen;
 	size_t				dstlen;
-	long				stdoffset;
-	long				dstoffset;
+	int_fast32_t			stdoffset;
+	int_fast32_t			dstoffset;
 	register time_t *		atp;
 	register unsigned char *	typep;
 	register char *			cp;
@@ -1067,12 +1067,12 @@ tzparse(const char *name, register struct state *const sp,
 				janfirst = newfirst;
 			}
 		} else {
-			register long	theirstdoffset;
-			register long	theirdstoffset;
-			register long	theiroffset;
-			register int	isdst;
-			register int	i;
-			register int	j;
+			register int_fast32_t	theirstdoffset;
+			register int_fast32_t	theirdstoffset;
+			register int_fast32_t	theiroffset;
+			register int		isdst;
+			register int		i;
+			register int		j;
 
 			if (*name != '\0')
 				return -1;
@@ -1265,7 +1265,8 @@ tzset(void)
 
 /*ARGSUSED*/
 static struct tm *
-localsub(const time_t *const timep, const long offset, struct tm *const tmp)
+localsub(const time_t *const timep, const int_fast32_t offset,
+	 struct tm *const tmp)
 {
 	register struct state *		sp;
 	register const struct ttinfo *	ttisp;
@@ -1370,7 +1371,8 @@ localtime_r(const time_t *const timep, struct tm *tmp)
 */
 
 static struct tm *
-gmtsub(const time_t *const timep, const long offset, struct tm *const tmp)
+gmtsub(const time_t *const timep, const int_fast32_t offset,
+       struct tm *const tmp)
 {
 	register struct tm *	result;
 
@@ -1424,7 +1426,7 @@ gmtime_r(const time_t *const timep, struct tm *tmp)
 #ifdef STD_INSPIRED
 
 struct tm *
-offtime(const time_t *const timep, const long offset)
+offtime(const time_t *const timep, const int_fast32_t offset)
 {
 	return gmtsub(timep, offset, &tm);
 }
@@ -1444,17 +1446,17 @@ leaps_thru_end_of(register const int y)
 }
 
 static struct tm *
-timesub(const time_t *const timep, const long offset,
+timesub(const time_t *const timep, const int_fast32_t offset,
 	register const struct state *const sp,
 	register struct tm *const tmp)
 {
 	register const struct lsinfo *	lp;
 	register time_t			tdays;
 	register int			idays;	/* unsigned would be so 2003 */
-	register long			rem;
+	register int_fast64_t		rem;
 	int				y;
 	register const int *		ip;
-	register long			corr;
+	register int_fast64_t		corr;
 	register int			hit;
 	register int			i;
 
@@ -1511,9 +1513,10 @@ timesub(const time_t *const timep, const long offset,
 		y = newy;
 	}
 	{
-		register long	seconds;
+		register int_fast32_t	seconds;
+		register time_t		half_second = 0.5;
 
-		seconds = tdays * SECSPERDAY + 0.5;
+		seconds = tdays * SECSPERDAY + half_second;
 		tdays = seconds / SECSPERDAY;
 		rem += seconds - tdays * SECSPERDAY;
 	}
@@ -1630,11 +1633,11 @@ increment_overflow(int *const ip, int j)
 }
 
 static int
-long_increment_overflow(long *const lp, int const m)
+increment_overflow32(int_fast32_t *const lp, int const m)
 {
-	register long const	l = *lp;
+	register int_fast32_t const	l = *lp;
 
-	if ((l >= 0) ? (m > LONG_MAX - l) : (m < LONG_MIN - l))
+	if ((l >= 0) ? (m > INT_FAST32_MAX - l) : (m < INT_FAST32_MIN - l))
 		return TRUE;
 	*lp += m;
 	return FALSE;
@@ -1653,7 +1656,8 @@ normalize_overflow(int *const tensptr, int *const unitsptr, const int base)
 }
 
 static int
-long_normalize_overflow(long *const tensptr, int *const unitsptr, const int base)
+normalize_overflow32(int_fast32_t *const tensptr, int *const unitsptr,
+		     const int base)
 {
 	register int	tensdelta;
 
@@ -1661,7 +1665,7 @@ long_normalize_overflow(long *const tensptr, int *const unitsptr, const int base
 		(*unitsptr / base) :
 		(-1 - (-1 - *unitsptr) / base);
 	*unitsptr -= tensdelta * base;
-	return long_increment_overflow(tensptr, tensdelta);
+	return increment_overflow32(tensptr, tensdelta);
 }
 
 static int
@@ -1681,8 +1685,8 @@ tmcomp(register const struct tm *const atmp,
 
 static time_t
 time2sub(struct tm *const tmp,
-	 struct tm *(*const funcp)(const time_t *, long, struct tm *),
-	 const long offset,
+	 struct tm *(*const funcp)(const time_t *, int_fast32_t, struct tm *),
+	 const int_fast32_t offset,
 	 int *const okayp,
 	 const int do_norm_secs)
 {
@@ -1690,10 +1694,10 @@ time2sub(struct tm *const tmp,
 	register int			dir;
 	register int			i, j;
 	register int			saved_seconds;
-	register long			li;
+	register int_fast32_t			li;
 	register time_t			lo;
 	register time_t			hi;
-	long				y;
+	int_fast32_t				y;
 	time_t				newt;
 	time_t				t;
 	struct tm			yourtm, mytm;
@@ -1710,16 +1714,16 @@ time2sub(struct tm *const tmp,
 	if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
 		return WRONG;
 	y = yourtm.tm_year;
-	if (long_normalize_overflow(&y, &yourtm.tm_mon, MONSPERYEAR))
+	if (normalize_overflow32(&y, &yourtm.tm_mon, MONSPERYEAR))
 		return WRONG;
 	/*
 	** Turn y into an actual year number for now.
 	** It is converted back to an offset from TM_YEAR_BASE later.
 	*/
-	if (long_increment_overflow(&y, TM_YEAR_BASE))
+	if (increment_overflow32(&y, TM_YEAR_BASE))
 		return WRONG;
 	while (yourtm.tm_mday <= 0) {
-		if (long_increment_overflow(&y, -1))
+		if (increment_overflow32(&y, -1))
 			return WRONG;
 		li = y + (1 < yourtm.tm_mon);
 		yourtm.tm_mday += year_lengths[isleap(li)];
@@ -1727,7 +1731,7 @@ time2sub(struct tm *const tmp,
 	while (yourtm.tm_mday > DAYSPERLYEAR) {
 		li = y + (1 < yourtm.tm_mon);
 		yourtm.tm_mday -= year_lengths[isleap(li)];
-		if (long_increment_overflow(&y, 1))
+		if (increment_overflow32(&y, 1))
 			return WRONG;
 	}
 	for ( ; ; ) {
@@ -1737,11 +1741,11 @@ time2sub(struct tm *const tmp,
 		yourtm.tm_mday -= i;
 		if (++yourtm.tm_mon >= MONSPERYEAR) {
 			yourtm.tm_mon = 0;
-			if (long_increment_overflow(&y, 1))
+			if (increment_overflow32(&y, 1))
 				return WRONG;
 		}
 	}
-	if (long_increment_overflow(&y, -TM_YEAR_BASE))
+	if (increment_overflow32(&y, -TM_YEAR_BASE))
 		return WRONG;
 	yourtm.tm_year = y;
 	if (yourtm.tm_year != y)
@@ -1864,8 +1868,8 @@ label:
 
 static time_t
 time2(struct tm * const	tmp,
-      struct tm * (*const funcp)(const time_t *, long, struct tm *),
-      const long offset,
+      struct tm * (*const funcp)(const time_t *, int_fast32_t, struct tm *),
+      const int_fast32_t offset,
       int *const okayp)
 {
 	time_t	t;
@@ -1881,8 +1885,8 @@ time2(struct tm * const	tmp,
 
 static time_t
 time1(struct tm *const tmp,
-      struct tm *(*const funcp) (const time_t *, long, struct tm *),
-      const long offset)
+      struct tm *(*const funcp) (const time_t *, int_fast32_t, struct tm *),
+      const int_fast32_t offset)
 {
 	register time_t			t;
 	register const struct state *	sp;
@@ -1981,7 +1985,7 @@ timegm(struct tm *const tmp)
 }
 
 time_t
-timeoff(struct tm *const tmp, const long offset)
+timeoff(struct tm *const tmp, const int_fast32_t offset)
 {
 	if (tmp != NULL)
 		tmp->tm_isdst = 0;
@@ -1997,7 +2001,7 @@ timeoff(struct tm *const tmp, const long offset)
 ** previous versions of the CMUCS runtime library.
 */
 
-long
+int_fast32_t
 gtime(struct tm *const tmp)
 {
 	const time_t	t = mktime(tmp);
@@ -2023,7 +2027,7 @@ gtime(struct tm *const tmp)
 ** when exchanging timestamps with POSIX conforming systems.
 */
 
-static long
+static int_fast64_t
 leapcorr(time_t *timep)
 {
 	register struct state *		sp;
diff --git a/private.h b/private.h
index 05ddba0..a31a26e 100644
--- a/private.h
+++ b/private.h
@@ -124,19 +124,65 @@
 #include "stdint.h"
 #endif /* !HAVE_STDINT_H */
 
+#ifndef HAVE_INTTYPES_H
+# define HAVE_INTTYPES_H HAVE_STDINT_H
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+
 #ifndef INT_FAST64_MAX
 /* Pre-C99 GCC compilers define __LONG_LONG_MAX__ instead of LLONG_MAX.  */
 #if defined LLONG_MAX || defined __LONG_LONG_MAX__
 typedef long long	int_fast64_t;
+# ifdef LLONG_MAX
+#  define INT_FAST64_MIN LLONG_MIN
+#  define INT_FAST64_MAX LLONG_MAX
+# else
+#  define INT_FAST64_MIN __LONG_LONG_MIN__
+#  define INT_FAST64_MAX __LONG_LONG_MAX__
+# endif
+# define SCNdFAST64 "lld"
 #else /* ! (defined LLONG_MAX || defined __LONG_LONG_MAX__) */
 #if (LONG_MAX >> 31) < 0xffffffff
 Please use a compiler that supports a 64-bit integer type (or wider);
 you may need to compile with "-DHAVE_STDINT_H".
 #endif /* (LONG_MAX >> 31) < 0xffffffff */
 typedef long		int_fast64_t;
+# define INT_FAST64_MIN LONG_MIN
+# define INT_FAST64_MAX LONG_MAX
+# define SCNdFAST64 "ld"
 #endif /* ! (defined LLONG_MAX || defined __LONG_LONG_MAX__) */
 #endif /* !defined INT_FAST64_MAX */
 
+#ifndef INT_FAST32_MAX
+# if INT_MAX >> 31 == 0
+typedef long int_fast32_t;
+# else
+typedef int int_fast32_t;
+# endif
+#endif
+
+#ifndef INTMAX_MAX
+# if defined LLONG_MAX || defined __LONG_LONG_MAX__
+typedef long long intmax_t;
+#  define PRIdMAX "lld"
+# else
+typedef long intmax_t;
+#  define PRIdMAX "ld"
+# endif
+#endif
+
+#ifndef UINTMAX_MAX
+# if defined ULLONG_MAX || defined __LONG_LONG_MAX__
+typedef unsigned long long uintmax_t;
+#  define PRIuMAX "llu"
+# else
+typedef unsigned long uintmax_t;
+#  define PRIuMAX "lu"
+# endif
+#endif
+
 #ifndef INT32_MAX
 #define INT32_MAX 0x7fffffff
 #endif /* !defined INT32_MAX */
@@ -144,12 +190,22 @@ typedef long		int_fast64_t;
 #define INT32_MIN (-1 - INT32_MAX)
 #endif /* !defined INT32_MIN */
 
-#if 2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__)
+#if 2 < __GNUC__ + (96 <= __GNUC_MINOR__)
+# define ATTRIBUTE_CONST __attribute__ ((const))
 # define ATTRIBUTE_PURE __attribute__ ((__pure__))
 #else
+# define ATTRIBUTE_CONST /* empty */
 # define ATTRIBUTE_PURE /* empty */
 #endif
 
+#if !defined _Noreturn && __STDC_VERSION__ < 201112
+# if 2 < __GNUC__ + (8 <= __GNUC_MINOR__)
+#  define _Noreturn __attribute__ ((__noreturn__))
+# else
+#  define _Noreturn
+# endif
+#endif
+
 #if __STDC_VERSION__ < 199901 && !defined restrict
 # define restrict /* empty */
 #endif
diff --git a/scheck.c b/scheck.c
index ed60980..8bd01a8 100644
--- a/scheck.c
+++ b/scheck.c
@@ -25,26 +25,35 @@ scheck(const char *const string, const char *const format)
 		return result;
 	fp = format;
 	tp = fbuf;
+
+	/*
+	** Copy directives, suppressing each conversion that is not
+	** already suppressed.  Scansets containing '%' are not
+	** supported; e.g., the conversion specification "%[%]" is not
+	** supported.  Also, multibyte characters containing a
+	** non-leading '%' byte are not supported.
+	*/
 	while ((*tp++ = c = *fp++) != '\0') {
 		if (c != '%')
 			continue;
-		if (*fp == '%') {
-			*tp++ = *fp++;
-			continue;
+		if (is_digit(*fp)) {
+			char const *f = fp;
+			char *t = tp;
+			do {
+				*t++ = c = *f++;
+			} while (is_digit(c));
+			if (c == '$') {
+				fp = f;
+				tp = t;
+			}
 		}
 		*tp++ = '*';
 		if (*fp == '*')
 			++fp;
-		while (is_digit(*fp))
-			*tp++ = *fp++;
-		if (*fp == 'l' || *fp == 'h')
-			*tp++ = *fp++;
-		else if (*fp == '[')
-			do *tp++ = *fp++;
-				while (*fp != '\0' && *fp != ']');
 		if ((*tp++ = *fp++) == '\0')
 			break;
 	}
+
 	*(tp - 1) = '%';
 	*tp++ = 'c';
 	*tp = '\0';
diff --git a/strftime.c b/strftime.c
index 2c3cef8..821ce7f 100644
--- a/strftime.c
+++ b/strftime.c
@@ -317,10 +317,10 @@ label:
 					tm = *t;
 					mkt = mktime(&tm);
 					if (TYPE_SIGNED(time_t))
-						(void) sprintf(buf, "%ld",
-							(long) mkt);
-					else	(void) sprintf(buf, "%lu",
-							(unsigned long) mkt);
+						(void) sprintf(buf, "%"PRIdMAX,
+							(intmax_t) mkt);
+					else	(void) sprintf(buf, "%"PRIuMAX,
+							(uintmax_t) mkt);
 					pt = _add(buf, pt, ptlim);
 				}
 				continue;
diff --git a/tzfile.h b/tzfile.h
index 0f6c687..d04fe04 100644
--- a/tzfile.h
+++ b/tzfile.h
@@ -122,7 +122,7 @@ struct tzhead {
 #define DAYSPERNYEAR	365
 #define DAYSPERLYEAR	366
 #define SECSPERHOUR	(SECSPERMIN * MINSPERHOUR)
-#define SECSPERDAY	((long) SECSPERHOUR * HOURSPERDAY)
+#define SECSPERDAY	((int_fast32_t) SECSPERHOUR * HOURSPERDAY)
 #define MONSPERYEAR	12
 
 #define TM_SUNDAY	0
diff --git a/zdump.c b/zdump.c
index 8118091..be0a496 100644
--- a/zdump.c
+++ b/zdump.c
@@ -30,6 +30,47 @@
 #define isascii(x) 1
 #endif /* !defined isascii */
 
+/*
+** Substitutes for pre-C99 compilers.
+** Much of this section of code is stolen from private.h.
+*/
+
+#ifndef HAVE_STDINT_H
+# define HAVE_STDINT_H \
+    (199901 <= __STDC_VERSION__ || 2 < (__GLIBC__ + (0 < __GLIBC_MINOR__)))
+#endif
+#if HAVE_STDINT_H
+# include "stdint.h"
+#endif
+#ifndef HAVE_INTTYPES_H
+# define HAVE_INTTYPES_H HAVE_STDINT_H
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+
+#ifndef INT_FAST32_MAX
+# if INT_MAX >> 31 == 0
+typedef long int_fast32_t;
+# else
+typedef int int_fast32_t;
+# endif
+#endif
+
+#ifndef INTMAX_MAX
+# if defined LLONG_MAX || defined __LONG_LONG_MAX__
+typedef long long intmax_t;
+#  define PRIdMAX "lld"
+# else
+typedef long intmax_t;
+#  define PRIdMAX "ld"
+# endif
+#endif
+#ifndef SCNdMAX
+# define SCNdMAX PRIdMAX
+#endif
+
+
 #ifndef ZDUMP_LO_YEAR
 #define ZDUMP_LO_YEAR	(-500)
 #endif /* !defined ZDUMP_LO_YEAR */
@@ -97,7 +138,7 @@
 #define isleap_sum(a, b)	isleap((a) % 400 + (b) % 400)
 #endif /* !defined isleap_sum */
 
-#define SECSPERDAY	((long) SECSPERHOUR * HOURSPERDAY)
+#define SECSPERDAY	((int_fast32_t) SECSPERHOUR * HOURSPERDAY)
 #define SECSPERNYEAR	(SECSPERDAY * DAYSPERNYEAR)
 #define SECSPERLYEAR	(SECSPERNYEAR + SECSPERDAY)
 
@@ -179,13 +220,13 @@ static int	warned;
 
 static char *	abbr(struct tm * tmp);
 static void	abbrok(const char * abbrp, const char * zone);
-static long	delta(struct tm * newp, struct tm * oldp) ATTRIBUTE_PURE;
+static intmax_t	delta(struct tm * newp, struct tm * oldp) ATTRIBUTE_PURE;
 static void	dumptime(const struct tm * tmp);
 static time_t	hunt(char * name, time_t lot, time_t	hit);
 static void	checkabsolutes(void);
 static void	show(char * zone, time_t t, int v);
 static const char *	tformat(void);
-static time_t	yeartot(long y) ATTRIBUTE_PURE;
+static time_t	yeartot(intmax_t y) ATTRIBUTE_PURE;
 
 #ifndef TYPECHECK
 #define my_localtime	localtime
@@ -324,15 +365,15 @@ main(int argc, char *argv[])
  arg_processing_done:;
 
 	if (vflag | Vflag) {
-		long	lo;
-		long	hi;
-		char	dummy;
-		register long cutloyear = ZDUMP_LO_YEAR;
-		register long cuthiyear = ZDUMP_HI_YEAR;
+		intmax_t	lo;
+		intmax_t	hi;
+		char		dummy;
+		register intmax_t cutloyear = ZDUMP_LO_YEAR;
+		register intmax_t cuthiyear = ZDUMP_HI_YEAR;
 		if (cutarg != NULL) {
-			if (sscanf(cutarg, "%ld%c", &hi, &dummy) == 1) {
+			if (sscanf(cutarg, "%"SCNdMAX"%c", &hi, &dummy) == 1) {
 				cuthiyear = hi;
-			} else if (sscanf(cutarg, "%ld,%ld%c",
+			} else if (sscanf(cutarg, "%"SCNdMAX",%"SCNdMAX"%c",
 				&lo, &hi, &dummy) == 2) {
 					cutloyear = lo;
 					cuthiyear = hi;
@@ -348,13 +389,13 @@ main(int argc, char *argv[])
 			cuthitime = yeartot(cuthiyear);
 		}
 		if (cuttimes != NULL) {
-			if (sscanf(cuttimes, "%ld%c", &hi, &dummy) == 1) {
+			if (sscanf(cuttimes, "%"SCNdMAX"%c", &hi, &dummy) == 1) {
 				if (hi < cuthitime) {
 					if (hi < absolute_min_time)
 						hi = absolute_min_time;
 					cuthitime = hi;
 				}
-			} else if (sscanf(cuttimes, "%ld,%ld%c",
+			} else if (sscanf(cuttimes, "%"SCNdMAX",%"SCNdMAX"%c",
 					  &lo, &hi, &dummy) == 2) {
 				if (cutlotime < lo) {
 					if (absolute_max_time < lo)
@@ -475,11 +516,11 @@ _("%s: use of -v on system with floating time_t other than float or double\n"),
 }
 
 static time_t
-yeartot(const long y)
+yeartot(const intmax_t y)
 {
-	register long	myy;
-	register long	seconds;
-	register time_t	t;
+	register intmax_t	myy;
+	register int_fast32_t	seconds;
+	register time_t		t;
 
 	myy = EPOCH_YEAR;
 	t = 0;
@@ -509,7 +550,6 @@ static time_t
 hunt(char *name, time_t lot, time_t hit)
 {
 	time_t			t;
-	long			diff;
 	struct tm		lotm;
 	register struct tm *	lotmp;
 	struct tm		tm;
@@ -522,7 +562,7 @@ hunt(char *name, time_t lot, time_t hit)
 		(void) strncpy(loab, abbr(&lotm), (sizeof loab) - 1);
 	}
 	for ( ; ; ) {
-		diff = (long) (hit - lot);
+		time_t diff = hit - lot;
 		if (diff < 2)
 			break;
 		t = lot;
@@ -552,11 +592,11 @@ hunt(char *name, time_t lot, time_t hit)
 ** Thanks to Paul Eggert for logic used in delta.
 */
 
-static long
+static intmax_t
 delta(struct tm * newp, struct tm *oldp)
 {
-	register long	result;
-	register int	tmy;
+	register intmax_t	result;
+	register int		tmy;
 
 	if (newp->tm_year < oldp->tm_year)
 		return -delta(oldp, newp);
@@ -632,12 +672,18 @@ tformat(void)
 		return "%g";
 	}
 	if (0 > (time_t) -1) {		/* signed */
+		if (sizeof (time_t) == sizeof (intmax_t))
+			return "%"PRIdMAX;
 		if (sizeof (time_t) > sizeof (long))
 			return "%lld";
 		if (sizeof (time_t) > sizeof (int))
 			return "%ld";
 		return "%d";
 	}
+#ifdef PRIuMAX
+	if (sizeof (time_t) == sizeof (uintmax_t))
+		return "%"PRIuMAX;
+#endif
 	if (sizeof (time_t) > sizeof (unsigned long))
 		return "%llu";
 	if (sizeof (time_t) > sizeof (unsigned int))
diff --git a/zic.c b/zic.c
index f277edc..1715c4a 100644
--- a/zic.c
+++ b/zic.c
@@ -11,6 +11,9 @@
 #define	ZIC_VERSION	'2'
 
 typedef int_fast64_t	zic_t;
+#define ZIC_MIN INT_FAST64_MIN
+#define ZIC_MAX INT_FAST64_MAX
+#define SCNdZIC SCNdFAST64
 
 #ifndef ZIC_MAX_ABBR_LEN_WO_WARN
 #define ZIC_MAX_ABBR_LEN_WO_WARN	6
@@ -38,9 +41,6 @@ typedef int_fast64_t	zic_t;
 #define isascii(x) 1
 #endif
 
-#define OFFSET_STRLEN_MAXIMUM	(7 + INT_STRLEN_MAXIMUM(long))
-#define RULE_STRLEN_MAXIMUM	8	/* "Mdd.dd.d" */
-
 #define end(cp)	(strchr((cp), '\0'))
 
 struct rule {
@@ -48,8 +48,8 @@ struct rule {
 	int		r_linenum;
 	const char *	r_name;
 
-	int		r_loyear;	/* for example, 1986 */
-	int		r_hiyear;	/* for example, 1986 */
+	zic_t		r_loyear;	/* for example, 1986 */
+	zic_t		r_hiyear;	/* for example, 1986 */
 	const char *	r_yrtype;
 	int		r_lowasnum;
 	int		r_hiwasnum;
@@ -60,12 +60,12 @@ struct rule {
 	int		r_dayofmonth;
 	int		r_wday;
 
-	long		r_tod;		/* time from midnight */
+	zic_t		r_tod;		/* time from midnight */
 	int		r_todisstd;	/* above is standard time if TRUE */
 					/* or wall clock time if FALSE */
 	int		r_todisgmt;	/* above is GMT if TRUE */
 					/* or local time if FALSE */
-	long		r_stdoff;	/* offset from standard time */
+	zic_t		r_stdoff;	/* offset from standard time */
 	const char *	r_abbrvar;	/* variable part of abbreviation */
 
 	int		r_todo;		/* a rule to do (used in outzone) */
@@ -85,11 +85,11 @@ struct zone {
 	int		z_linenum;
 
 	const char *	z_name;
-	long		z_gmtoff;
+	zic_t		z_gmtoff;
 	const char *	z_rule;
 	const char *	z_format;
 
-	long		z_stdoff;
+	zic_t		z_stdoff;
 
 	struct rule *	z_rules;
 	int		z_nrules;
@@ -105,16 +105,15 @@ extern char *	optarg;
 extern int	optind;
 
 static void	addtt(zic_t starttime, int type);
-static int	addtype(long gmtoff, const char * abbr, int isdst,
+static int	addtype(zic_t gmtoff, const char * abbr, int isdst,
 				int ttisstd, int ttisgmt);
 static void	leapadd(zic_t t, int positive, int rolling, int count);
 static void	adjleap(void);
 static void	associate(void);
 static void	dolink(const char * fromfield, const char * tofield);
-static long	eitol(int i);
 static char **	getfields(char * buf);
-static long	gethms(const char * string, const char * errstrng,
-			int signable);
+static zic_t	gethms(const char * string, const char * errstrng,
+		       int signable);
 static void	infile(const char * filename);
 static void	inleap(char ** fields, int nfields);
 static void	inlink(char ** fields, int nfields);
@@ -126,14 +125,14 @@ static int	itsdir(const char * name);
 static int	lowerit(int c);
 static int	mkdirs(char * filename);
 static void	newabbr(const char * abbr);
-static long	oadd(long t1, long t2);
+static zic_t	oadd(zic_t t1, zic_t t2);
 static void	outzone(const struct zone * zp, int ntzones);
-static zic_t	rpytime(const struct rule * rp, int wantedy);
+static zic_t	rpytime(const struct rule * rp, zic_t wantedy);
 static void	rulesub(struct rule * rp,
 			const char * loyearp, const char * hiyearp,
 			const char * typep, const char * monthp,
 			const char * dayp, const char * timep);
-static zic_t	tadd(zic_t t1, long t2);
+static zic_t	tadd(zic_t t1, zic_t t2);
 static int	yearistype(int year, const char * type);
 
 static int		charcnt;
@@ -141,13 +140,13 @@ static int		errors;
 static const char *	filename;
 static int		leapcnt;
 static int		leapseen;
-static int		leapminyear;
-static int		leapmaxyear;
+static zic_t		leapminyear;
+static zic_t		leapmaxyear;
 static int		linenum;
 static int		max_abbrvar_len;
 static int		max_format_len;
-static int		max_year;
-static int		min_year;
+static zic_t		max_year;
+static zic_t		min_year;
 static int		noise;
 static const char *	rfilename;
 static int		rlinenum;
@@ -338,14 +337,14 @@ static struct attype {
 	zic_t		at;
 	unsigned char	type;
 }			attypes[TZ_MAX_TIMES];
-static long		gmtoffs[TZ_MAX_TYPES];
+static zic_t		gmtoffs[TZ_MAX_TYPES];
 static char		isdsts[TZ_MAX_TYPES];
 static unsigned char	abbrinds[TZ_MAX_TYPES];
 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 zic_t		corr[TZ_MAX_LEAPS];
 static char		roll[TZ_MAX_LEAPS];
 
 /*
@@ -419,7 +418,7 @@ warning(const char *const string)
 	--errors;
 }
 
-static void
+static _Noreturn void
 usage(FILE *stream, int status)
 {
 	(void) fprintf(stream, _("%s: usage is %s \
@@ -444,9 +443,9 @@ main(int argc, char **argv)
 	register int	j;
 	register int	c;
 
-#ifdef unix
+#ifdef S_IWGRP
 	(void) umask(umask(S_IWGRP | S_IWOTH) | (S_IWGRP | S_IWOTH));
-#endif /* defined unix */
+#endif
 #if HAVE_GETTEXT
 	(void) setlocale(LC_ALL, "");
 #ifdef TZ_DOMAINDIR
@@ -854,10 +853,10 @@ _("%s: panic: Invalid l_value %d\n"),
 ** Call error with errstring and return zero on errors.
 */
 
-static long
+static zic_t
 gethms(const char *string, const char *const errstring, const int signable)
 {
-	long	hh;
+	zic_t	hh;
 	int	mm, ss, sign;
 
 	if (string == NULL || *string == '\0')
@@ -868,11 +867,11 @@ gethms(const char *string, const char *const errstring, const int signable)
 		sign = -1;
 		++string;
 	} else	sign = 1;
-	if (sscanf(string, scheck(string, "%ld"), &hh) == 1)
+	if (sscanf(string, scheck(string, "%"SCNdZIC), &hh) == 1)
 		mm = ss = 0;
-	else if (sscanf(string, scheck(string, "%ld:%d"), &hh, &mm) == 2)
+	else if (sscanf(string, scheck(string, "%"SCNdZIC":%d"), &hh, &mm) == 2)
 		ss = 0;
-	else if (sscanf(string, scheck(string, "%ld:%d:%d"),
+	else if (sscanf(string, scheck(string, "%"SCNdZIC":%d:%d"),
 		&hh, &mm, &ss) != 3) {
 			error(errstring);
 			return 0;
@@ -883,7 +882,7 @@ gethms(const char *string, const char *const errstring, const int signable)
 			error(errstring);
 			return 0;
 	}
-	if (LONG_MAX / SECSPERHOUR < hh) {
+	if (ZIC_MAX / SECSPERHOUR < hh) {
 		error(_("time overflow"));
 		return 0;
 	}
@@ -892,8 +891,8 @@ gethms(const char *string, const char *const errstring, const int signable)
 	if (noise && (hh > HOURSPERDAY ||
 		(hh == HOURSPERDAY && (mm != 0 || ss != 0))))
 warning(_("values over 24 hours not handled by pre-2007 versions of zic"));
-	return oadd(eitol(sign) * hh * eitol(SECSPERHOUR),
-		    eitol(sign) * (eitol(mm) * eitol(SECSPERMIN) + eitol(ss)));
+	return oadd(sign * hh * SECSPERHOUR,
+		    sign * (mm * SECSPERMIN + ss));
 }
 
 static void
@@ -1058,8 +1057,9 @@ inleap(register char ** const fields, const int nfields)
 	register const char *		cp;
 	register const struct lookup *	lp;
 	register int			i, j;
-	int				year, month, day;
-	long				dayoff, tod;
+	zic_t				year;
+	int				month, day;
+	zic_t				dayoff, tod;
 	zic_t				t;
 
 	if (nfields != LEAP_FIELDS) {
@@ -1068,7 +1068,7 @@ inleap(register char ** const fields, const int nfields)
 	}
 	dayoff = 0;
 	cp = fields[LP_YEAR];
-	if (sscanf(cp, scheck(cp, "%d"), &year) != 1) {
+	if (sscanf(cp, scheck(cp, "%"SCNdZIC), &year) != 1) {
 		/*
 		** Leapin' Lizards!
 		*/
@@ -1089,7 +1089,7 @@ inleap(register char ** const fields, const int nfields)
 			--j;
 			i = -len_years[isleap(j)];
 		}
-		dayoff = oadd(dayoff, eitol(i));
+		dayoff = oadd(dayoff, i);
 	}
 	if ((lp = byword(fields[LP_MONTH], mon_names)) == NULL) {
 		error(_("invalid month name"));
@@ -1099,7 +1099,7 @@ inleap(register char ** const fields, const int nfields)
 	j = TM_JANUARY;
 	while (j != month) {
 		i = len_months[isleap(year)][j];
-		dayoff = oadd(dayoff, eitol(i));
+		dayoff = oadd(dayoff, i);
 		++j;
 	}
 	cp = fields[LP_DAY];
@@ -1108,7 +1108,7 @@ inleap(register char ** const fields, const int nfields)
 			error(_("invalid day of month"));
 			return;
 	}
-	dayoff = oadd(dayoff, eitol(day - 1));
+	dayoff = oadd(dayoff, day - 1);
 	if (dayoff < 0 && !TYPE_SIGNED(zic_t)) {
 		error(_("time before zero"));
 		return;
@@ -1233,17 +1233,17 @@ rulesub(register struct rule *const rp,
 	rp->r_lowasnum = lp == NULL;
 	if (!rp->r_lowasnum) switch ((int) lp->l_value) {
 		case YR_MINIMUM:
-			rp->r_loyear = INT_MIN;
+			rp->r_loyear = ZIC_MIN;
 			break;
 		case YR_MAXIMUM:
-			rp->r_loyear = INT_MAX;
+			rp->r_loyear = ZIC_MAX;
 			break;
 		default:	/* "cannot happen" */
 			(void) fprintf(stderr,
 				_("%s: panic: Invalid l_value %d\n"),
 				progname, lp->l_value);
 			exit(EXIT_FAILURE);
-	} else if (sscanf(cp, scheck(cp, "%d"), &rp->r_loyear) != 1) {
+	} else if (sscanf(cp, scheck(cp, "%"SCNdZIC), &rp->r_loyear) != 1) {
 		error(_("invalid starting year"));
 		return;
 	}
@@ -1252,10 +1252,10 @@ rulesub(register struct rule *const rp,
 	rp->r_hiwasnum = lp == NULL;
 	if (!rp->r_hiwasnum) switch ((int) lp->l_value) {
 		case YR_MINIMUM:
-			rp->r_hiyear = INT_MIN;
+			rp->r_hiyear = ZIC_MIN;
 			break;
 		case YR_MAXIMUM:
-			rp->r_hiyear = INT_MAX;
+			rp->r_hiyear = ZIC_MAX;
 			break;
 		case YR_ONLY:
 			rp->r_hiyear = rp->r_loyear;
@@ -1265,7 +1265,7 @@ rulesub(register struct rule *const rp,
 				_("%s: panic: Invalid l_value %d\n"),
 				progname, lp->l_value);
 			exit(EXIT_FAILURE);
-	} else if (sscanf(cp, scheck(cp, "%d"), &rp->r_hiyear) != 1) {
+	} else if (sscanf(cp, scheck(cp, "%"SCNdZIC), &rp->r_hiyear) != 1) {
 		error(_("invalid ending year"));
 		return;
 	}
@@ -1330,7 +1330,7 @@ rulesub(register struct rule *const rp,
 }
 
 static void
-convert(const long val, char *const buf)
+convert(const int_fast32_t val, char *const buf)
 {
 	register int	i;
 	register int	shift;
@@ -1352,7 +1352,7 @@ convert64(const zic_t val, char *const buf)
 }
 
 static void
-puttzcode(const long val, FILE *const fp)
+puttzcode(const int_fast32_t val, FILE *const fp)
 {
 	char	buf[4];
 
@@ -1639,12 +1639,12 @@ writezone(const char *const name, const char *const string)
 		tzh = tzh0;
 		(void) strncpy(tzh.tzh_magic, TZ_MAGIC, sizeof tzh.tzh_magic);
 		tzh.tzh_version[0] = ZIC_VERSION;
-		convert(eitol(thistypecnt), tzh.tzh_ttisgmtcnt);
-		convert(eitol(thistypecnt), tzh.tzh_ttisstdcnt);
-		convert(eitol(thisleapcnt), tzh.tzh_leapcnt);
-		convert(eitol(thistimecnt), tzh.tzh_timecnt);
-		convert(eitol(thistypecnt), tzh.tzh_typecnt);
-		convert(eitol(thischarcnt), tzh.tzh_charcnt);
+		convert(thistypecnt, tzh.tzh_ttisgmtcnt);
+		convert(thistypecnt, tzh.tzh_ttisstdcnt);
+		convert(thisleapcnt, tzh.tzh_leapcnt);
+		convert(thistimecnt, tzh.tzh_timecnt);
+		convert(thistypecnt, tzh.tzh_typecnt);
+		convert(thischarcnt, tzh.tzh_charcnt);
 		DO(tzh_magic);
 		DO(tzh_version);
 		DO(tzh_reserved);
@@ -1657,7 +1657,7 @@ writezone(const char *const name, const char *const string)
 #undef DO
 		for (i = thistimei; i < thistimelim; ++i)
 			if (pass == 1)
-				puttzcode((long) ats[i], fp);
+				puttzcode(ats[i], fp);
 			else	puttzcode64(ats[i], fp);
 		for (i = thistimei; i < thistimelim; ++i) {
 			unsigned char	uc;
@@ -1751,7 +1751,7 @@ doabbr(char *const abbr, const char *const format, const char *const letters,
 }
 
 static void
-updateminmax(const int x)
+updateminmax(const zic_t x)
 {
 	if (min_year > x)
 		min_year = x;
@@ -1760,7 +1760,7 @@ updateminmax(const int x)
 }
 
 static int
-stringoffset(char *result, long offset)
+stringoffset(char *result, zic_t offset)
 {
 	register int	hours;
 	register int	minutes;
@@ -1790,10 +1790,10 @@ stringoffset(char *result, long offset)
 }
 
 static int
-stringrule(char *result, const struct rule *const rp, const long dstoff,
-	   const long gmtoff)
+stringrule(char *result, const struct rule *const rp, const zic_t dstoff,
+	   const zic_t gmtoff)
 {
-	register long	tod;
+	register zic_t	tod;
 
 	result = end(result);
 	if (rp->r_dycode == DC_DOM) {
@@ -1856,7 +1856,7 @@ stringzone(char *result, const struct zone *const zpfirst, const int zonecount)
 	stdrp = dstrp = NULL;
 	for (i = 0; i < zp->z_nrules; ++i) {
 		rp = &zp->z_rules[i];
-		if (rp->r_hiwasnum || rp->r_hiyear != INT_MAX)
+		if (rp->r_hiwasnum || rp->r_hiyear != ZIC_MAX)
 			continue;
 		if (rp->r_yrtype != NULL)
 			continue;
@@ -1931,10 +1931,10 @@ outzone(const struct zone * const zpfirst, const int zonecount)
 	register int			i, j;
 	register int			usestart, useuntil;
 	register zic_t			starttime, untiltime;
-	register long			gmtoff;
-	register long			stdoff;
-	register int			year;
-	register long			startoff;
+	register zic_t			gmtoff;
+	register zic_t			stdoff;
+	register zic_t			year;
+	register zic_t			startoff;
 	register int			startttisstd;
 	register int			startttisgmt;
 	register int			type;
@@ -1968,7 +1968,7 @@ outzone(const struct zone * const zpfirst, const int zonecount)
 	min_year = max_year = EPOCH_YEAR;
 	if (leapseen) {
 		updateminmax(leapminyear);
-		updateminmax(leapmaxyear + (leapmaxyear < INT_MAX));
+		updateminmax(leapmaxyear + (leapmaxyear < ZIC_MAX));
 	}
 	/*
 	** Reserve type 0.
@@ -2003,12 +2003,12 @@ wp = ecpyalloc(_("no POSIX environment variable for zone"));
 		free(wp);
 	}
 	if (envvar[0] == '\0') {
-		if (min_year >= INT_MIN + YEARSPERREPEAT)
+		if (min_year >= ZIC_MIN + YEARSPERREPEAT)
 			min_year -= YEARSPERREPEAT;
-		else	min_year = INT_MIN;
-		if (max_year <= INT_MAX - YEARSPERREPEAT)
+		else	min_year = ZIC_MIN;
+		if (max_year <= ZIC_MAX - YEARSPERREPEAT)
 			max_year += YEARSPERREPEAT;
-		else	max_year = INT_MAX;
+		else	max_year = ZIC_MAX;
 		/*
 		** Regardless of any of the above,
 		** for a "proDSTic" zone which specifies that its rules
@@ -2074,7 +2074,7 @@ wp = ecpyalloc(_("no POSIX environment variable for zone"));
 			for ( ; ; ) {
 				register int	k;
 				register zic_t	jtime, ktime;
-				register long	offset;
+				register zic_t	offset;
 
 				INITIALIZE(ktime);
 				if (useuntil) {
@@ -2216,7 +2216,7 @@ addtt(const zic_t starttime, int type)
 }
 
 static int
-addtype(const long gmtoff, const char *const abbr, const int isdst,
+addtype(const zic_t gmtoff, const char *const abbr, const int isdst,
 	const int ttisstd, const int ttisgmt)
 {
 	register int	i, j;
@@ -2295,7 +2295,7 @@ leapadd(const zic_t t, const int positive, const int rolling, int count)
 			roll[j] = roll[j - 1];
 		}
 		trans[i] = t;
-		corr[i] = positive ? 1L : eitol(-count);
+		corr[i] = positive ? 1 : -count;
 		roll[i] = rolling;
 		++leapcnt;
 	} while (positive && --count != 0);
@@ -2305,7 +2305,7 @@ static void
 adjleap(void)
 {
 	register int	i;
-	register long	last = 0;
+	register zic_t	last = 0;
 
 	/*
 	** propagate leap seconds forward
@@ -2439,10 +2439,10 @@ getfields(register char *cp)
 	return array;
 }
 
-static ATTRIBUTE_PURE long
-oadd(const long t1, const long t2)
+static ATTRIBUTE_PURE zic_t
+oadd(const zic_t t1, const zic_t t2)
 {
-	if (t1 < 0 ? t2 < LONG_MIN - t1 : LONG_MAX - t1 < t2) {
+	if (t1 < 0 ? t2 < ZIC_MIN - t1 : ZIC_MAX - t1 < t2) {
 		error(_("time overflow"));
 		exit(EXIT_FAILURE);
 	}
@@ -2450,7 +2450,7 @@ oadd(const long t1, const long t2)
 }
 
 static ATTRIBUTE_PURE zic_t
-tadd(const zic_t t1, const long t2)
+tadd(const zic_t t1, const zic_t t2)
 {
 	if (t1 == max_time && t2 > 0)
 		return max_time;
@@ -2469,15 +2469,15 @@ tadd(const zic_t t1, const long t2)
 */
 
 static zic_t
-rpytime(register const struct rule *const rp, register const int wantedy)
+rpytime(register const struct rule *const rp, register const zic_t wantedy)
 {
-	register int	y, m, i;
-	register long	dayoff;			/* with a nod to Margaret O. */
-	register zic_t	t;
+	register int	m, i;
+	register zic_t	dayoff;			/* with a nod to Margaret O. */
+	register zic_t	t, y;
 
-	if (wantedy == INT_MIN)
+	if (wantedy == ZIC_MIN)
 		return min_time;
-	if (wantedy == INT_MAX)
+	if (wantedy == ZIC_MAX)
 		return max_time;
 	dayoff = 0;
 	m = TM_JANUARY;
@@ -2490,11 +2490,11 @@ rpytime(register const struct rule *const rp, register const int wantedy)
 			--y;
 			i = -len_years[isleap(y)];
 		}
-		dayoff = oadd(dayoff, eitol(i));
+		dayoff = oadd(dayoff, i);
 	}
 	while (m != rp->r_month) {
 		i = len_months[isleap(y)][m];
-		dayoff = oadd(dayoff, eitol(i));
+		dayoff = oadd(dayoff, i);
 		++m;
 	}
 	i = rp->r_dayofmonth;
@@ -2507,12 +2507,12 @@ rpytime(register const struct rule *const rp, register const int wantedy)
 		}
 	}
 	--i;
-	dayoff = oadd(dayoff, eitol(i));
+	dayoff = oadd(dayoff, i);
 	if (rp->r_dycode == DC_DOWGEQ || rp->r_dycode == DC_DOWLEQ) {
-		register long	wday;
+		register zic_t	wday;
 
-#define LDAYSPERWEEK	((long) DAYSPERWEEK)
-		wday = eitol(EPOCH_WDAY);
+#define LDAYSPERWEEK	((zic_t) DAYSPERWEEK)
+		wday = EPOCH_WDAY;
 		/*
 		** Don't trust mod of negative numbers.
 		*/
@@ -2523,7 +2523,7 @@ rpytime(register const struct rule *const rp, register const int wantedy)
 			if (wday < 0)
 				wday += LDAYSPERWEEK;
 		}
-		while (wday != eitol(rp->r_wday))
+		while (wday != rp->r_wday)
 			if (rp->r_dycode == DC_DOWGEQ) {
 				dayoff = oadd(dayoff, 1);
 				if (++wday >= LDAYSPERWEEK)
@@ -2598,7 +2598,7 @@ mp = _("time zone abbreviation differs from POSIX standard");
 		exit(EXIT_FAILURE);
 	}
 	(void) strcpy(&chars[charcnt], string);
-	charcnt += eitol(i);
+	charcnt += i;
 }
 
 static int
@@ -2612,7 +2612,7 @@ mkdirs(char *argname)
 	cp = name = ecpyalloc(argname);
 	while ((cp = strchr(cp + 1, '/')) != 0) {
 		*cp = '\0';
-#ifndef unix
+#ifdef HAVE_DOS_FILE_NAMES
 		/*
 		** DOS drive specifier?
 		*/
@@ -2621,7 +2621,7 @@ mkdirs(char *argname)
 				*cp = '/';
 				continue;
 		}
-#endif /* !defined unix */
+#endif
 		if (!itsdir(name)) {
 			/*
 			** It doesn't seem to exist, so we try to create it.
@@ -2647,21 +2647,6 @@ _("%s: Can't create directory %s: %s\n"),
 	return 0;
 }
 
-static ATTRIBUTE_PURE long
-eitol(const int i)
-{
-	long	l;
-
-	l = i;
-	if ((i < 0 && l >= 0) || (i == 0 && l != 0) || (i > 0 && l <= 0)) {
-		(void) fprintf(stderr,
-			_("%s: %d did not sign extend correctly\n"),
-			progname, i);
-		exit(EXIT_FAILURE);
-	}
-	return l;
-}
-
 /*
 ** UNIX was a registered trademark of The Open Group in 2003.
 */
-- 
1.8.1.2



More information about the tz mailing list