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