Deleted Added
full compact
zdump.c (176407) zdump.c (192625)
1static const char elsieid[] = "@(#)zdump.c 7.31";
2
3#ifndef lint
4static const char rcsid[] =
1#ifndef lint
2static const char rcsid[] =
5 "$FreeBSD: head/usr.sbin/zic/zdump.c 176407 2008-02-19 07:09:19Z ru $";
3 "$FreeBSD: head/usr.sbin/zic/zdump.c 192625 2009-05-23 06:31:50Z edwin $";
4static char elsieid[] = "@(#)zdump.c 8.8";
6#endif /* not lint */
7
8/*
9** This code has been made independent of the rest of the time
10** conversion package to increase confidence in the verification it provides.
11** You can use this code to help in verifying other implementations.
12*/
13
14#include <err.h>
15#include <stdio.h> /* for stdout, stderr */
16#include <stdlib.h> /* for exit, malloc, atoi */
17#include <string.h> /* for strcpy */
18#include <sys/types.h> /* for time_t */
19#include <time.h> /* for struct tm */
20#include <unistd.h>
5#endif /* not lint */
6
7/*
8** This code has been made independent of the rest of the time
9** conversion package to increase confidence in the verification it provides.
10** You can use this code to help in verifying other implementations.
11*/
12
13#include <err.h>
14#include <stdio.h> /* for stdout, stderr */
15#include <stdlib.h> /* for exit, malloc, atoi */
16#include <string.h> /* for strcpy */
17#include <sys/types.h> /* for time_t */
18#include <time.h> /* for struct tm */
19#include <unistd.h>
20#include <float.h> /* for FLT_MAX and DBL_MAX */
21#include <ctype.h> /* for isalpha et al. */
22#ifndef isascii
23#define isascii(x) 1
24#endif /* !defined isascii */
21
25
26#ifndef ZDUMP_LO_YEAR
27#define ZDUMP_LO_YEAR (-500)
28#endif /* !defined ZDUMP_LO_YEAR */
29
30#ifndef ZDUMP_HI_YEAR
31#define ZDUMP_HI_YEAR 2500
32#endif /* !defined ZDUMP_HI_YEAR */
33
22#ifndef MAX_STRING_LENGTH
23#define MAX_STRING_LENGTH 1024
24#endif /* !defined MAX_STRING_LENGTH */
25
26#ifndef TRUE
27#define TRUE 1
28#endif /* !defined TRUE */
29

--- 33 unchanged lines hidden (view full) ---

63#define TM_YEAR_BASE 1900
64#endif /* !defined TM_YEAR_BASE */
65
66#ifndef DAYSPERNYEAR
67#define DAYSPERNYEAR 365
68#endif /* !defined DAYSPERNYEAR */
69
70#ifndef isleap
34#ifndef MAX_STRING_LENGTH
35#define MAX_STRING_LENGTH 1024
36#endif /* !defined MAX_STRING_LENGTH */
37
38#ifndef TRUE
39#define TRUE 1
40#endif /* !defined TRUE */
41

--- 33 unchanged lines hidden (view full) ---

75#define TM_YEAR_BASE 1900
76#endif /* !defined TM_YEAR_BASE */
77
78#ifndef DAYSPERNYEAR
79#define DAYSPERNYEAR 365
80#endif /* !defined DAYSPERNYEAR */
81
82#ifndef isleap
71#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
83#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
72#endif /* !defined isleap */
73
84#endif /* !defined isleap */
85
74#if HAVE_GETTEXT - 0
86#ifndef isleap_sum
87/*
88** See tzfile.h for details on isleap_sum.
89*/
90#define isleap_sum(a, b) isleap((a) % 400 + (b) % 400)
91#endif /* !defined isleap_sum */
92
93#define SECSPERDAY ((long) SECSPERHOUR * HOURSPERDAY)
94#define SECSPERNYEAR (SECSPERDAY * DAYSPERNYEAR)
95#define SECSPERLYEAR (SECSPERNYEAR + SECSPERDAY)
96
97#ifndef HAVE_GETTEXT
98#define HAVE_GETTEXT 0
99#endif
100#if HAVE_GETTEXT
75#include "locale.h" /* for setlocale */
76#include "libintl.h"
101#include "locale.h" /* for setlocale */
102#include "libintl.h"
77#endif /* HAVE_GETTEXT - 0 */
103#endif /* HAVE_GETTEXT */
78
79#ifndef GNUC_or_lint
80#ifdef lint
81#define GNUC_or_lint
104
105#ifndef GNUC_or_lint
106#ifdef lint
107#define GNUC_or_lint
82#endif /* defined lint */
83#ifndef lint
108#else /* !defined lint */
84#ifdef __GNUC__
85#define GNUC_or_lint
86#endif /* defined __GNUC__ */
87#endif /* !defined lint */
88#endif /* !defined GNUC_or_lint */
89
90#ifndef INITIALIZE
91#ifdef GNUC_or_lint
92#define INITIALIZE(x) ((x) = 0)
109#ifdef __GNUC__
110#define GNUC_or_lint
111#endif /* defined __GNUC__ */
112#endif /* !defined lint */
113#endif /* !defined GNUC_or_lint */
114
115#ifndef INITIALIZE
116#ifdef GNUC_or_lint
117#define INITIALIZE(x) ((x) = 0)
93#endif /* defined GNUC_or_lint */
94#ifndef GNUC_or_lint
118#else /* !defined GNUC_or_lint */
95#define INITIALIZE(x)
96#endif /* !defined GNUC_or_lint */
97#endif /* !defined INITIALIZE */
98
99/*
100** For the benefit of GNU folk...
101** `_(MSGID)' uses the current locale's message library string for MSGID.
102** The default is to use gettext if available, and use MSGID otherwise.
103*/
104
105#ifndef _
119#define INITIALIZE(x)
120#endif /* !defined GNUC_or_lint */
121#endif /* !defined INITIALIZE */
122
123/*
124** For the benefit of GNU folk...
125** `_(MSGID)' uses the current locale's message library string for MSGID.
126** The default is to use gettext if available, and use MSGID otherwise.
127*/
128
129#ifndef _
106#if HAVE_GETTEXT - 0
130#if HAVE_GETTEXT
107#define _(msgid) gettext(msgid)
131#define _(msgid) gettext(msgid)
108#else /* !(HAVE_GETTEXT - 0) */
132#else /* !(HAVE_GETTEXT) */
109#define _(msgid) msgid
133#define _(msgid) msgid
110#endif /* !(HAVE_GETTEXT - 0) */
134#endif /* !(HAVE_GETTEXT) */
111#endif /* !defined _ */
112
113#ifndef TZ_DOMAIN
114#define TZ_DOMAIN "tz"
115#endif /* !defined TZ_DOMAIN */
116
135#endif /* !defined _ */
136
137#ifndef TZ_DOMAIN
138#define TZ_DOMAIN "tz"
139#endif /* !defined TZ_DOMAIN */
140
117#ifndef P
118#ifdef __STDC__
119#define P(x) x
120#endif /* defined __STDC__ */
121#ifndef __STDC__
122#define P(x) ()
123#endif /* !defined __STDC__ */
124#endif /* !defined P */
125
126extern char ** environ;
127extern char * tzname[2];
128
141extern char ** environ;
142extern char * tzname[2];
143
129static char * abbr P((struct tm * tmp));
130static long delta P((struct tm * newp, struct tm * oldp));
131static time_t hunt P((char * name, time_t lot, time_t hit));
144static time_t absolute_min_time;
145static time_t absolute_max_time;
132static size_t longest;
146static size_t longest;
133static void show P((char * zone, time_t t, int v));
134static void usage(void);
147static char * progname;
148static int warned;
135
149
150static void usage(const char *progname, FILE *stream, int status);
151static char * abbr(struct tm * tmp);
152static void abbrok(const char * abbrp, const char * zone);
153static long delta(struct tm * newp, struct tm * oldp);
154static void dumptime(const struct tm * tmp);
155static time_t hunt(char * name, time_t lot, time_t hit);
156static void setabsolutes(void);
157static void show(char * zone, time_t t, int v);
158static const char * tformat(void);
159static time_t yeartot(long y);
160
161#ifndef TYPECHECK
162#define my_localtime localtime
163#else /* !defined TYPECHECK */
164static struct tm *
165my_localtime(tp)
166time_t * tp;
167{
168 register struct tm * tmp;
169
170 tmp = localtime(tp);
171 if (tp != NULL && tmp != NULL) {
172 struct tm tm;
173 register time_t t;
174
175 tm = *tmp;
176 t = mktime(&tm);
177 if (t - *tp >= 1 || *tp - t >= 1) {
178 (void) fflush(stdout);
179 (void) fprintf(stderr, "\n%s: ", progname);
180 (void) fprintf(stderr, tformat(), *tp);
181 (void) fprintf(stderr, " ->");
182 (void) fprintf(stderr, " year=%d", tmp->tm_year);
183 (void) fprintf(stderr, " mon=%d", tmp->tm_mon);
184 (void) fprintf(stderr, " mday=%d", tmp->tm_mday);
185 (void) fprintf(stderr, " hour=%d", tmp->tm_hour);
186 (void) fprintf(stderr, " min=%d", tmp->tm_min);
187 (void) fprintf(stderr, " sec=%d", tmp->tm_sec);
188 (void) fprintf(stderr, " isdst=%d", tmp->tm_isdst);
189 (void) fprintf(stderr, " -> ");
190 (void) fprintf(stderr, tformat(), t);
191 (void) fprintf(stderr, "\n");
192 }
193 }
194 return tmp;
195}
196#endif /* !defined TYPECHECK */
197
198static void
199abbrok(abbrp, zone)
200const char * const abbrp;
201const char * const zone;
202{
203 register const char * cp;
204 register char * wp;
205
206 if (warned)
207 return;
208 cp = abbrp;
209 wp = NULL;
210 while (isascii((unsigned char) *cp) && isalpha((unsigned char) *cp))
211 ++cp;
212 if (cp - abbrp == 0)
213 wp = _("lacks alphabetic at start");
214 else if (cp - abbrp < 3)
215 wp = _("has fewer than 3 alphabetics");
216 else if (cp - abbrp > 6)
217 wp = _("has more than 6 alphabetics");
218 if (wp == NULL && (*cp == '+' || *cp == '-')) {
219 ++cp;
220 if (isascii((unsigned char) *cp) &&
221 isdigit((unsigned char) *cp))
222 if (*cp++ == '1' && *cp >= '0' && *cp <= '4')
223 ++cp;
224 if (*cp != '\0')
225 wp = _("differs from POSIX standard");
226 }
227 if (wp == NULL)
228 return;
229 (void) fflush(stdout);
230 (void) fprintf(stderr,
231 _("%s: warning: zone \"%s\" abbreviation \"%s\" %s\n"),
232 progname, zone, abbrp, wp);
233 warned = TRUE;
234}
235
136int
137main(argc, argv)
138int argc;
139char * argv[];
140{
141 register int i;
142 register int c;
143 register int vflag;
236int
237main(argc, argv)
238int argc;
239char * argv[];
240{
241 register int i;
242 register int c;
243 register int vflag;
144 register char * cutoff;
145 register int cutyear;
146 register long cuttime;
147 char ** fakeenv;
244 register char * cutarg;
245 register long cutloyear = ZDUMP_LO_YEAR;
246 register long cuthiyear = ZDUMP_HI_YEAR;
247 register time_t cutlotime;
248 register time_t cuthitime;
249 register char ** fakeenv;
148 time_t now;
149 time_t t;
150 time_t newt;
250 time_t now;
251 time_t t;
252 time_t newt;
151 time_t hibit;
152 struct tm tm;
153 struct tm newtm;
253 struct tm tm;
254 struct tm newtm;
255 register struct tm * tmp;
256 register struct tm * newtmp;
154
257
155 INITIALIZE(cuttime);
156#if HAVE_GETTEXT - 0
258 INITIALIZE(cutlotime);
259 INITIALIZE(cuthitime);
260#if HAVE_GETTEXT
157 (void) setlocale(LC_MESSAGES, "");
158#ifdef TZ_DOMAINDIR
159 (void) bindtextdomain(TZ_DOMAIN, TZ_DOMAINDIR);
261 (void) setlocale(LC_MESSAGES, "");
262#ifdef TZ_DOMAINDIR
263 (void) bindtextdomain(TZ_DOMAIN, TZ_DOMAINDIR);
160#endif /* defined(TEXTDOMAINDIR) */
264#endif /* TEXTDOMAINDIR */
161 (void) textdomain(TZ_DOMAIN);
265 (void) textdomain(TZ_DOMAIN);
162#endif /* HAVE_GETTEXT - 0 */
266#endif /* HAVE_GETTEXT */
163 for (i = 1; i < argc; ++i)
164 if (strcmp(argv[i], "--version") == 0) {
165 errx(EXIT_SUCCESS, "%s", elsieid);
267 for (i = 1; i < argc; ++i)
268 if (strcmp(argv[i], "--version") == 0) {
269 errx(EXIT_SUCCESS, "%s", elsieid);
270 } else if (strcmp(argv[i], "--help") == 0) {
271 usage(progname, stdout, EXIT_SUCCESS);
166 }
167 vflag = 0;
272 }
273 vflag = 0;
168 cutoff = NULL;
274 cutarg = NULL;
169 while ((c = getopt(argc, argv, "c:v")) == 'c' || c == 'v')
170 if (c == 'v')
171 vflag = 1;
275 while ((c = getopt(argc, argv, "c:v")) == 'c' || c == 'v')
276 if (c == 'v')
277 vflag = 1;
172 else cutoff = optarg;
278 else cutarg = optarg;
173 if ((c != -1) ||
174 (optind == argc - 1 && strcmp(argv[optind], "=") == 0)) {
279 if ((c != -1) ||
280 (optind == argc - 1 && strcmp(argv[optind], "=") == 0)) {
175 usage();
281 usage(progname, stderr, EXIT_FAILURE);
176 }
282 }
177 if (cutoff != NULL) {
178 int y;
283 if (vflag) {
284 if (cutarg != NULL) {
285 long lo;
286 long hi;
287 char dummy;
179
288
180 cutyear = atoi(cutoff);
181 cuttime = 0;
182 for (y = EPOCH_YEAR; y < cutyear; ++y)
183 cuttime += DAYSPERNYEAR + isleap(y);
184 cuttime *= SECSPERHOUR * HOURSPERDAY;
289 if (sscanf(cutarg, "%ld%c", &hi, &dummy) == 1) {
290 cuthiyear = hi;
291 } else if (sscanf(cutarg, "%ld,%ld%c",
292 &lo, &hi, &dummy) == 2) {
293 cutloyear = lo;
294 cuthiyear = hi;
295 } else {
296(void) fprintf(stderr, _("%s: wild -c argument %s\n"),
297 progname, cutarg);
298 exit(EXIT_FAILURE);
299 }
300 }
301 setabsolutes();
302 cutlotime = yeartot(cutloyear);
303 cuthitime = yeartot(cuthiyear);
185 }
186 (void) time(&now);
187 longest = 0;
188 for (i = optind; i < argc; ++i)
189 if (strlen(argv[i]) > longest)
190 longest = strlen(argv[i]);
304 }
305 (void) time(&now);
306 longest = 0;
307 for (i = optind; i < argc; ++i)
308 if (strlen(argv[i]) > longest)
309 longest = strlen(argv[i]);
191 for (hibit = 1; (hibit << 1) != 0; hibit <<= 1)
192 continue;
193 {
194 register int from;
195 register int to;
196
310 {
311 register int from;
312 register int to;
313
197 for (i = 0; environ[i] != NULL; ++i)
314 for (i = 0; environ[i] != NULL; ++i)
198 continue;
199 fakeenv = (char **) malloc((size_t) ((i + 2) *
200 sizeof *fakeenv));
201 if (fakeenv == NULL ||
202 (fakeenv[0] = (char *) malloc((size_t) (longest +
203 4))) == NULL)
204 errx(EXIT_FAILURE,
205 _("malloc() failed"));

--- 8 unchanged lines hidden (view full) ---

214 for (i = optind; i < argc; ++i) {
215 static char buf[MAX_STRING_LENGTH];
216
217 (void) strcpy(&fakeenv[0][3], argv[i]);
218 if (!vflag) {
219 show(argv[i], now, FALSE);
220 continue;
221 }
315 continue;
316 fakeenv = (char **) malloc((size_t) ((i + 2) *
317 sizeof *fakeenv));
318 if (fakeenv == NULL ||
319 (fakeenv[0] = (char *) malloc((size_t) (longest +
320 4))) == NULL)
321 errx(EXIT_FAILURE,
322 _("malloc() failed"));

--- 8 unchanged lines hidden (view full) ---

331 for (i = optind; i < argc; ++i) {
332 static char buf[MAX_STRING_LENGTH];
333
334 (void) strcpy(&fakeenv[0][3], argv[i]);
335 if (!vflag) {
336 show(argv[i], now, FALSE);
337 continue;
338 }
222 /*
223 ** Get lowest value of t.
224 */
225 t = hibit;
226 if (t > 0) /* time_t is unsigned */
227 t = 0;
339 warned = FALSE;
340 t = absolute_min_time;
228 show(argv[i], t, TRUE);
229 t += SECSPERHOUR * HOURSPERDAY;
230 show(argv[i], t, TRUE);
341 show(argv[i], t, TRUE);
342 t += SECSPERHOUR * HOURSPERDAY;
343 show(argv[i], t, TRUE);
231 tm = *localtime(&t);
232 (void) strncpy(buf, abbr(&tm), (sizeof buf) - 1);
344 if (t < cutlotime)
345 t = cutlotime;
346 tmp = my_localtime(&t);
347 if (tmp != NULL) {
348 tm = *tmp;
349 (void) strncpy(buf, abbr(&tm), (sizeof buf) - 1);
350 }
233 for ( ; ; ) {
351 for ( ; ; ) {
234 if (cutoff != NULL && t >= cuttime)
352 if (t >= cuthitime || t >= cuthitime - SECSPERHOUR * 12)
235 break;
236 newt = t + SECSPERHOUR * 12;
353 break;
354 newt = t + SECSPERHOUR * 12;
237 if (cutoff != NULL && newt >= cuttime)
238 break;
239 if (newt <= t)
240 break;
241 newtm = *localtime(&newt);
242 if (delta(&newtm, &tm) != (newt - t) ||
355 newtmp = localtime(&newt);
356 if (newtmp != NULL)
357 newtm = *newtmp;
358 if ((tmp == NULL || newtmp == NULL) ? (tmp != newtmp) :
359 (delta(&newtm, &tm) != (newt - t) ||
243 newtm.tm_isdst != tm.tm_isdst ||
360 newtm.tm_isdst != tm.tm_isdst ||
244 strcmp(abbr(&newtm), buf) != 0) {
361 strcmp(abbr(&newtm), buf) != 0)) {
245 newt = hunt(argv[i], t, newt);
362 newt = hunt(argv[i], t, newt);
246 newtm = *localtime(&newt);
247 (void) strncpy(buf, abbr(&newtm),
248 (sizeof buf) - 1);
363 newtmp = localtime(&newt);
364 if (newtmp != NULL) {
365 newtm = *newtmp;
366 (void) strncpy(buf,
367 abbr(&newtm),
368 (sizeof buf) - 1);
369 }
249 }
250 t = newt;
251 tm = newtm;
370 }
371 t = newt;
372 tm = newtm;
373 tmp = newtmp;
252 }
374 }
253 /*
254 ** Get highest value of t.
255 */
256 t = ~((time_t) 0);
257 if (t < 0) /* time_t is signed */
258 t &= ~hibit;
375 t = absolute_max_time;
259 t -= SECSPERHOUR * HOURSPERDAY;
260 show(argv[i], t, TRUE);
261 t += SECSPERHOUR * HOURSPERDAY;
262 show(argv[i], t, TRUE);
263 }
264 if (fflush(stdout) || ferror(stdout))
265 errx(EXIT_FAILURE, _("error writing standard output"));
266 exit(EXIT_SUCCESS);
376 t -= SECSPERHOUR * HOURSPERDAY;
377 show(argv[i], t, TRUE);
378 t += SECSPERHOUR * HOURSPERDAY;
379 show(argv[i], t, TRUE);
380 }
381 if (fflush(stdout) || ferror(stdout))
382 errx(EXIT_FAILURE, _("error writing standard output"));
383 exit(EXIT_SUCCESS);
384 /* If exit fails to exit... */
385 return(EXIT_FAILURE);
386}
267
387
268 /* gcc -Wall pacifier */
269 for ( ; ; )
270 continue;
388static void
389setabsolutes(void)
390{
391 if (0.5 == (time_t) 0.5) {
392 /*
393 ** time_t is floating.
394 */
395 if (sizeof (time_t) == sizeof (float)) {
396 absolute_min_time = (time_t) -FLT_MAX;
397 absolute_max_time = (time_t) FLT_MAX;
398 } else if (sizeof (time_t) == sizeof (double)) {
399 absolute_min_time = (time_t) -DBL_MAX;
400 absolute_max_time = (time_t) DBL_MAX;
401 } else {
402 (void) fprintf(stderr,
403_("%s: use of -v on system with floating time_t other than float or double\n"),
404 progname);
405 exit(EXIT_FAILURE);
406 }
407 } else if (0 > (time_t) -1) {
408 /*
409 ** time_t is signed. Assume overflow wraps around.
410 */
411 time_t t = 0;
412 time_t t1 = 1;
413
414 while (t < t1) {
415 t = t1;
416 t1 = 2 * t1 + 1;
417 }
418
419 absolute_max_time = t;
420 t = -t;
421 absolute_min_time = t - 1;
422 if (t < absolute_min_time)
423 absolute_min_time = t;
424 } else {
425 /*
426 ** time_t is unsigned.
427 */
428 absolute_min_time = 0;
429 absolute_max_time = absolute_min_time - 1;
430 }
271}
272
431}
432
433static time_t
434yeartot(y)
435const long y;
436{
437 register long myy;
438 register long seconds;
439 register time_t t;
440
441 myy = EPOCH_YEAR;
442 t = 0;
443 while (myy != y) {
444 if (myy < y) {
445 seconds = isleap(myy) ? SECSPERLYEAR : SECSPERNYEAR;
446 ++myy;
447 if (t > absolute_max_time - seconds) {
448 t = absolute_max_time;
449 break;
450 }
451 t += seconds;
452 } else {
453 --myy;
454 seconds = isleap(myy) ? SECSPERLYEAR : SECSPERNYEAR;
455 if (t < absolute_min_time + seconds) {
456 t = absolute_min_time;
457 break;
458 }
459 t -= seconds;
460 }
461 }
462 return t;
463}
464
273static void
465static void
274usage(void)
466usage(const char *progname, FILE *stream, int status)
275{
467{
276 fprintf(stderr,
277_("usage: zdump [--version] [-v] [-c cutoff] zonename ...\n"));
278 exit(EXIT_FAILURE);
468 fprintf(stream,
469_("usage: %s [--version] [-v] [--help] [-c [loyear,]hiyear] zonename ...\n\
470\n\
471Report bugs to tz@elsie.nci.nih.gov.\n"), progname);
472 exit(status);
279}
280
281static time_t
473}
474
475static time_t
282hunt(name, lot, hit)
283char * name;
284time_t lot;
285time_t hit;
476hunt(char *name, time_t lot, time_t hit)
286{
477{
287 time_t t;
288 struct tm lotm;
289 struct tm tm;
290 static char loab[MAX_STRING_LENGTH];
478 time_t t;
479 long diff;
480 struct tm lotm;
481 register struct tm * lotmp;
482 struct tm tm;
483 register struct tm * tmp;
484 char loab[MAX_STRING_LENGTH];
291
485
292 lotm = *localtime(&lot);
293 (void) strncpy(loab, abbr(&lotm), (sizeof loab) - 1);
294 while ((hit - lot) >= 2) {
295 t = lot / 2 + hit / 2;
486 lotmp = my_localtime(&lot);
487 if (lotmp != NULL) {
488 lotm = *lotmp;
489 (void) strncpy(loab, abbr(&lotm), (sizeof loab) - 1);
490 }
491 for ( ; ; ) {
492 diff = (long) (hit - lot);
493 if (diff < 2)
494 break;
495 t = lot;
496 t += diff / 2;
296 if (t <= lot)
297 ++t;
298 else if (t >= hit)
299 --t;
497 if (t <= lot)
498 ++t;
499 else if (t >= hit)
500 --t;
300 tm = *localtime(&t);
301 if (delta(&tm, &lotm) == (t - lot) &&
501 tmp = my_localtime(&t);
502 if (tmp != NULL)
503 tm = *tmp;
504 if ((lotmp == NULL || tmp == NULL) ? (lotmp == tmp) :
505 (delta(&tm, &lotm) == (t - lot) &&
302 tm.tm_isdst == lotm.tm_isdst &&
506 tm.tm_isdst == lotm.tm_isdst &&
303 strcmp(abbr(&tm), loab) == 0) {
507 strcmp(abbr(&tm), loab) == 0)) {
304 lot = t;
305 lotm = tm;
508 lot = t;
509 lotm = tm;
510 lotmp = tmp;
306 } else hit = t;
307 }
308 show(name, lot, TRUE);
309 show(name, hit, TRUE);
310 return hit;
311}
312
313/*
511 } else hit = t;
512 }
513 show(name, lot, TRUE);
514 show(name, hit, TRUE);
515 return hit;
516}
517
518/*
314** Thanks to Paul Eggert (eggert@twinsun.com) for logic used in delta.
519** Thanks to Paul Eggert for logic used in delta.
315*/
316
317static long
318delta(newp, oldp)
319struct tm * newp;
320struct tm * oldp;
321{
520*/
521
522static long
523delta(newp, oldp)
524struct tm * newp;
525struct tm * oldp;
526{
322 long result;
323 int tmy;
527 register long result;
528 register int tmy;
324
325 if (newp->tm_year < oldp->tm_year)
326 return -delta(oldp, newp);
327 result = 0;
328 for (tmy = oldp->tm_year; tmy < newp->tm_year; ++tmy)
529
530 if (newp->tm_year < oldp->tm_year)
531 return -delta(oldp, newp);
532 result = 0;
533 for (tmy = oldp->tm_year; tmy < newp->tm_year; ++tmy)
329 result += DAYSPERNYEAR + isleap(tmy + TM_YEAR_BASE);
534 result += DAYSPERNYEAR + isleap_sum(tmy, TM_YEAR_BASE);
330 result += newp->tm_yday - oldp->tm_yday;
331 result *= HOURSPERDAY;
332 result += newp->tm_hour - oldp->tm_hour;
333 result *= MINSPERHOUR;
334 result += newp->tm_min - oldp->tm_min;
335 result *= SECSPERMIN;
336 result += newp->tm_sec - oldp->tm_sec;
337 return result;
338}
339
340static void
535 result += newp->tm_yday - oldp->tm_yday;
536 result *= HOURSPERDAY;
537 result += newp->tm_hour - oldp->tm_hour;
538 result *= MINSPERHOUR;
539 result += newp->tm_min - oldp->tm_min;
540 result *= SECSPERMIN;
541 result += newp->tm_sec - oldp->tm_sec;
542 return result;
543}
544
545static void
341show(zone, t, v)
342char * zone;
343time_t t;
344int v;
546show(char *zone, time_t t, int v)
345{
547{
346 struct tm * tmp;
548 register struct tm * tmp;
347
348 (void) printf("%-*s ", (int) longest, zone);
549
550 (void) printf("%-*s ", (int) longest, zone);
349 if (v)
350 (void) printf("%.24s UTC = ", asctime(gmtime(&t)));
351 tmp = localtime(&t);
352 (void) printf("%.24s", asctime(tmp));
353 if (*abbr(tmp) != '\0')
354 (void) printf(" %s", abbr(tmp));
355 if (v) {
551 if (v) {
356 (void) printf(" isdst=%d", tmp->tm_isdst);
552 tmp = gmtime(&t);
553 if (tmp == NULL) {
554 (void) printf(tformat(), t);
555 } else {
556 dumptime(tmp);
557 (void) printf(" UTC");
558 }
559 (void) printf(" = ");
560 }
561 tmp = my_localtime(&t);
562 dumptime(tmp);
563 if (tmp != NULL) {
564 if (*abbr(tmp) != '\0')
565 (void) printf(" %s", abbr(tmp));
566 if (v) {
567 (void) printf(" isdst=%d", tmp->tm_isdst);
357#ifdef TM_GMTOFF
568#ifdef TM_GMTOFF
358 (void) printf(" gmtoff=%ld", tmp->TM_GMTOFF);
569 (void) printf(" gmtoff=%ld", tmp->TM_GMTOFF);
359#endif /* defined TM_GMTOFF */
570#endif /* defined TM_GMTOFF */
571 }
360 }
361 (void) printf("\n");
572 }
573 (void) printf("\n");
574 if (tmp != NULL && *abbr(tmp) != '\0')
575 abbrok(abbr(tmp), zone);
362}
363
364static char *
365abbr(tmp)
366struct tm * tmp;
367{
368 register char * result;
369 static char nada;
370
371 if (tmp->tm_isdst != 0 && tmp->tm_isdst != 1)
372 return &nada;
373 result = tzname[tmp->tm_isdst];
374 return (result == NULL) ? &nada : result;
375}
576}
577
578static char *
579abbr(tmp)
580struct tm * tmp;
581{
582 register char * result;
583 static char nada;
584
585 if (tmp->tm_isdst != 0 && tmp->tm_isdst != 1)
586 return &nada;
587 result = tzname[tmp->tm_isdst];
588 return (result == NULL) ? &nada : result;
589}
590
591/*
592** The code below can fail on certain theoretical systems;
593** it works on all known real-world systems as of 2004-12-30.
594*/
595
596static const char *
597tformat(void)
598{
599 if (0.5 == (time_t) 0.5) { /* floating */
600 if (sizeof (time_t) > sizeof (double))
601 return "%Lg";
602 return "%g";
603 }
604 if (0 > (time_t) -1) { /* signed */
605 if (sizeof (time_t) > sizeof (long))
606 return "%lld";
607 if (sizeof (time_t) > sizeof (int))
608 return "%ld";
609 return "%d";
610 }
611 if (sizeof (time_t) > sizeof (unsigned long))
612 return "%llu";
613 if (sizeof (time_t) > sizeof (unsigned int))
614 return "%lu";
615 return "%u";
616}
617
618static void
619dumptime(timeptr)
620register const struct tm * timeptr;
621{
622 static const char wday_name[][3] = {
623 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
624 };
625 static const char mon_name[][3] = {
626 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
627 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
628 };
629 register const char * wn;
630 register const char * mn;
631 register int lead;
632 register int trail;
633
634 if (timeptr == NULL) {
635 (void) printf("NULL");
636 return;
637 }
638 /*
639 ** The packaged versions of localtime and gmtime never put out-of-range
640 ** values in tm_wday or tm_mon, but since this code might be compiled
641 ** with other (perhaps experimental) versions, paranoia is in order.
642 */
643 if (timeptr->tm_wday < 0 || timeptr->tm_wday >=
644 (int) (sizeof wday_name / sizeof wday_name[0]))
645 wn = "???";
646 else wn = wday_name[timeptr->tm_wday];
647 if (timeptr->tm_mon < 0 || timeptr->tm_mon >=
648 (int) (sizeof mon_name / sizeof mon_name[0]))
649 mn = "???";
650 else mn = mon_name[timeptr->tm_mon];
651 (void) printf("%.3s %.3s%3d %.2d:%.2d:%.2d ",
652 wn, mn,
653 timeptr->tm_mday, timeptr->tm_hour,
654 timeptr->tm_min, timeptr->tm_sec);
655#define DIVISOR 10
656 trail = timeptr->tm_year % DIVISOR + TM_YEAR_BASE % DIVISOR;
657 lead = timeptr->tm_year / DIVISOR + TM_YEAR_BASE / DIVISOR +
658 trail / DIVISOR;
659 trail %= DIVISOR;
660 if (trail < 0 && lead > 0) {
661 trail += DIVISOR;
662 --lead;
663 } else if (lead < 0 && trail > 0) {
664 trail -= DIVISOR;
665 ++lead;
666 }
667 if (lead == 0)
668 (void) printf("%d", trail);
669 else (void) printf("%d%d", lead, ((trail < 0) ? -trail : trail));
670}