1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/intl/icu/source/tools/tzcode/zdump.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1039 @@ 1.4 +static char elsieid[] = "@(#)zdump.c 8.8"; 1.5 + 1.6 +/* 1.7 +** This code has been made independent of the rest of the time 1.8 +** conversion package to increase confidence in the verification it provides. 1.9 +** You can use this code to help in verifying other implementations. 1.10 +*/ 1.11 + 1.12 +/* 1.13 + * ICU note: Mr. Arthur David Olson (olsona@dc37a.nci.nih.gov) stated that 1.14 + * "zdump.c is indeed in the public domain" in e-mail on Feb 22, 2007. 1.15 + * This version of zdump.c is modified by ICU team to change output format 1.16 + * and some additional options. 1.17 + */ 1.18 + 1.19 + 1.20 +#include "stdio.h" /* for stdout, stderr, perror */ 1.21 +#include "string.h" /* for strcpy */ 1.22 +#include "sys/types.h" /* for time_t */ 1.23 +#include "time.h" /* for struct tm */ 1.24 +#include "stdlib.h" /* for exit, malloc, atoi */ 1.25 +#include "float.h" /* for FLT_MAX and DBL_MAX */ 1.26 +#include "ctype.h" /* for isalpha et al. */ 1.27 + 1.28 +/* Enable extensions and modifications for ICU. */ 1.29 +#define ICU 1.30 + 1.31 +#ifdef ICU 1.32 +#include "dirent.h" 1.33 +#endif 1.34 + 1.35 +#ifndef isascii 1.36 +#define isascii(x) 1 1.37 +#endif /* !defined isascii */ 1.38 + 1.39 +#ifndef ZDUMP_LO_YEAR 1.40 +#define ZDUMP_LO_YEAR (-500) 1.41 +#endif /* !defined ZDUMP_LO_YEAR */ 1.42 + 1.43 +#ifndef ZDUMP_HI_YEAR 1.44 +#define ZDUMP_HI_YEAR 2500 1.45 +#endif /* !defined ZDUMP_HI_YEAR */ 1.46 + 1.47 +#ifndef MAX_STRING_LENGTH 1.48 +#define MAX_STRING_LENGTH 1024 1.49 +#endif /* !defined MAX_STRING_LENGTH */ 1.50 + 1.51 +#ifndef TRUE 1.52 +#define TRUE 1 1.53 +#endif /* !defined TRUE */ 1.54 + 1.55 +#ifndef FALSE 1.56 +#define FALSE 0 1.57 +#endif /* !defined FALSE */ 1.58 + 1.59 +#ifndef EXIT_SUCCESS 1.60 +#define EXIT_SUCCESS 0 1.61 +#endif /* !defined EXIT_SUCCESS */ 1.62 + 1.63 +#ifndef EXIT_FAILURE 1.64 +#define EXIT_FAILURE 1 1.65 +#endif /* !defined EXIT_FAILURE */ 1.66 + 1.67 +#ifndef SECSPERMIN 1.68 +#define SECSPERMIN 60 1.69 +#endif /* !defined SECSPERMIN */ 1.70 + 1.71 +#ifndef MINSPERHOUR 1.72 +#define MINSPERHOUR 60 1.73 +#endif /* !defined MINSPERHOUR */ 1.74 + 1.75 +#ifndef SECSPERHOUR 1.76 +#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR) 1.77 +#endif /* !defined SECSPERHOUR */ 1.78 + 1.79 +#ifndef HOURSPERDAY 1.80 +#define HOURSPERDAY 24 1.81 +#endif /* !defined HOURSPERDAY */ 1.82 + 1.83 +#ifndef EPOCH_YEAR 1.84 +#define EPOCH_YEAR 1970 1.85 +#endif /* !defined EPOCH_YEAR */ 1.86 + 1.87 +#ifndef TM_YEAR_BASE 1.88 +#define TM_YEAR_BASE 1900 1.89 +#endif /* !defined TM_YEAR_BASE */ 1.90 + 1.91 +#ifndef DAYSPERNYEAR 1.92 +#define DAYSPERNYEAR 365 1.93 +#endif /* !defined DAYSPERNYEAR */ 1.94 + 1.95 +#ifndef isleap 1.96 +#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0)) 1.97 +#endif /* !defined isleap */ 1.98 + 1.99 +#ifndef isleap_sum 1.100 +/* 1.101 +** See tzfile.h for details on isleap_sum. 1.102 +*/ 1.103 +#define isleap_sum(a, b) isleap((a) % 400 + (b) % 400) 1.104 +#endif /* !defined isleap_sum */ 1.105 + 1.106 +#define SECSPERDAY ((long) SECSPERHOUR * HOURSPERDAY) 1.107 +#define SECSPERNYEAR (SECSPERDAY * DAYSPERNYEAR) 1.108 +#define SECSPERLYEAR (SECSPERNYEAR + SECSPERDAY) 1.109 + 1.110 +#ifndef HAVE_GETTEXT 1.111 +#define HAVE_GETTEXT 0 1.112 +#endif 1.113 +#if HAVE_GETTEXT 1.114 +#include "locale.h" /* for setlocale */ 1.115 +#include "libintl.h" 1.116 +#endif /* HAVE_GETTEXT */ 1.117 + 1.118 +#ifndef GNUC_or_lint 1.119 +#ifdef lint 1.120 +#define GNUC_or_lint 1.121 +#else /* !defined lint */ 1.122 +#ifdef __GNUC__ 1.123 +#define GNUC_or_lint 1.124 +#endif /* defined __GNUC__ */ 1.125 +#endif /* !defined lint */ 1.126 +#endif /* !defined GNUC_or_lint */ 1.127 + 1.128 +#ifndef INITIALIZE 1.129 +#ifdef GNUC_or_lint 1.130 +#define INITIALIZE(x) ((x) = 0) 1.131 +#else /* !defined GNUC_or_lint */ 1.132 +#define INITIALIZE(x) 1.133 +#endif /* !defined GNUC_or_lint */ 1.134 +#endif /* !defined INITIALIZE */ 1.135 + 1.136 +/* 1.137 +** For the benefit of GNU folk... 1.138 +** `_(MSGID)' uses the current locale's message library string for MSGID. 1.139 +** The default is to use gettext if available, and use MSGID otherwise. 1.140 +*/ 1.141 + 1.142 +#ifndef _ 1.143 +#if HAVE_GETTEXT 1.144 +#define _(msgid) gettext(msgid) 1.145 +#else /* !HAVE_GETTEXT */ 1.146 +#define _(msgid) msgid 1.147 +#endif /* !HAVE_GETTEXT */ 1.148 +#endif /* !defined _ */ 1.149 + 1.150 +#ifndef TZ_DOMAIN 1.151 +#define TZ_DOMAIN "tz" 1.152 +#endif /* !defined TZ_DOMAIN */ 1.153 + 1.154 +extern char ** environ; 1.155 +extern int getopt(int argc, char * const argv[], 1.156 + const char * options); 1.157 +extern char * optarg; 1.158 +extern int optind; 1.159 +extern char * tzname[2]; 1.160 + 1.161 +static time_t absolute_min_time; 1.162 +static time_t absolute_max_time; 1.163 +static size_t longest; 1.164 +static char * progname; 1.165 +static int warned; 1.166 + 1.167 +static char * abbr(struct tm * tmp); 1.168 +static void abbrok(const char * abbrp, const char * zone); 1.169 +static long delta(struct tm * newp, struct tm * oldp); 1.170 +static void dumptime(const struct tm * tmp); 1.171 +static time_t hunt(char * name, time_t lot, time_t hit); 1.172 +static void setabsolutes(void); 1.173 +static void show(char * zone, time_t t, int v); 1.174 +static const char * tformat(void); 1.175 +static time_t yeartot(long y); 1.176 +#ifdef ICU 1.177 +typedef struct listentry { 1.178 + char * name; 1.179 + struct listentry * next; 1.180 +} listentry; 1.181 + 1.182 +static time_t huntICU(char * name, time_t lot, time_t hit, FILE *fp); 1.183 +static void dumptimeICU(FILE * fp, time_t t); 1.184 +static void showICU(FILE * fp, char * zone, time_t t1, time_t t2); 1.185 +static int getall(struct listentry ** namelist); 1.186 +static void getzones(char * basedir, char * subdir, struct listentry ** last, int * count); 1.187 +#endif 1.188 + 1.189 +#ifndef TYPECHECK 1.190 +#define my_localtime localtime 1.191 +#else /* !defined TYPECHECK */ 1.192 +static struct tm * 1.193 +my_localtime(tp) 1.194 +time_t * tp; 1.195 +{ 1.196 + register struct tm * tmp; 1.197 + 1.198 + tmp = localtime(tp); 1.199 + if (tp != NULL && tmp != NULL) { 1.200 + struct tm tm; 1.201 + register time_t t; 1.202 + 1.203 + tm = *tmp; 1.204 + t = mktime(&tm); 1.205 + if (t - *tp >= 1 || *tp - t >= 1) { 1.206 + (void) fflush(stdout); 1.207 + (void) fprintf(stderr, "\n%s: ", progname); 1.208 + (void) fprintf(stderr, tformat(), *tp); 1.209 + (void) fprintf(stderr, " ->"); 1.210 + (void) fprintf(stderr, " year=%d", tmp->tm_year); 1.211 + (void) fprintf(stderr, " mon=%d", tmp->tm_mon); 1.212 + (void) fprintf(stderr, " mday=%d", tmp->tm_mday); 1.213 + (void) fprintf(stderr, " hour=%d", tmp->tm_hour); 1.214 + (void) fprintf(stderr, " min=%d", tmp->tm_min); 1.215 + (void) fprintf(stderr, " sec=%d", tmp->tm_sec); 1.216 + (void) fprintf(stderr, " isdst=%d", tmp->tm_isdst); 1.217 + (void) fprintf(stderr, " -> "); 1.218 + (void) fprintf(stderr, tformat(), t); 1.219 + (void) fprintf(stderr, "\n"); 1.220 + } 1.221 + } 1.222 + return tmp; 1.223 +} 1.224 +#endif /* !defined TYPECHECK */ 1.225 + 1.226 +static void 1.227 +abbrok(abbrp, zone) 1.228 +const char * const abbrp; 1.229 +const char * const zone; 1.230 +{ 1.231 + register const char * cp; 1.232 + register char * wp; 1.233 + 1.234 + if (warned) 1.235 + return; 1.236 + cp = abbrp; 1.237 + wp = NULL; 1.238 + while (isascii((unsigned char) *cp) && isalpha((unsigned char) *cp)) 1.239 + ++cp; 1.240 + if (cp - abbrp == 0) 1.241 + wp = _("lacks alphabetic at start"); 1.242 + else if (cp - abbrp < 3) 1.243 + wp = _("has fewer than 3 alphabetics"); 1.244 + else if (cp - abbrp > 6) 1.245 + wp = _("has more than 6 alphabetics"); 1.246 + if (wp == NULL && (*cp == '+' || *cp == '-')) { 1.247 + ++cp; 1.248 + if (isascii((unsigned char) *cp) && 1.249 + isdigit((unsigned char) *cp)) 1.250 + if (*cp++ == '1' && *cp >= '0' && *cp <= '4') 1.251 + ++cp; 1.252 + if (*cp != '\0') 1.253 + wp = _("differs from POSIX standard"); 1.254 + } 1.255 + if (wp == NULL) 1.256 + return; 1.257 + (void) fflush(stdout); 1.258 + (void) fprintf(stderr, 1.259 + _("%s: warning: zone \"%s\" abbreviation \"%s\" %s\n"), 1.260 + progname, zone, abbrp, wp); 1.261 + warned = TRUE; 1.262 +} 1.263 + 1.264 +static void 1.265 +usage(const char *progname, FILE *stream, int status) 1.266 +{ 1.267 + (void) fprintf(stream, 1.268 +_("%s: usage is %s [ --version ] [ --help ] [ -v ] [ -c [loyear,]hiyear ] zonename ...\n\ 1.269 +\n\ 1.270 +Report bugs to tz@elsie.nci.nih.gov.\n"), 1.271 + progname, progname); 1.272 + exit(status); 1.273 +} 1.274 + 1.275 +int 1.276 +main(argc, argv) 1.277 +int argc; 1.278 +char * argv[]; 1.279 +{ 1.280 + register int i; 1.281 + register int c; 1.282 + register int vflag; 1.283 + register char * cutarg; 1.284 + register long cutloyear = ZDUMP_LO_YEAR; 1.285 + register long cuthiyear = ZDUMP_HI_YEAR; 1.286 + register time_t cutlotime; 1.287 + register time_t cuthitime; 1.288 + register char ** fakeenv; 1.289 + time_t now; 1.290 + time_t t; 1.291 + time_t newt; 1.292 + struct tm tm; 1.293 + struct tm newtm; 1.294 + register struct tm * tmp; 1.295 + register struct tm * newtmp; 1.296 +#ifdef ICU 1.297 + int nextopt; 1.298 + char * dirarg; 1.299 + int aflag; 1.300 + int iflag; 1.301 + listentry * namelist = NULL; 1.302 + FILE * fp = stdout; 1.303 +#endif 1.304 + 1.305 + INITIALIZE(cutlotime); 1.306 + INITIALIZE(cuthitime); 1.307 +#if HAVE_GETTEXT 1.308 + (void) setlocale(LC_ALL, ""); 1.309 +#ifdef TZ_DOMAINDIR 1.310 + (void) bindtextdomain(TZ_DOMAIN, TZ_DOMAINDIR); 1.311 +#endif /* defined TEXTDOMAINDIR */ 1.312 + (void) textdomain(TZ_DOMAIN); 1.313 +#endif /* HAVE_GETTEXT */ 1.314 + progname = argv[0]; 1.315 + for (i = 1; i < argc; ++i) 1.316 + if (strcmp(argv[i], "--version") == 0) { 1.317 + (void) printf("%s\n", elsieid); 1.318 + exit(EXIT_SUCCESS); 1.319 + } else if (strcmp(argv[i], "--help") == 0) { 1.320 + usage(progname, stdout, EXIT_SUCCESS); 1.321 + } 1.322 + vflag = 0; 1.323 + cutarg = NULL; 1.324 +#ifdef ICU 1.325 + aflag = 0; 1.326 + iflag = 0; 1.327 + dirarg = NULL; 1.328 + nextopt = 1; 1.329 + while(nextopt) { 1.330 + c = getopt(argc, argv, "ac:d:iv"); 1.331 + switch(c) { 1.332 + case 'a': 1.333 + aflag = 1; 1.334 + break; 1.335 + case 'c': 1.336 + cutarg = optarg; 1.337 + break; 1.338 + case 'd': 1.339 + dirarg = optarg; 1.340 + break; 1.341 + case 'i': 1.342 + iflag = 1; 1.343 + break; 1.344 + case 'v': 1.345 + vflag = 1; 1.346 + break; 1.347 + default: 1.348 + nextopt = 0; 1.349 + break; 1.350 + } 1.351 + } 1.352 + if ((c != EOF && c != -1) || 1.353 + (optind == argc - 1 && strcmp(argv[optind], "=") == 0)) { 1.354 + (void) fprintf(stderr, 1.355 + _("%s: usage is %s [ --version ] [ -a ] [ -v ] [ -i ] [ -c [loyear,]hiyear ] [ -d dir ] [ zonename ... ]\n"), 1.356 + progname, progname); 1.357 + exit(EXIT_FAILURE); 1.358 + } 1.359 + 1.360 + if (dirarg != NULL) { 1.361 + DIR * dp; 1.362 + /* create the output directory */ 1.363 + mkdir(dirarg, 0777); 1.364 + if ((dp = opendir(dirarg)) == NULL) { 1.365 + fprintf(stderr, "cannot create the target directory"); 1.366 + exit(EXIT_FAILURE); 1.367 + } 1.368 + closedir(dp); 1.369 + } 1.370 +#else 1.371 + while ((c = getopt(argc, argv, "c:v")) == 'c' || c == 'v') 1.372 + if (c == 'v') 1.373 + vflag = 1; 1.374 + else cutarg = optarg; 1.375 + if ((c != EOF && c != -1) || 1.376 + (optind == argc - 1 && strcmp(argv[optind], "=") == 0)) { 1.377 + usage(progname, stderr, EXIT_FAILURE); 1.378 + } 1.379 +#endif 1.380 + if (vflag) { 1.381 + if (cutarg != NULL) { 1.382 + long lo; 1.383 + long hi; 1.384 + char dummy; 1.385 + 1.386 + if (sscanf(cutarg, "%ld%c", &hi, &dummy) == 1) { 1.387 + cuthiyear = hi; 1.388 + } else if (sscanf(cutarg, "%ld,%ld%c", 1.389 + &lo, &hi, &dummy) == 2) { 1.390 + cutloyear = lo; 1.391 + cuthiyear = hi; 1.392 + } else { 1.393 +(void) fprintf(stderr, _("%s: wild -c argument %s\n"), 1.394 + progname, cutarg); 1.395 + exit(EXIT_FAILURE); 1.396 + } 1.397 + } 1.398 + setabsolutes(); 1.399 + cutlotime = yeartot(cutloyear); 1.400 + cuthitime = yeartot(cuthiyear); 1.401 + } 1.402 + 1.403 +#ifdef ICU 1.404 + if (aflag) { 1.405 + /* get all available zones */ 1.406 + char ** fakeargv; 1.407 + int i; 1.408 + int count; 1.409 + 1.410 + count = getall(&namelist); 1.411 + 1.412 + fakeargv = (char **) malloc((size_t) (argc + count) * sizeof *argv); 1.413 + /* 1.414 + if ((fakeargv = (char **) malloc((size_t) (argc + count) * sizeof *argv)) == NULL) { 1.415 + exit(EXIT_FAILURE); 1.416 + } 1.417 + */ 1.418 + for (i = 0; i < argc; i++) { 1.419 + fakeargv[i] = argv[i]; 1.420 + } 1.421 + for (i = 0; i < count; i++) { 1.422 + fakeargv[i + argc] = namelist->name; 1.423 + namelist = namelist->next; 1.424 + } 1.425 + argv = fakeargv; 1.426 + argc += count; 1.427 + } 1.428 +#endif 1.429 + (void) time(&now); 1.430 + longest = 0; 1.431 + for (i = optind; i < argc; ++i) 1.432 + if (strlen(argv[i]) > longest) 1.433 + longest = strlen(argv[i]); 1.434 + { 1.435 + register int from; 1.436 + register int to; 1.437 + 1.438 + for (i = 0; environ[i] != NULL; ++i) 1.439 + continue; 1.440 + fakeenv = (char **) malloc((size_t) ((i + 2) * 1.441 + sizeof *fakeenv)); 1.442 + if (fakeenv == NULL || 1.443 + (fakeenv[0] = (char *) malloc(longest + 4)) == NULL) { 1.444 + (void) perror(progname); 1.445 + exit(EXIT_FAILURE); 1.446 + } 1.447 + to = 0; 1.448 + (void) strcpy(fakeenv[to++], "TZ="); 1.449 + for (from = 0; environ[from] != NULL; ++from) 1.450 + if (strncmp(environ[from], "TZ=", 3) != 0) 1.451 + fakeenv[to++] = environ[from]; 1.452 + fakeenv[to] = NULL; 1.453 + environ = fakeenv; 1.454 + } 1.455 + for (i = optind; i < argc; ++i) { 1.456 + static char buf[MAX_STRING_LENGTH]; 1.457 + 1.458 + (void) strcpy(&fakeenv[0][3], argv[i]); 1.459 + if (!vflag) { 1.460 + show(argv[i], now, FALSE); 1.461 + continue; 1.462 + } 1.463 +#ifdef ICU 1.464 + fp = NULL; 1.465 + if (iflag) { 1.466 + if (dirarg == NULL) { 1.467 + /* we want to display a zone name here */ 1.468 + if (i != optind) { 1.469 + printf("\n"); 1.470 + } 1.471 + printf("ZONE: %s\n", argv[i]); 1.472 + } else { 1.473 + int zstart; 1.474 + char path[FILENAME_MAX + 1]; 1.475 + strcpy(path, dirarg); 1.476 + strcat(path, "/"); 1.477 + zstart = strlen(path); 1.478 + strcat(path, argv[i]); 1.479 + /* replace '/' with '-' */ 1.480 + while(path[++zstart] != 0) { 1.481 + if (path[zstart] == '/') { 1.482 + path[zstart] = '-'; 1.483 + } 1.484 + } 1.485 + if ((fp = fopen(path, "w")) == NULL) { 1.486 + fprintf(stderr, "cannot create output file %s\n", path); 1.487 + exit(EXIT_FAILURE); 1.488 + } 1.489 + } 1.490 + } 1.491 +#endif 1.492 + warned = FALSE; 1.493 + t = absolute_min_time; 1.494 +#ifdef ICU 1.495 + /* skip displaying info for the lowest time, which is actually not 1.496 + * a transition when -i option is set */ 1.497 + if (!iflag) { 1.498 +#endif 1.499 + show(argv[i], t, TRUE); 1.500 + t += SECSPERHOUR * HOURSPERDAY; 1.501 + show(argv[i], t, TRUE); 1.502 +#ifdef ICU 1.503 + } 1.504 +#endif 1.505 + if (t < cutlotime) 1.506 + t = cutlotime; 1.507 + tmp = my_localtime(&t); 1.508 + if (tmp != NULL) { 1.509 + tm = *tmp; 1.510 + (void) strncpy(buf, abbr(&tm), (sizeof buf) - 1); 1.511 + } 1.512 + for ( ; ; ) { 1.513 + if (t >= cuthitime || t >= cuthitime - SECSPERHOUR * 12) 1.514 + break; 1.515 + newt = t + SECSPERHOUR * 12; 1.516 + newtmp = localtime(&newt); 1.517 + if (newtmp != NULL) 1.518 + newtm = *newtmp; 1.519 +#ifdef ICU 1.520 + if (iflag) { 1.521 + /* We do not want to capture transitions just for 1.522 + * abbreviated zone name changes */ 1.523 + if ((tmp == NULL || newtmp == NULL) ? (tmp != newtmp) : 1.524 + (delta(&newtm, &tm) != (newt - t) || 1.525 + newtm.tm_isdst != tm.tm_isdst)) { 1.526 + newt = huntICU(argv[i], t, newt, fp); 1.527 + newtmp = localtime(&newt); 1.528 + if (newtmp != NULL) { 1.529 + newtm = *newtmp; 1.530 + (void) strncpy(buf, 1.531 + abbr(&newtm), 1.532 + (sizeof buf) - 1); 1.533 + } 1.534 + } 1.535 + } else { 1.536 +#endif 1.537 + if ((tmp == NULL || newtmp == NULL) ? (tmp != newtmp) : 1.538 + (delta(&newtm, &tm) != (newt - t) || 1.539 + newtm.tm_isdst != tm.tm_isdst || 1.540 + strcmp(abbr(&newtm), buf) != 0)) { 1.541 + newt = hunt(argv[i], t, newt); 1.542 + newtmp = localtime(&newt); 1.543 + if (newtmp != NULL) { 1.544 + newtm = *newtmp; 1.545 + (void) strncpy(buf, 1.546 + abbr(&newtm), 1.547 + (sizeof buf) - 1); 1.548 + } 1.549 + } 1.550 +#ifdef ICU 1.551 + } 1.552 +#endif 1.553 + t = newt; 1.554 + tm = newtm; 1.555 + tmp = newtmp; 1.556 + } 1.557 +#ifdef ICU 1.558 + if (!iflag) { 1.559 + /* skip displaying info for the highest time, which is actually not 1.560 + * a transition when -i option is used*/ 1.561 +#endif 1.562 + t = absolute_max_time; 1.563 + t -= SECSPERHOUR * HOURSPERDAY; 1.564 + show(argv[i], t, TRUE); 1.565 + t += SECSPERHOUR * HOURSPERDAY; 1.566 + show(argv[i], t, TRUE); 1.567 + 1.568 +#ifdef ICU 1.569 + } 1.570 + /* close file */ 1.571 + if (fp != NULL) { 1.572 + fclose(fp); 1.573 + } 1.574 +#endif 1.575 + } 1.576 + if (fflush(stdout) || ferror(stdout)) { 1.577 + (void) fprintf(stderr, "%s: ", progname); 1.578 + (void) perror(_("Error writing to standard output")); 1.579 + exit(EXIT_FAILURE); 1.580 + } 1.581 +#ifdef ICU 1.582 + if (aflag) { 1.583 + struct listentry * entry = namelist; 1.584 + struct listentry * next; 1.585 + while (entry != NULL) { 1.586 + free(entry->name); 1.587 + next = entry->next; 1.588 + free(entry); 1.589 + entry = next; 1.590 + } 1.591 + } 1.592 +#endif 1.593 + exit(EXIT_SUCCESS); 1.594 + /* If exit fails to exit... */ 1.595 + return EXIT_FAILURE; 1.596 +} 1.597 + 1.598 +static void 1.599 +setabsolutes(void) 1.600 +{ 1.601 + if (0.5 == (time_t) 0.5) { 1.602 + /* 1.603 + ** time_t is floating. 1.604 + */ 1.605 + if (sizeof (time_t) == sizeof (float)) { 1.606 + absolute_min_time = (time_t) -FLT_MAX; 1.607 + absolute_max_time = (time_t) FLT_MAX; 1.608 + } else if (sizeof (time_t) == sizeof (double)) { 1.609 + absolute_min_time = (time_t) -DBL_MAX; 1.610 + absolute_max_time = (time_t) DBL_MAX; 1.611 + } else { 1.612 + (void) fprintf(stderr, 1.613 +_("%s: use of -v on system with floating time_t other than float or double\n"), 1.614 + progname); 1.615 + exit(EXIT_FAILURE); 1.616 + } 1.617 + } else if (0 > (time_t) -1) { 1.618 + /* 1.619 + ** time_t is signed. Assume overflow wraps around. 1.620 + */ 1.621 + time_t t = 0; 1.622 + time_t t1 = 1; 1.623 + 1.624 + while (t < t1) { 1.625 + t = t1; 1.626 + t1 = 2 * t1 + 1; 1.627 + } 1.628 + 1.629 + absolute_max_time = t; 1.630 + t = -t; 1.631 + absolute_min_time = t - 1; 1.632 + if (t < absolute_min_time) 1.633 + absolute_min_time = t; 1.634 + } else { 1.635 + /* 1.636 + ** time_t is unsigned. 1.637 + */ 1.638 + absolute_min_time = 0; 1.639 + absolute_max_time = absolute_min_time - 1; 1.640 + } 1.641 +} 1.642 + 1.643 +static time_t 1.644 +yeartot(y) 1.645 +const long y; 1.646 +{ 1.647 + register long myy; 1.648 + register long seconds; 1.649 + register time_t t; 1.650 + 1.651 + myy = EPOCH_YEAR; 1.652 + t = 0; 1.653 + while (myy != y) { 1.654 + if (myy < y) { 1.655 + seconds = isleap(myy) ? SECSPERLYEAR : SECSPERNYEAR; 1.656 + ++myy; 1.657 + if (t > absolute_max_time - seconds) { 1.658 + t = absolute_max_time; 1.659 + break; 1.660 + } 1.661 + t += seconds; 1.662 + } else { 1.663 + --myy; 1.664 + seconds = isleap(myy) ? SECSPERLYEAR : SECSPERNYEAR; 1.665 + if (t < absolute_min_time + seconds) { 1.666 + t = absolute_min_time; 1.667 + break; 1.668 + } 1.669 + t -= seconds; 1.670 + } 1.671 + } 1.672 + return t; 1.673 +} 1.674 + 1.675 +static time_t 1.676 +hunt(char *name, time_t lot, time_t hit) 1.677 +{ 1.678 + time_t t; 1.679 + long diff; 1.680 + struct tm lotm; 1.681 + register struct tm * lotmp; 1.682 + struct tm tm; 1.683 + register struct tm * tmp; 1.684 + char loab[MAX_STRING_LENGTH]; 1.685 + 1.686 + lotmp = my_localtime(&lot); 1.687 + if (lotmp != NULL) { 1.688 + lotm = *lotmp; 1.689 + (void) strncpy(loab, abbr(&lotm), (sizeof loab) - 1); 1.690 + } 1.691 + for ( ; ; ) { 1.692 + diff = (long) (hit - lot); 1.693 + if (diff < 2) 1.694 + break; 1.695 + t = lot; 1.696 + t += diff / 2; 1.697 + if (t <= lot) 1.698 + ++t; 1.699 + else if (t >= hit) 1.700 + --t; 1.701 + tmp = my_localtime(&t); 1.702 + if (tmp != NULL) 1.703 + tm = *tmp; 1.704 + if ((lotmp == NULL || tmp == NULL) ? (lotmp == tmp) : 1.705 + (delta(&tm, &lotm) == (t - lot) && 1.706 + tm.tm_isdst == lotm.tm_isdst && 1.707 + strcmp(abbr(&tm), loab) == 0)) { 1.708 + lot = t; 1.709 + lotm = tm; 1.710 + lotmp = tmp; 1.711 + } else hit = t; 1.712 + } 1.713 + show(name, lot, TRUE); 1.714 + show(name, hit, TRUE); 1.715 + return hit; 1.716 +} 1.717 + 1.718 +/* 1.719 +** Thanks to Paul Eggert for logic used in delta. 1.720 +*/ 1.721 + 1.722 +static long 1.723 +delta(newp, oldp) 1.724 +struct tm * newp; 1.725 +struct tm * oldp; 1.726 +{ 1.727 + register long result; 1.728 + register int tmy; 1.729 + 1.730 + if (newp->tm_year < oldp->tm_year) 1.731 + return -delta(oldp, newp); 1.732 + result = 0; 1.733 + for (tmy = oldp->tm_year; tmy < newp->tm_year; ++tmy) 1.734 + result += DAYSPERNYEAR + isleap_sum(tmy, TM_YEAR_BASE); 1.735 + result += newp->tm_yday - oldp->tm_yday; 1.736 + result *= HOURSPERDAY; 1.737 + result += newp->tm_hour - oldp->tm_hour; 1.738 + result *= MINSPERHOUR; 1.739 + result += newp->tm_min - oldp->tm_min; 1.740 + result *= SECSPERMIN; 1.741 + result += newp->tm_sec - oldp->tm_sec; 1.742 + return result; 1.743 +} 1.744 + 1.745 +static void 1.746 +show(char *zone, time_t t, int v) 1.747 +{ 1.748 + register struct tm * tmp; 1.749 + 1.750 + (void) printf("%-*s ", (int) longest, zone); 1.751 + if (v) { 1.752 + tmp = gmtime(&t); 1.753 + if (tmp == NULL) { 1.754 + (void) printf(tformat(), t); 1.755 + } else { 1.756 + dumptime(tmp); 1.757 + (void) printf(" UTC"); 1.758 + } 1.759 + (void) printf(" = "); 1.760 + } 1.761 + tmp = my_localtime(&t); 1.762 + dumptime(tmp); 1.763 + if (tmp != NULL) { 1.764 + if (*abbr(tmp) != '\0') 1.765 + (void) printf(" %s", abbr(tmp)); 1.766 + if (v) { 1.767 + (void) printf(" isdst=%d", tmp->tm_isdst); 1.768 +#ifdef TM_GMTOFF 1.769 + (void) printf(" gmtoff=%ld", tmp->TM_GMTOFF); 1.770 +#endif /* defined TM_GMTOFF */ 1.771 + } 1.772 + } 1.773 + (void) printf("\n"); 1.774 + if (tmp != NULL && *abbr(tmp) != '\0') 1.775 + abbrok(abbr(tmp), zone); 1.776 +} 1.777 + 1.778 +static char * 1.779 +abbr(tmp) 1.780 +struct tm * tmp; 1.781 +{ 1.782 + register char * result; 1.783 + static char nada; 1.784 + 1.785 + if (tmp->tm_isdst != 0 && tmp->tm_isdst != 1) 1.786 + return &nada; 1.787 + result = tzname[tmp->tm_isdst]; 1.788 + return (result == NULL) ? &nada : result; 1.789 +} 1.790 + 1.791 +/* 1.792 +** The code below can fail on certain theoretical systems; 1.793 +** it works on all known real-world systems as of 2004-12-30. 1.794 +*/ 1.795 + 1.796 +static const char * 1.797 +tformat(void) 1.798 +{ 1.799 + if (0.5 == (time_t) 0.5) { /* floating */ 1.800 + if (sizeof (time_t) > sizeof (double)) 1.801 + return "%Lg"; 1.802 + return "%g"; 1.803 + } 1.804 + if (0 > (time_t) -1) { /* signed */ 1.805 + if (sizeof (time_t) > sizeof (long)) 1.806 + return "%lld"; 1.807 + if (sizeof (time_t) > sizeof (int)) 1.808 + return "%ld"; 1.809 + return "%d"; 1.810 + } 1.811 + if (sizeof (time_t) > sizeof (unsigned long)) 1.812 + return "%llu"; 1.813 + if (sizeof (time_t) > sizeof (unsigned int)) 1.814 + return "%lu"; 1.815 + return "%u"; 1.816 +} 1.817 + 1.818 +static void 1.819 +dumptime(timeptr) 1.820 +register const struct tm * timeptr; 1.821 +{ 1.822 + static const char wday_name[][3] = { 1.823 + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" 1.824 + }; 1.825 + static const char mon_name[][3] = { 1.826 + "Jan", "Feb", "Mar", "Apr", "May", "Jun", 1.827 + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" 1.828 + }; 1.829 + register const char * wn; 1.830 + register const char * mn; 1.831 + register int lead; 1.832 + register int trail; 1.833 + 1.834 + if (timeptr == NULL) { 1.835 + (void) printf("NULL"); 1.836 + return; 1.837 + } 1.838 + /* 1.839 + ** The packaged versions of localtime and gmtime never put out-of-range 1.840 + ** values in tm_wday or tm_mon, but since this code might be compiled 1.841 + ** with other (perhaps experimental) versions, paranoia is in order. 1.842 + */ 1.843 + if (timeptr->tm_wday < 0 || timeptr->tm_wday >= 1.844 + (int) (sizeof wday_name / sizeof wday_name[0])) 1.845 + wn = "???"; 1.846 + else wn = wday_name[timeptr->tm_wday]; 1.847 + if (timeptr->tm_mon < 0 || timeptr->tm_mon >= 1.848 + (int) (sizeof mon_name / sizeof mon_name[0])) 1.849 + mn = "???"; 1.850 + else mn = mon_name[timeptr->tm_mon]; 1.851 + (void) printf("%.3s %.3s%3d %.2d:%.2d:%.2d ", 1.852 + wn, mn, 1.853 + timeptr->tm_mday, timeptr->tm_hour, 1.854 + timeptr->tm_min, timeptr->tm_sec); 1.855 +#define DIVISOR 10 1.856 + trail = timeptr->tm_year % DIVISOR + TM_YEAR_BASE % DIVISOR; 1.857 + lead = timeptr->tm_year / DIVISOR + TM_YEAR_BASE / DIVISOR + 1.858 + trail / DIVISOR; 1.859 + trail %= DIVISOR; 1.860 + if (trail < 0 && lead > 0) { 1.861 + trail += DIVISOR; 1.862 + --lead; 1.863 + } else if (lead < 0 && trail > 0) { 1.864 + trail -= DIVISOR; 1.865 + ++lead; 1.866 + } 1.867 + if (lead == 0) 1.868 + (void) printf("%d", trail); 1.869 + else (void) printf("%d%d", lead, ((trail < 0) ? -trail : trail)); 1.870 +} 1.871 + 1.872 +#ifdef ICU 1.873 +static time_t 1.874 +huntICU(char *name, time_t lot, time_t hit, FILE * fp) 1.875 +{ 1.876 + time_t t; 1.877 + long diff; 1.878 + struct tm lotm; 1.879 + register struct tm * lotmp; 1.880 + struct tm tm; 1.881 + register struct tm * tmp; 1.882 + char loab[MAX_STRING_LENGTH]; 1.883 + 1.884 + lotmp = my_localtime(&lot); 1.885 + if (lotmp != NULL) { 1.886 + lotm = *lotmp; 1.887 + (void) strncpy(loab, abbr(&lotm), (sizeof loab) - 1); 1.888 + } 1.889 + for ( ; ; ) { 1.890 + diff = (long) (hit - lot); 1.891 + if (diff < 2) 1.892 + break; 1.893 + t = lot; 1.894 + t += diff / 2; 1.895 + if (t <= lot) 1.896 + ++t; 1.897 + else if (t >= hit) 1.898 + --t; 1.899 + tmp = my_localtime(&t); 1.900 + if (tmp != NULL) 1.901 + tm = *tmp; 1.902 + /* We do not want to capture transitions just for 1.903 + * abbreviated zone name changes */ 1.904 + if ((lotmp == NULL || tmp == NULL) ? (lotmp == tmp) : 1.905 + (delta(&tm, &lotm) == (t - lot) && 1.906 + tm.tm_isdst == lotm.tm_isdst)) { 1.907 + lot = t; 1.908 + lotm = tm; 1.909 + lotmp = tmp; 1.910 + } else hit = t; 1.911 + } 1.912 + showICU(fp, name, lot, hit); 1.913 + return hit; 1.914 +} 1.915 + 1.916 +static void showICU(FILE * fp, char *zone, time_t t1, time_t t2) 1.917 +{ 1.918 + if (fp == NULL) { 1.919 + fp = stdout; 1.920 + } 1.921 + dumptimeICU(fp, t1); 1.922 + fprintf(fp, " > "); 1.923 + dumptimeICU(fp, t2); 1.924 + fprintf(fp, "\n"); 1.925 +} 1.926 + 1.927 +static void dumptimeICU(FILE * fp, time_t t) 1.928 +{ 1.929 + static const char wday_name[][3] = { 1.930 + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" 1.931 + }; 1.932 + struct tm gmt; 1.933 + struct tm loc; 1.934 + register int lead; 1.935 + register int trail; 1.936 + long offset; 1.937 + long hour, min, sec; 1.938 + 1.939 + loc = *my_localtime(&t); 1.940 + 1.941 + trail = loc.tm_year % DIVISOR + TM_YEAR_BASE % DIVISOR; 1.942 + lead = loc.tm_year / DIVISOR + TM_YEAR_BASE / DIVISOR + trail / DIVISOR; 1.943 + trail %= DIVISOR; 1.944 + if (trail < 0 && lead > 0) { 1.945 + trail += DIVISOR; 1.946 + --lead; 1.947 + } else if (lead < 0 && trail > 0) { 1.948 + trail -= DIVISOR; 1.949 + ++lead; 1.950 + } 1.951 + 1.952 + fprintf(fp, "%04d-%02d-%02d", lead * DIVISOR + trail, loc.tm_mon + 1, loc.tm_mday); 1.953 + fprintf(fp, " %.3s ", wday_name[loc.tm_wday]); 1.954 + fprintf(fp, "%02d:%02d:%02d", loc.tm_hour, loc.tm_min, loc.tm_sec); 1.955 + 1.956 + gmt = *gmtime(&t); 1.957 + offset = delta(&loc, &gmt); 1.958 + if (offset < 0) { 1.959 + offset = -offset; 1.960 + fprintf(fp, "-"); 1.961 + } else { 1.962 + fprintf(fp, "+"); 1.963 + } 1.964 + 1.965 + sec = offset % 60; 1.966 + offset = (offset - sec) / 60; 1.967 + min = offset % 60; 1.968 + hour = offset / 60; 1.969 + 1.970 + fprintf(fp, "%02d", hour); 1.971 + fprintf(fp, "%02d", min); 1.972 + fprintf(fp, "%02d", sec); 1.973 + fprintf(fp, "[DST=%d]", loc.tm_isdst); 1.974 +} 1.975 + 1.976 +static int getall(struct listentry ** namelist) { 1.977 + int count = 0; 1.978 + struct listentry dummyentry; 1.979 + struct listentry * last = &dummyentry; 1.980 + 1.981 + getzones(TZDIR, NULL, &last, &count); 1.982 + if (count > 0) { 1.983 + *namelist = dummyentry.next; 1.984 + } 1.985 + 1.986 + return count; 1.987 +} 1.988 + 1.989 +static void getzones(char * basedir, char * relpath, struct listentry ** last, int * count) { 1.990 + char path[FILENAME_MAX + 1]; 1.991 + struct dirent * dir; 1.992 + DIR * dp; 1.993 + 1.994 + strcpy(path, basedir); 1.995 + if (relpath != NULL) { 1.996 + strcat(path, "/"); 1.997 + strcat(path, relpath); 1.998 + } 1.999 + 1.1000 + if ((dp = opendir(path)) == NULL) { 1.1001 + /* file */ 1.1002 + if (strstr(relpath, ".tab") == NULL && strcmp(relpath, "Etc/Unknown") != 0) { 1.1003 + char * pzonename; 1.1004 + listentry * pentry; 1.1005 + 1.1006 + if ((pzonename = malloc(strlen(relpath) + 1)) == NULL) { 1.1007 + exit(EXIT_FAILURE); 1.1008 + } 1.1009 + strcpy(pzonename, relpath); 1.1010 + 1.1011 + if ((pentry = malloc(sizeof(listentry))) == NULL) { 1.1012 + exit(EXIT_FAILURE); 1.1013 + } 1.1014 + 1.1015 + pentry->name = pzonename; 1.1016 + pentry->next = NULL; 1.1017 + (*last)->next = pentry; 1.1018 + *last = pentry; 1.1019 + (*count)++; 1.1020 + } 1.1021 + } else { 1.1022 + /* directory */ 1.1023 + while ((dir = readdir(dp)) != NULL) { 1.1024 + char subpath[FILENAME_MAX + 1]; 1.1025 + 1.1026 + if (strcmp(dir->d_name, ".") == 0 1.1027 + || strcmp(dir->d_name, "..") == 0) { 1.1028 + continue; 1.1029 + } 1.1030 + if (relpath != NULL) { 1.1031 + strcpy(subpath, relpath); 1.1032 + strcat(subpath, "/"); 1.1033 + strcat(subpath, dir->d_name); 1.1034 + } else { 1.1035 + strcpy(subpath, dir->d_name); 1.1036 + } 1.1037 + getzones(basedir, subpath, last, count); 1.1038 + } 1.1039 + closedir(dp); 1.1040 + } 1.1041 +} 1.1042 +#endif