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 30#ifndef FALSE 31#define FALSE 0 32#endif /* !defined FALSE */ 33 34#ifndef EXIT_SUCCESS 35#define EXIT_SUCCESS 0 36#endif /* !defined EXIT_SUCCESS */ 37 38#ifndef EXIT_FAILURE 39#define EXIT_FAILURE 1 40#endif /* !defined EXIT_FAILURE */ 41 42#ifndef SECSPERMIN 43#define SECSPERMIN 60 44#endif /* !defined SECSPERMIN */ 45 46#ifndef MINSPERHOUR 47#define MINSPERHOUR 60 48#endif /* !defined MINSPERHOUR */ 49 50#ifndef SECSPERHOUR 51#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR) 52#endif /* !defined SECSPERHOUR */ 53 54#ifndef HOURSPERDAY 55#define HOURSPERDAY 24 56#endif /* !defined HOURSPERDAY */ 57 58#ifndef EPOCH_YEAR 59#define EPOCH_YEAR 1970 60#endif /* !defined EPOCH_YEAR */ 61 62#ifndef TM_YEAR_BASE 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 42#ifndef FALSE 43#define FALSE 0 44#endif /* !defined FALSE */ 45 46#ifndef EXIT_SUCCESS 47#define EXIT_SUCCESS 0 48#endif /* !defined EXIT_SUCCESS */ 49 50#ifndef EXIT_FAILURE 51#define EXIT_FAILURE 1 52#endif /* !defined EXIT_FAILURE */ 53 54#ifndef SECSPERMIN 55#define SECSPERMIN 60 56#endif /* !defined SECSPERMIN */ 57 58#ifndef MINSPERHOUR 59#define MINSPERHOUR 60 60#endif /* !defined MINSPERHOUR */ 61 62#ifndef SECSPERHOUR 63#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR) 64#endif /* !defined SECSPERHOUR */ 65 66#ifndef HOURSPERDAY 67#define HOURSPERDAY 24 68#endif /* !defined HOURSPERDAY */ 69 70#ifndef EPOCH_YEAR 71#define EPOCH_YEAR 1970 72#endif /* !defined EPOCH_YEAR */ 73 74#ifndef TM_YEAR_BASE 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")); 206 to = 0; 207 (void) strcpy(fakeenv[to++], "TZ="); 208 for (from = 0; environ[from] != NULL; ++from) 209 if (strncmp(environ[from], "TZ=", 3) != 0) 210 fakeenv[to++] = environ[from]; 211 fakeenv[to] = NULL; 212 environ = fakeenv; 213 } 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")); 323 to = 0; 324 (void) strcpy(fakeenv[to++], "TZ="); 325 for (from = 0; environ[from] != NULL; ++from) 326 if (strncmp(environ[from], "TZ=", 3) != 0) 327 fakeenv[to++] = environ[from]; 328 fakeenv[to] = NULL; 329 environ = fakeenv; 330 } 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}
|
| |