FW: tzcode2006a.tar.gz on Irix 6.5.18m

Paul Eggert eggert at CS.UCLA.EDU
Fri Feb 3 06:40:21 UTC 2006


Andrew Donaldson <A.Donaldson at bom.gov.au> writes:

> Yell out if you would like anything else tested.

Thanks for looking into the problem.  There were a lot of changes
between the non-working and the working zdump.c.  I enclose them
below.

One thing that jumps out is the new setabsoletes() function.  I
suspect that it is not working properly on your host.  Can you verify
this, by using a debugger and/or inserting print statements?  I would
like to know the value of absolute_min_time and absolute_max_time when
setabsoletes returns, and I'd also like to know the size and
signedness of time_t on your host.  (The code is relying on undefined
behavior here, so it's not strictly portable.)

Thanks.


--- tz-2004gg/zdump.c	2004-10-18 08:37:53.000000000 -0700
+++ tz-2004hg/zdump.c	2004-12-07 08:40:04.000000000 -0800
@@ -1,4 +1,4 @@
-static char	elsieid[] = "@(#)zdump.c	7.47";
+static char	elsieid[] = "@(#)zdump.c	7.57";
 
 /*
 ** This code has been made independent of the rest of the time
@@ -11,6 +11,15 @@ static char	elsieid[] = "@(#)zdump.c	7.4
 #include "sys/types.h"	/* for time_t */
 #include "time.h"	/* for struct tm */
 #include "stdlib.h"	/* for exit, malloc, atoi */
+#include "float.h"	/* for FLT_MAX and DBL_MAX */
+
+#ifndef ZDUMP_LO_YEAR
+#define ZDUMP_LO_YEAR	(-500)
+#endif /* !defined ZDUMP_LO_YEAR */
+
+#ifndef ZDUMP_HI_YEAR
+#define ZDUMP_HI_YEAR	2500
+#endif /* !defined ZDUMP_HI_YEAR */
 
 #ifndef MAX_STRING_LENGTH
 #define MAX_STRING_LENGTH	1024
@@ -71,6 +80,10 @@ static char	elsieid[] = "@(#)zdump.c	7.4
 #define isleap_sum(a, b)	isleap((a) % 400 + (b) % 400)
 #endif /* !defined isleap_sum */
 
+#define SECSPERDAY	((long) SECSPERHOUR * HOURSPERDAY)
+#define SECSPERNYEAR	(SECSPERDAY * DAYSPERNYEAR)
+#define SECSPERLYEAR	(SECSPERNYEAR + SECSPERDAY)
+
 #if HAVE_GETTEXT
 #include "locale.h"	/* for setlocale */
 #include "libintl.h"
@@ -127,13 +140,18 @@ extern char *	optarg;
 extern int	optind;
 extern char *	tzname[2];
 
+static time_t	absolute_min_time;
+static time_t	absolute_max_time;
+static size_t	longest;
+static char *	progname;
+
 static char *	abbr P((struct tm * tmp));
 static long	delta P((struct tm * newp, struct tm * oldp));
+static void	dumptime P((const struct tm * tmp));
 static time_t	hunt P((char * name, time_t lot, time_t	hit));
-static size_t	longest;
-static char *	progname;
+static void	setabsolutes();
 static void	show P((char * zone, time_t t, int v));
-static void	dumptime P((const struct tm * tmp));
+static time_t	yeartot P((long y));
 
 int
 main(argc, argv)
@@ -143,18 +161,22 @@ char *	argv[];
 	register int		i;
 	register int		c;
 	register int		vflag;
-	register char *		cutoff;
-	register int		cutyear;
-	register long		cuttime;
-	char **			fakeenv;
+	register char *		cutarg;
+	register long		cutloyear = ZDUMP_LO_YEAR;
+	register long		cuthiyear = ZDUMP_HI_YEAR;
+	register time_t		cutlotime;
+	register time_t		cuthitime;
+	register char **	fakeenv;
 	time_t			now;
 	time_t			t;
 	time_t			newt;
-	time_t			hibit;
 	struct tm		tm;
 	struct tm		newtm;
+	register struct tm *	tmp;
+	register struct tm *	newtmp;
 
-	INITIALIZE(cuttime);
+	INITIALIZE(cutlotime);
+	INITIALIZE(cuthitime);
 #if HAVE_GETTEXT
 	(void) setlocale(LC_MESSAGES, "");
 #ifdef TZ_DOMAINDIR
@@ -169,34 +191,45 @@ char *	argv[];
 			(void) exit(EXIT_SUCCESS);
 		}
 	vflag = 0;
-	cutoff = NULL;
+	cutarg = NULL;
 	while ((c = getopt(argc, argv, "c:v")) == 'c' || c == 'v')
 		if (c == 'v')
 			vflag = 1;
-		else	cutoff = optarg;
+		else	cutarg = optarg;
 	if ((c != EOF && c != -1) ||
 		(optind == argc - 1 && strcmp(argv[optind], "=") == 0)) {
 			(void) fprintf(stderr,
-_("%s: usage is %s [ --version ] [ -v ] [ -c cutoff ] zonename ...\n"),
-				argv[0], argv[0]);
+_("%s: usage is %s [ --version ] [ -v ] [ -c [loyear,]hiyear ] zonename ...\n"),
+				progname, progname);
+			(void) exit(EXIT_FAILURE);
+	}
+	if (vflag) {
+		if (cutarg != NULL) {
+			long	lo;
+			long	hi;
+			char	c;
+
+			if (sscanf(cutarg, "%ld%c", &hi, &c) == 1) {
+				cuthiyear = hi;
+			} else if (sscanf(cutarg, "%ld,%ld%c",
+				&lo, &hi, &c) == 2) {
+					cutloyear = lo;
+					cuthiyear = hi;
+			} else {
+(void) fprintf(stderr, _("%s: wild -c argument %s\n"),
+					progname, cutarg);
 			(void) exit(EXIT_FAILURE);
 	}
-	if (cutoff != NULL) {
-		int	y;
-
-		cutyear = atoi(cutoff);
-		cuttime = 0;
-		for (y = EPOCH_YEAR; y < cutyear; ++y)
-			cuttime += DAYSPERNYEAR + isleap(y);
-		cuttime *= SECSPERHOUR * HOURSPERDAY;
+		}
+		setabsolutes();
+		cutlotime = yeartot(cutloyear);
+		cuthitime = yeartot(cuthiyear);
 	}
 	(void) time(&now);
 	longest = 0;
 	for (i = optind; i < argc; ++i)
 		if (strlen(argv[i]) > longest)
 			longest = strlen(argv[i]);
-	for (hibit = 1; (hibit << 1) != 0; hibit <<= 1)
-		continue;
 	{
 		register int	from;
 		register int	to;
@@ -226,58 +259,129 @@ _("%s: usage is %s [ --version ] [ -v ] 
 			show(argv[i], now, FALSE);
 			continue;
 		}
-		/*
-		** Get lowest value of t.
-		*/
-		t = hibit;
-		if (t > 0)		/* time_t is unsigned */
-			t = 0;
+		t = absolute_min_time;
 		show(argv[i], t, TRUE);
 		t += SECSPERHOUR * HOURSPERDAY;
 		show(argv[i], t, TRUE);
-		tm = *localtime(&t);
+		if (t < cutlotime)
+			t = cutlotime;
+		tmp = localtime(&t);
+		if (tmp != NULL) {
+			tm = *tmp;
 		(void) strncpy(buf, abbr(&tm), (sizeof buf) - 1);
+		}
 		for ( ; ; ) {
-			if (cutoff != NULL && t >= cuttime)
+			if (t >= cuthitime)
 				break;
 			newt = t + SECSPERHOUR * 12;
-			if (cutoff != NULL && newt >= cuttime)
+			if (newt >= cuthitime)
 				break;
 			if (newt <= t)
 				break;
-			newtm = *localtime(&newt);
-			if (delta(&newtm, &tm) != (newt - t) ||
+			newtmp = localtime(&newt);
+			if (newtmp != NULL)
+				newtm = *newtmp;
+			if ((tmp == NULL || newtmp == NULL) ?  (tmp != newtmp) :
+				(delta(&newtm, &tm) != (newt - t) ||
 				newtm.tm_isdst != tm.tm_isdst ||
-				strcmp(abbr(&newtm), buf) != 0) {
+				strcmp(abbr(&newtm), buf) != 0)) {
 					newt = hunt(argv[i], t, newt);
-					newtm = *localtime(&newt);
-					(void) strncpy(buf, abbr(&newtm),
+					newtmp = localtime(&newt);
+					if (newtmp != NULL) {
+						newtm = *newtmp;
+						(void) strncpy(buf,
+							abbr(&newtm),
 						(sizeof buf) - 1);
 			}
+			}
 			t = newt;
 			tm = newtm;
+			tmp = newtmp;
 		}
-		/*
-		** Get highest value of t.
-		*/
-		t = ~((time_t) 0);
-		if (t < 0)		/* time_t is signed */
-			t &= ~hibit;
+		t = absolute_max_time;
 		t -= SECSPERHOUR * HOURSPERDAY;
 		show(argv[i], t, TRUE);
 		t += SECSPERHOUR * HOURSPERDAY;
 		show(argv[i], t, TRUE);
 	}
 	if (fflush(stdout) || ferror(stdout)) {
-		(void) fprintf(stderr, "%s: ", argv[0]);
+		(void) fprintf(stderr, "%s: ", progname);
 		(void) perror(_("Error writing standard output"));
 		(void) exit(EXIT_FAILURE);
 	}
 	exit(EXIT_SUCCESS);
+	/* If exit fails to exit... */
+	return EXIT_FAILURE;
+}
 
-	/* gcc -Wall pacifier */
-	for ( ; ; )
+static void
+setabsolutes()
+{
+	if (0.5 == (time_t) 0.5) {
+		/*
+		** time_t is floating.
+		*/
+		if (sizeof (time_t) == sizeof (float)) {
+			absolute_min_time = (time_t) -FLT_MAX;
+			absolute_max_time = (time_t) FLT_MAX;
+		} else if (sizeof (time_t) == sizeof (double)) {
+			absolute_min_time = (time_t) -DBL_MAX;
+			absolute_max_time = (time_t) DBL_MAX;
+		} else {
+			(void) fprintf(stderr,
+_("%s: use of -v on system with floating time_t other than float or double\n"),
+				progname);
+			(void) exit(EXIT_FAILURE);
+		}
+	} else if (0 > (time_t) -1) {
+		/*
+		** time_t is signed.
+		*/
+		register time_t	hibit;
+
+		for (hibit = 1; (hibit * 2) != 0; hibit *= 2)
 		continue;
+		absolute_min_time = hibit;
+		absolute_max_time = -(hibit + 1);
+	} else {
+		/*
+		** time_t is unsigned.
+		*/
+		absolute_min_time = 0;
+		absolute_max_time = absolute_min_time - 1;
+	}
+}
+
+static time_t
+yeartot(y)
+const long	y;
+{
+	register long	myy;
+	register long	seconds;
+	register time_t	t;
+
+	myy = EPOCH_YEAR;
+	t = 0;
+	while (myy != y) {
+		if (myy < y) {
+			seconds = isleap(myy) ? SECSPERLYEAR : SECSPERNYEAR;
+			++myy;
+			if (t > absolute_max_time - seconds) {
+				t = absolute_max_time;
+				break;
+			}
+			t += seconds;
+		} else {
+			--myy;
+			seconds = isleap(myy) ? SECSPERLYEAR : SECSPERNYEAR;
+			if (t < absolute_min_time + seconds) {
+				t = absolute_min_time;
+				break;
+			}
+			t -= seconds;
+		}
+	}
+	return t;
 }
 
 static time_t
@@ -287,24 +391,38 @@ time_t	lot;
 time_t	hit;
 {
 	time_t		t;
+	long			diff;
 	struct tm	lotm;
+	register struct tm *	lotmp;
 	struct tm	tm;
-	static char	loab[MAX_STRING_LENGTH];
+	register struct tm *	tmp;
+	char			loab[MAX_STRING_LENGTH];
 
-	lotm = *localtime(&lot);
+	lotmp = localtime(&lot);
+	if (lotmp != NULL) {
+		lotm = *lotmp;
 	(void) strncpy(loab, abbr(&lotm), (sizeof loab) - 1);
-	while ((hit - lot) >= 2) {
-		t = lot / 2 + hit / 2;
+	}
+	for ( ; ; ) {
+		diff = (long) (hit - lot);
+		if (diff < 2)
+			break;
+		t = lot;
+		t += diff / 2;
 		if (t <= lot)
 			++t;
 		else if (t >= hit)
 			--t;
-		tm = *localtime(&t);
-		if (delta(&tm, &lotm) == (t - lot) &&
+		tmp = localtime(&t);
+		if (tmp != NULL)
+			tm = *tmp;
+		if ((lotmp == NULL || tmp == NULL) ? (lotmp == tmp) :
+			(delta(&tm, &lotm) == (t - lot) &&
 			tm.tm_isdst == lotm.tm_isdst &&
-			strcmp(abbr(&tm), loab) == 0) {
+			strcmp(abbr(&tm), loab) == 0)) {
 				lot = t;
 				lotm = tm;
+				lotmp = tmp;
 		} else	hit = t;
 	}
 	show(name, lot, TRUE);
@@ -321,8 +439,8 @@ delta(newp, oldp)
 struct tm *	newp;
 struct tm *	oldp;
 {
-	long	result;
-	int	tmy;
+	register long	result;
+	register int	tmy;
 
 	if (newp->tm_year < oldp->tm_year)
 		return -delta(oldp, newp);
@@ -345,15 +463,22 @@ char *	zone;
 time_t	t;
 int	v;
 {
-	struct tm *	tmp;
+	register struct tm *	tmp;
 
 	(void) printf("%-*s  ", (int) longest, zone);
 	if (v) {
-		dumptime(gmtime(&t));
-		(void) printf(" UTC = ");
+		tmp = gmtime(&t);
+		if (tmp == NULL) {
+			(void) printf("%g", (double) t);
+		} else {
+			dumptime(tmp);
+			(void) printf(" UTC");
+		}
+		(void) printf(" = ");
 	}
 	tmp = localtime(&t);
 	dumptime(tmp);
+	if (tmp != NULL) {
 	if (*abbr(tmp) != '\0')
 		(void) printf(" %s", abbr(tmp));
 	if (v) {
@@ -362,6 +487,7 @@ int	v;
 		(void) printf(" gmtoff=%ld", tmp->TM_GMTOFF);
 #endif /* defined TM_GMTOFF */
 	}
+	}
 	(void) printf("\n");
 }
 
@@ -394,6 +520,10 @@ register const struct tm *	timeptr;
 	register int		lead;
 	register int		trail;
 
+	if (timeptr == NULL) {
+		(void) printf("NULL");
+		return;
+	}
 	/*
 	** The packaged versions of localtime and gmtime never put out-of-range
 	** values in tm_wday or tm_mon, but since this code might be compiled



More information about the tz mailing list