Annotation of src/lib/libc/time/zdump.c, Revision 1.3
1.3 ! jtc 1: /* $NetBSD: zdump.c,v 1.2 1995/03/10 18:12:43 jtc Exp $ */
1.2 jtc 2:
1.1 jtc 3: #ifndef lint
4: #ifndef NOID
1.3 ! jtc 5: static char elsieid[] = "@(#)zdump.c 7.24";
1.1 jtc 6: #endif /* !defined NOID */
7: #endif /* !defined lint */
8:
9: /*
10: ** This code has been made independent of the rest of the time
11: ** conversion package to increase confidence in the verification it provides.
12: ** You can use this code to help in verifying other implementations.
13: */
14:
15: #include "stdio.h" /* for stdout, stderr, perror */
16: #include "string.h" /* for strcpy */
17: #include "sys/types.h" /* for time_t */
18: #include "time.h" /* for struct tm */
19: #include "stdlib.h" /* for exit, malloc, atoi */
20:
21: #ifndef MAX_STRING_LENGTH
22: #define MAX_STRING_LENGTH 1024
23: #endif /* !defined MAX_STRING_LENGTH */
24:
25: #ifndef TRUE
26: #define TRUE 1
27: #endif /* !defined TRUE */
28:
29: #ifndef FALSE
30: #define FALSE 0
31: #endif /* !defined FALSE */
32:
33: #ifndef EXIT_SUCCESS
34: #define EXIT_SUCCESS 0
35: #endif /* !defined EXIT_SUCCESS */
36:
37: #ifndef EXIT_FAILURE
38: #define EXIT_FAILURE 1
39: #endif /* !defined EXIT_FAILURE */
40:
41: #ifndef SECSPERMIN
42: #define SECSPERMIN 60
43: #endif /* !defined SECSPERMIN */
44:
45: #ifndef MINSPERHOUR
46: #define MINSPERHOUR 60
47: #endif /* !defined MINSPERHOUR */
48:
49: #ifndef SECSPERHOUR
50: #define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
51: #endif /* !defined SECSPERHOUR */
52:
53: #ifndef HOURSPERDAY
54: #define HOURSPERDAY 24
55: #endif /* !defined HOURSPERDAY */
56:
57: #ifndef EPOCH_YEAR
58: #define EPOCH_YEAR 1970
59: #endif /* !defined EPOCH_YEAR */
60:
61: #ifndef TM_YEAR_BASE
62: #define TM_YEAR_BASE 1900
63: #endif /* !defined TM_YEAR_BASE */
64:
65: #ifndef DAYSPERNYEAR
66: #define DAYSPERNYEAR 365
67: #endif /* !defined DAYSPERNYEAR */
68:
69: #ifndef isleap
70: #define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
71: #endif /* !defined isleap */
72:
1.3 ! jtc 73: #if HAVE_GETTEXT - 0
! 74: #include "locale.h" /* for setlocale */
! 75: #include "libintl.h"
! 76: #endif /* HAVE_GETTEXT - 0 */
! 77:
1.1 jtc 78: #ifndef GNUC_or_lint
79: #ifdef lint
80: #define GNUC_or_lint
81: #endif /* defined lint */
82: #ifndef lint
83: #ifdef __GNUC__
84: #define GNUC_or_lint
85: #endif /* defined __GNUC__ */
86: #endif /* !defined lint */
87: #endif /* !defined GNUC_or_lint */
88:
89: #ifndef INITIALIZE
90: #ifdef GNUC_or_lint
91: #define INITIALIZE(x) ((x) = 0)
92: #endif /* defined GNUC_or_lint */
93: #ifndef GNUC_or_lint
94: #define INITIALIZE(x)
95: #endif /* !defined GNUC_or_lint */
96: #endif /* !defined INITIALIZE */
97:
1.3 ! jtc 98: /*
! 99: ** For the benefit of GNU folk...
! 100: ** `_(MSGID)' uses the current locale's message library string for MSGID.
! 101: ** The default is to use gettext if available, and use MSGID otherwise.
! 102: */
! 103:
! 104: #ifndef _
! 105: #if HAVE_GETTEXT - 0
! 106: #define _(msgid) gettext(msgid)
! 107: #else /* !(HAVE_GETTEXT - 0) */
! 108: #define _(msgid) msgid
! 109: #endif /* !(HAVE_GETTEXT - 0) */
! 110: #endif /* !defined _ */
! 111:
! 112: #ifndef TZ_DOMAIN
! 113: #define TZ_DOMAIN "tz"
! 114: #endif /* !defined TZ_DOMAIN */
! 115:
1.1 jtc 116: extern char ** environ;
117: extern int getopt();
118: extern char * optarg;
119: extern int optind;
120: extern time_t time();
121: extern char * tzname[2];
122:
123: static char * abbr();
124: static long delta();
125: static time_t hunt();
126: static int longest;
127: static char * progname;
128: static void show();
129:
130: int
131: main(argc, argv)
132: int argc;
133: char * argv[];
134: {
135: register int i;
136: register int c;
137: register int vflag;
138: register char * cutoff;
139: register int cutyear;
140: register long cuttime;
141: char ** fakeenv;
142: time_t now;
143: time_t t;
144: time_t newt;
145: time_t hibit;
146: struct tm tm;
147: struct tm newtm;
148:
149: INITIALIZE(cuttime);
1.3 ! jtc 150: #if HAVE_GETTEXT - 0
! 151: (void) setlocale(LC_MESSAGES, "");
! 152: #ifdef TZ_DOMAINDIR
! 153: (void) bindtextdomain(TZ_DOMAIN, TZ_DOMAINDIR);
! 154: #endif /* defined(TEXTDOMAINDIR) */
! 155: (void) textdomain(TZ_DOMAIN);
! 156: #endif /* HAVE_GETTEXT - 0 */
1.1 jtc 157: progname = argv[0];
158: vflag = 0;
159: cutoff = NULL;
160: while ((c = getopt(argc, argv, "c:v")) == 'c' || c == 'v')
161: if (c == 'v')
162: vflag = 1;
163: else cutoff = optarg;
164: if (c != EOF ||
165: (optind == argc - 1 && strcmp(argv[optind], "=") == 0)) {
166: (void) fprintf(stderr,
1.3 ! jtc 167: _("%s: usage is %s [ -v ] [ -c cutoff ] zonename ...\n"),
1.1 jtc 168: argv[0], argv[0]);
169: (void) exit(EXIT_FAILURE);
170: }
171: if (cutoff != NULL) {
172: int y;
173:
174: cutyear = atoi(cutoff);
175: cuttime = 0;
176: for (y = EPOCH_YEAR; y < cutyear; ++y)
177: cuttime += DAYSPERNYEAR + isleap(y);
178: cuttime *= SECSPERHOUR * HOURSPERDAY;
179: }
180: (void) time(&now);
181: longest = 0;
182: for (i = optind; i < argc; ++i)
183: if (strlen(argv[i]) > longest)
184: longest = strlen(argv[i]);
185: for (hibit = 1; (hibit << 1) != 0; hibit <<= 1)
186: continue;
187: {
188: register int from;
189: register int to;
190:
191: for (i = 0; environ[i] != NULL; ++i)
192: continue;
193: fakeenv = (char **) malloc((size_t) ((i + 2) *
194: sizeof *fakeenv));
195: if (fakeenv == NULL ||
196: (fakeenv[0] = (char *) malloc((size_t) (longest +
197: 4))) == NULL) {
198: (void) perror(progname);
199: (void) exit(EXIT_FAILURE);
200: }
201: to = 0;
202: (void) strcpy(fakeenv[to++], "TZ=");
203: for (from = 0; environ[from] != NULL; ++from)
204: if (strncmp(environ[from], "TZ=", 3) != 0)
205: fakeenv[to++] = environ[from];
206: fakeenv[to] = NULL;
207: environ = fakeenv;
208: }
209: for (i = optind; i < argc; ++i) {
210: static char buf[MAX_STRING_LENGTH];
211:
212: (void) strcpy(&fakeenv[0][3], argv[i]);
1.3 ! jtc 213: if (!vflag) {
! 214: show(argv[i], now, FALSE);
1.1 jtc 215: continue;
1.3 ! jtc 216: }
1.1 jtc 217: /*
218: ** Get lowest value of t.
219: */
220: t = hibit;
221: if (t > 0) /* time_t is unsigned */
222: t = 0;
223: show(argv[i], t, TRUE);
224: t += SECSPERHOUR * HOURSPERDAY;
225: show(argv[i], t, TRUE);
226: tm = *localtime(&t);
227: (void) strncpy(buf, abbr(&tm), (sizeof buf) - 1);
228: for ( ; ; ) {
229: if (cutoff != NULL && t >= cuttime)
230: break;
231: newt = t + SECSPERHOUR * 12;
232: if (cutoff != NULL && newt >= cuttime)
233: break;
234: if (newt <= t)
235: break;
236: newtm = *localtime(&newt);
237: if (delta(&newtm, &tm) != (newt - t) ||
238: newtm.tm_isdst != tm.tm_isdst ||
239: strcmp(abbr(&newtm), buf) != 0) {
240: newt = hunt(argv[i], t, newt);
241: newtm = *localtime(&newt);
242: (void) strncpy(buf, abbr(&newtm),
243: (sizeof buf) - 1);
244: }
245: t = newt;
246: tm = newtm;
247: }
248: /*
249: ** Get highest value of t.
250: */
251: t = ~((time_t) 0);
252: if (t < 0) /* time_t is signed */
253: t &= ~hibit;
254: t -= SECSPERHOUR * HOURSPERDAY;
255: show(argv[i], t, TRUE);
256: t += SECSPERHOUR * HOURSPERDAY;
257: show(argv[i], t, TRUE);
258: }
259: if (fflush(stdout) || ferror(stdout)) {
1.3 ! jtc 260: (void) fprintf(stderr, _("%s: Error writing standard output "),
1.1 jtc 261: argv[0]);
1.3 ! jtc 262: (void) perror(_("standard output"));
1.1 jtc 263: (void) exit(EXIT_FAILURE);
264: }
265: exit(EXIT_SUCCESS);
266:
267: /* gcc -Wall pacifier */
268: for ( ; ; )
269: continue;
270: }
271:
272: static time_t
273: hunt(name, lot, hit)
274: char * name;
275: time_t lot;
276: time_t hit;
277: {
278: time_t t;
279: struct tm lotm;
280: struct tm tm;
281: static char loab[MAX_STRING_LENGTH];
282:
283: lotm = *localtime(&lot);
284: (void) strncpy(loab, abbr(&lotm), (sizeof loab) - 1);
285: while ((hit - lot) >= 2) {
286: t = lot / 2 + hit / 2;
287: if (t <= lot)
288: ++t;
289: else if (t >= hit)
290: --t;
291: tm = *localtime(&t);
292: if (delta(&tm, &lotm) == (t - lot) &&
293: tm.tm_isdst == lotm.tm_isdst &&
294: strcmp(abbr(&tm), loab) == 0) {
295: lot = t;
296: lotm = tm;
297: } else hit = t;
298: }
299: show(name, lot, TRUE);
300: show(name, hit, TRUE);
301: return hit;
302: }
303:
304: /*
305: ** Thanks to Paul Eggert (eggert@twinsun.com) for logic used in delta.
306: */
307:
308: static long
309: delta(newp, oldp)
310: struct tm * newp;
311: struct tm * oldp;
312: {
313: long result;
314: int tmy;
315:
316: if (newp->tm_year < oldp->tm_year)
317: return -delta(oldp, newp);
318: result = 0;
319: for (tmy = oldp->tm_year; tmy < newp->tm_year; ++tmy)
320: result += DAYSPERNYEAR + isleap(tmy + TM_YEAR_BASE);
321: result += newp->tm_yday - oldp->tm_yday;
322: result *= HOURSPERDAY;
323: result += newp->tm_hour - oldp->tm_hour;
324: result *= MINSPERHOUR;
325: result += newp->tm_min - oldp->tm_min;
326: result *= SECSPERMIN;
327: result += newp->tm_sec - oldp->tm_sec;
328: return result;
329: }
330:
331: extern struct tm * localtime();
332:
333: static void
334: show(zone, t, v)
335: char * zone;
336: time_t t;
337: int v;
338: {
339: struct tm * tmp;
340:
341: (void) printf("%-*s ", longest, zone);
342: if (v)
343: (void) printf("%.24s GMT = ", asctime(gmtime(&t)));
344: tmp = localtime(&t);
345: (void) printf("%.24s", asctime(tmp));
346: if (*abbr(tmp) != '\0')
347: (void) printf(" %s", abbr(tmp));
348: if (v) {
349: (void) printf(" isdst=%d", tmp->tm_isdst);
350: #ifdef TM_GMTOFF
351: (void) printf(" gmtoff=%ld", tmp->TM_GMTOFF);
352: #endif /* defined TM_GMTOFF */
353: }
354: (void) printf("\n");
355: }
356:
357: static char *
358: abbr(tmp)
359: struct tm * tmp;
360: {
361: register char * result;
362: static char nada;
363:
364: if (tmp->tm_isdst != 0 && tmp->tm_isdst != 1)
365: return &nada;
366: result = tzname[tmp->tm_isdst];
367: return (result == NULL) ? &nada : result;
368: }
CVSweb <webmaster@jp.NetBSD.org>