Index: icu46/source/tools/tzcode/zdump.c |
=================================================================== |
--- icu46/source/tools/tzcode/zdump.c (revision 0) |
+++ icu46/source/tools/tzcode/zdump.c (revision 0) |
@@ -0,0 +1,1039 @@ |
+static char elsieid[] = "@(#)zdump.c 8.8"; |
+ |
+/* |
+** This code has been made independent of the rest of the time |
+** conversion package to increase confidence in the verification it provides. |
+** You can use this code to help in verifying other implementations. |
+*/ |
+ |
+/* |
+ * ICU note: Mr. Arthur David Olson (olsona@dc37a.nci.nih.gov) stated that |
+ * "zdump.c is indeed in the public domain" in e-mail on Feb 22, 2007. |
+ * This version of zdump.c is modified by ICU team to change output format |
+ * and some additional options. |
+ */ |
+ |
+ |
+#include "stdio.h" /* for stdout, stderr, perror */ |
+#include "string.h" /* for strcpy */ |
+#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 */ |
+#include "ctype.h" /* for isalpha et al. */ |
+ |
+/* Enable extensions and modifications for ICU. */ |
+#define ICU |
+ |
+#ifdef ICU |
+#include "dirent.h" |
+#endif |
+ |
+#ifndef isascii |
+#define isascii(x) 1 |
+#endif /* !defined isascii */ |
+ |
+#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 |
+#endif /* !defined MAX_STRING_LENGTH */ |
+ |
+#ifndef TRUE |
+#define TRUE 1 |
+#endif /* !defined TRUE */ |
+ |
+#ifndef FALSE |
+#define FALSE 0 |
+#endif /* !defined FALSE */ |
+ |
+#ifndef EXIT_SUCCESS |
+#define EXIT_SUCCESS 0 |
+#endif /* !defined EXIT_SUCCESS */ |
+ |
+#ifndef EXIT_FAILURE |
+#define EXIT_FAILURE 1 |
+#endif /* !defined EXIT_FAILURE */ |
+ |
+#ifndef SECSPERMIN |
+#define SECSPERMIN 60 |
+#endif /* !defined SECSPERMIN */ |
+ |
+#ifndef MINSPERHOUR |
+#define MINSPERHOUR 60 |
+#endif /* !defined MINSPERHOUR */ |
+ |
+#ifndef SECSPERHOUR |
+#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR) |
+#endif /* !defined SECSPERHOUR */ |
+ |
+#ifndef HOURSPERDAY |
+#define HOURSPERDAY 24 |
+#endif /* !defined HOURSPERDAY */ |
+ |
+#ifndef EPOCH_YEAR |
+#define EPOCH_YEAR 1970 |
+#endif /* !defined EPOCH_YEAR */ |
+ |
+#ifndef TM_YEAR_BASE |
+#define TM_YEAR_BASE 1900 |
+#endif /* !defined TM_YEAR_BASE */ |
+ |
+#ifndef DAYSPERNYEAR |
+#define DAYSPERNYEAR 365 |
+#endif /* !defined DAYSPERNYEAR */ |
+ |
+#ifndef isleap |
+#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0)) |
+#endif /* !defined isleap */ |
+ |
+#ifndef isleap_sum |
+/* |
+** See tzfile.h for details on isleap_sum. |
+*/ |
+#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) |
+ |
+#ifndef HAVE_GETTEXT |
+#define HAVE_GETTEXT 0 |
+#endif |
+#if HAVE_GETTEXT |
+#include "locale.h" /* for setlocale */ |
+#include "libintl.h" |
+#endif /* HAVE_GETTEXT */ |
+ |
+#ifndef GNUC_or_lint |
+#ifdef lint |
+#define GNUC_or_lint |
+#else /* !defined lint */ |
+#ifdef __GNUC__ |
+#define GNUC_or_lint |
+#endif /* defined __GNUC__ */ |
+#endif /* !defined lint */ |
+#endif /* !defined GNUC_or_lint */ |
+ |
+#ifndef INITIALIZE |
+#ifdef GNUC_or_lint |
+#define INITIALIZE(x) ((x) = 0) |
+#else /* !defined GNUC_or_lint */ |
+#define INITIALIZE(x) |
+#endif /* !defined GNUC_or_lint */ |
+#endif /* !defined INITIALIZE */ |
+ |
+/* |
+** For the benefit of GNU folk... |
+** `_(MSGID)' uses the current locale's message library string for MSGID. |
+** The default is to use gettext if available, and use MSGID otherwise. |
+*/ |
+ |
+#ifndef _ |
+#if HAVE_GETTEXT |
+#define _(msgid) gettext(msgid) |
+#else /* !HAVE_GETTEXT */ |
+#define _(msgid) msgid |
+#endif /* !HAVE_GETTEXT */ |
+#endif /* !defined _ */ |
+ |
+#ifndef TZ_DOMAIN |
+#define TZ_DOMAIN "tz" |
+#endif /* !defined TZ_DOMAIN */ |
+ |
+extern char ** environ; |
+extern int getopt(int argc, char * const argv[], |
+ const char * options); |
+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 int warned; |
+ |
+static char * abbr(struct tm * tmp); |
+static void abbrok(const char * abbrp, const char * zone); |
+static long delta(struct tm * newp, struct tm * oldp); |
+static void dumptime(const struct tm * tmp); |
+static time_t hunt(char * name, time_t lot, time_t hit); |
+static void setabsolutes(void); |
+static void show(char * zone, time_t t, int v); |
+static const char * tformat(void); |
+static time_t yeartot(long y); |
+#ifdef ICU |
+typedef struct listentry { |
+ char * name; |
+ struct listentry * next; |
+} listentry; |
+ |
+static time_t huntICU(char * name, time_t lot, time_t hit, FILE *fp); |
+static void dumptimeICU(FILE * fp, time_t t); |
+static void showICU(FILE * fp, char * zone, time_t t1, time_t t2); |
+static int getall(struct listentry ** namelist); |
+static void getzones(char * basedir, char * subdir, struct listentry ** last, int * count); |
+#endif |
+ |
+#ifndef TYPECHECK |
+#define my_localtime localtime |
+#else /* !defined TYPECHECK */ |
+static struct tm * |
+my_localtime(tp) |
+time_t * tp; |
+{ |
+ register struct tm * tmp; |
+ |
+ tmp = localtime(tp); |
+ if (tp != NULL && tmp != NULL) { |
+ struct tm tm; |
+ register time_t t; |
+ |
+ tm = *tmp; |
+ t = mktime(&tm); |
+ if (t - *tp >= 1 || *tp - t >= 1) { |
+ (void) fflush(stdout); |
+ (void) fprintf(stderr, "\n%s: ", progname); |
+ (void) fprintf(stderr, tformat(), *tp); |
+ (void) fprintf(stderr, " ->"); |
+ (void) fprintf(stderr, " year=%d", tmp->tm_year); |
+ (void) fprintf(stderr, " mon=%d", tmp->tm_mon); |
+ (void) fprintf(stderr, " mday=%d", tmp->tm_mday); |
+ (void) fprintf(stderr, " hour=%d", tmp->tm_hour); |
+ (void) fprintf(stderr, " min=%d", tmp->tm_min); |
+ (void) fprintf(stderr, " sec=%d", tmp->tm_sec); |
+ (void) fprintf(stderr, " isdst=%d", tmp->tm_isdst); |
+ (void) fprintf(stderr, " -> "); |
+ (void) fprintf(stderr, tformat(), t); |
+ (void) fprintf(stderr, "\n"); |
+ } |
+ } |
+ return tmp; |
+} |
+#endif /* !defined TYPECHECK */ |
+ |
+static void |
+abbrok(abbrp, zone) |
+const char * const abbrp; |
+const char * const zone; |
+{ |
+ register const char * cp; |
+ register char * wp; |
+ |
+ if (warned) |
+ return; |
+ cp = abbrp; |
+ wp = NULL; |
+ while (isascii((unsigned char) *cp) && isalpha((unsigned char) *cp)) |
+ ++cp; |
+ if (cp - abbrp == 0) |
+ wp = _("lacks alphabetic at start"); |
+ else if (cp - abbrp < 3) |
+ wp = _("has fewer than 3 alphabetics"); |
+ else if (cp - abbrp > 6) |
+ wp = _("has more than 6 alphabetics"); |
+ if (wp == NULL && (*cp == '+' || *cp == '-')) { |
+ ++cp; |
+ if (isascii((unsigned char) *cp) && |
+ isdigit((unsigned char) *cp)) |
+ if (*cp++ == '1' && *cp >= '0' && *cp <= '4') |
+ ++cp; |
+ if (*cp != '\0') |
+ wp = _("differs from POSIX standard"); |
+ } |
+ if (wp == NULL) |
+ return; |
+ (void) fflush(stdout); |
+ (void) fprintf(stderr, |
+ _("%s: warning: zone \"%s\" abbreviation \"%s\" %s\n"), |
+ progname, zone, abbrp, wp); |
+ warned = TRUE; |
+} |
+ |
+static void |
+usage(const char *progname, FILE *stream, int status) |
+{ |
+ (void) fprintf(stream, |
+_("%s: usage is %s [ --version ] [ --help ] [ -v ] [ -c [loyear,]hiyear ] zonename ...\n\ |
+\n\ |
+Report bugs to tz@elsie.nci.nih.gov.\n"), |
+ progname, progname); |
+ exit(status); |
+} |
+ |
+int |
+main(argc, argv) |
+int argc; |
+char * argv[]; |
+{ |
+ register int i; |
+ register int c; |
+ register int vflag; |
+ 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; |
+ struct tm tm; |
+ struct tm newtm; |
+ register struct tm * tmp; |
+ register struct tm * newtmp; |
+#ifdef ICU |
+ int nextopt; |
+ char * dirarg; |
+ int aflag; |
+ int iflag; |
+ listentry * namelist = NULL; |
+ FILE * fp = stdout; |
+#endif |
+ |
+ INITIALIZE(cutlotime); |
+ INITIALIZE(cuthitime); |
+#if HAVE_GETTEXT |
+ (void) setlocale(LC_ALL, ""); |
+#ifdef TZ_DOMAINDIR |
+ (void) bindtextdomain(TZ_DOMAIN, TZ_DOMAINDIR); |
+#endif /* defined TEXTDOMAINDIR */ |
+ (void) textdomain(TZ_DOMAIN); |
+#endif /* HAVE_GETTEXT */ |
+ progname = argv[0]; |
+ for (i = 1; i < argc; ++i) |
+ if (strcmp(argv[i], "--version") == 0) { |
+ (void) printf("%s\n", elsieid); |
+ exit(EXIT_SUCCESS); |
+ } else if (strcmp(argv[i], "--help") == 0) { |
+ usage(progname, stdout, EXIT_SUCCESS); |
+ } |
+ vflag = 0; |
+ cutarg = NULL; |
+#ifdef ICU |
+ aflag = 0; |
+ iflag = 0; |
+ dirarg = NULL; |
+ nextopt = 1; |
+ while(nextopt) { |
+ c = getopt(argc, argv, "ac:d:iv"); |
+ switch(c) { |
+ case 'a': |
+ aflag = 1; |
+ break; |
+ case 'c': |
+ cutarg = optarg; |
+ break; |
+ case 'd': |
+ dirarg = optarg; |
+ break; |
+ case 'i': |
+ iflag = 1; |
+ break; |
+ case 'v': |
+ vflag = 1; |
+ break; |
+ default: |
+ nextopt = 0; |
+ break; |
+ } |
+ } |
+ if ((c != EOF && c != -1) || |
+ (optind == argc - 1 && strcmp(argv[optind], "=") == 0)) { |
+ (void) fprintf(stderr, |
+ _("%s: usage is %s [ --version ] [ -a ] [ -v ] [ -i ] [ -c [loyear,]hiyear ] [ -d dir ] [ zonename ... ]\n"), |
+ progname, progname); |
+ exit(EXIT_FAILURE); |
+ } |
+ |
+ if (dirarg != NULL) { |
+ DIR * dp; |
+ /* create the output directory */ |
+ mkdir(dirarg, 0777); |
+ if ((dp = opendir(dirarg)) == NULL) { |
+ fprintf(stderr, "cannot create the target directory"); |
+ exit(EXIT_FAILURE); |
+ } |
+ closedir(dp); |
+ } |
+#else |
+ while ((c = getopt(argc, argv, "c:v")) == 'c' || c == 'v') |
+ if (c == 'v') |
+ vflag = 1; |
+ else cutarg = optarg; |
+ if ((c != EOF && c != -1) || |
+ (optind == argc - 1 && strcmp(argv[optind], "=") == 0)) { |
+ usage(progname, stderr, EXIT_FAILURE); |
+ } |
+#endif |
+ if (vflag) { |
+ if (cutarg != NULL) { |
+ long lo; |
+ long hi; |
+ char dummy; |
+ |
+ if (sscanf(cutarg, "%ld%c", &hi, &dummy) == 1) { |
+ cuthiyear = hi; |
+ } else if (sscanf(cutarg, "%ld,%ld%c", |
+ &lo, &hi, &dummy) == 2) { |
+ cutloyear = lo; |
+ cuthiyear = hi; |
+ } else { |
+(void) fprintf(stderr, _("%s: wild -c argument %s\n"), |
+ progname, cutarg); |
+ exit(EXIT_FAILURE); |
+ } |
+ } |
+ setabsolutes(); |
+ cutlotime = yeartot(cutloyear); |
+ cuthitime = yeartot(cuthiyear); |
+ } |
+ |
+#ifdef ICU |
+ if (aflag) { |
+ /* get all available zones */ |
+ char ** fakeargv; |
+ int i; |
+ int count; |
+ |
+ count = getall(&namelist); |
+ |
+ fakeargv = (char **) malloc((size_t) (argc + count) * sizeof *argv); |
+ /* |
+ if ((fakeargv = (char **) malloc((size_t) (argc + count) * sizeof *argv)) == NULL) { |
+ exit(EXIT_FAILURE); |
+ } |
+ */ |
+ for (i = 0; i < argc; i++) { |
+ fakeargv[i] = argv[i]; |
+ } |
+ for (i = 0; i < count; i++) { |
+ fakeargv[i + argc] = namelist->name; |
+ namelist = namelist->next; |
+ } |
+ argv = fakeargv; |
+ argc += count; |
+ } |
+#endif |
+ (void) time(&now); |
+ longest = 0; |
+ for (i = optind; i < argc; ++i) |
+ if (strlen(argv[i]) > longest) |
+ longest = strlen(argv[i]); |
+ { |
+ register int from; |
+ register int to; |
+ |
+ for (i = 0; environ[i] != NULL; ++i) |
+ continue; |
+ fakeenv = (char **) malloc((size_t) ((i + 2) * |
+ sizeof *fakeenv)); |
+ if (fakeenv == NULL || |
+ (fakeenv[0] = (char *) malloc(longest + 4)) == NULL) { |
+ (void) perror(progname); |
+ exit(EXIT_FAILURE); |
+ } |
+ to = 0; |
+ (void) strcpy(fakeenv[to++], "TZ="); |
+ for (from = 0; environ[from] != NULL; ++from) |
+ if (strncmp(environ[from], "TZ=", 3) != 0) |
+ fakeenv[to++] = environ[from]; |
+ fakeenv[to] = NULL; |
+ environ = fakeenv; |
+ } |
+ for (i = optind; i < argc; ++i) { |
+ static char buf[MAX_STRING_LENGTH]; |
+ |
+ (void) strcpy(&fakeenv[0][3], argv[i]); |
+ if (!vflag) { |
+ show(argv[i], now, FALSE); |
+ continue; |
+ } |
+#ifdef ICU |
+ fp = NULL; |
+ if (iflag) { |
+ if (dirarg == NULL) { |
+ /* we want to display a zone name here */ |
+ if (i != optind) { |
+ printf("\n"); |
+ } |
+ printf("ZONE: %s\n", argv[i]); |
+ } else { |
+ int zstart; |
+ char path[FILENAME_MAX + 1]; |
+ strcpy(path, dirarg); |
+ strcat(path, "/"); |
+ zstart = strlen(path); |
+ strcat(path, argv[i]); |
+ /* replace '/' with '-' */ |
+ while(path[++zstart] != 0) { |
+ if (path[zstart] == '/') { |
+ path[zstart] = '-'; |
+ } |
+ } |
+ if ((fp = fopen(path, "w")) == NULL) { |
+ fprintf(stderr, "cannot create output file %s\n", path); |
+ exit(EXIT_FAILURE); |
+ } |
+ } |
+ } |
+#endif |
+ warned = FALSE; |
+ t = absolute_min_time; |
+#ifdef ICU |
+ /* skip displaying info for the lowest time, which is actually not |
+ * a transition when -i option is set */ |
+ if (!iflag) { |
+#endif |
+ show(argv[i], t, TRUE); |
+ t += SECSPERHOUR * HOURSPERDAY; |
+ show(argv[i], t, TRUE); |
+#ifdef ICU |
+ } |
+#endif |
+ if (t < cutlotime) |
+ t = cutlotime; |
+ tmp = my_localtime(&t); |
+ if (tmp != NULL) { |
+ tm = *tmp; |
+ (void) strncpy(buf, abbr(&tm), (sizeof buf) - 1); |
+ } |
+ for ( ; ; ) { |
+ if (t >= cuthitime || t >= cuthitime - SECSPERHOUR * 12) |
+ break; |
+ newt = t + SECSPERHOUR * 12; |
+ newtmp = localtime(&newt); |
+ if (newtmp != NULL) |
+ newtm = *newtmp; |
+#ifdef ICU |
+ if (iflag) { |
+ /* We do not want to capture transitions just for |
+ * abbreviated zone name changes */ |
+ if ((tmp == NULL || newtmp == NULL) ? (tmp != newtmp) : |
+ (delta(&newtm, &tm) != (newt - t) || |
+ newtm.tm_isdst != tm.tm_isdst)) { |
+ newt = huntICU(argv[i], t, newt, fp); |
+ newtmp = localtime(&newt); |
+ if (newtmp != NULL) { |
+ newtm = *newtmp; |
+ (void) strncpy(buf, |
+ abbr(&newtm), |
+ (sizeof buf) - 1); |
+ } |
+ } |
+ } else { |
+#endif |
+ if ((tmp == NULL || newtmp == NULL) ? (tmp != newtmp) : |
+ (delta(&newtm, &tm) != (newt - t) || |
+ newtm.tm_isdst != tm.tm_isdst || |
+ strcmp(abbr(&newtm), buf) != 0)) { |
+ newt = hunt(argv[i], t, newt); |
+ newtmp = localtime(&newt); |
+ if (newtmp != NULL) { |
+ newtm = *newtmp; |
+ (void) strncpy(buf, |
+ abbr(&newtm), |
+ (sizeof buf) - 1); |
+ } |
+ } |
+#ifdef ICU |
+ } |
+#endif |
+ t = newt; |
+ tm = newtm; |
+ tmp = newtmp; |
+ } |
+#ifdef ICU |
+ if (!iflag) { |
+ /* skip displaying info for the highest time, which is actually not |
+ * a transition when -i option is used*/ |
+#endif |
+ t = absolute_max_time; |
+ t -= SECSPERHOUR * HOURSPERDAY; |
+ show(argv[i], t, TRUE); |
+ t += SECSPERHOUR * HOURSPERDAY; |
+ show(argv[i], t, TRUE); |
+ |
+#ifdef ICU |
+ } |
+ /* close file */ |
+ if (fp != NULL) { |
+ fclose(fp); |
+ } |
+#endif |
+ } |
+ if (fflush(stdout) || ferror(stdout)) { |
+ (void) fprintf(stderr, "%s: ", progname); |
+ (void) perror(_("Error writing to standard output")); |
+ exit(EXIT_FAILURE); |
+ } |
+#ifdef ICU |
+ if (aflag) { |
+ struct listentry * entry = namelist; |
+ struct listentry * next; |
+ while (entry != NULL) { |
+ free(entry->name); |
+ next = entry->next; |
+ free(entry); |
+ entry = next; |
+ } |
+ } |
+#endif |
+ exit(EXIT_SUCCESS); |
+ /* If exit fails to exit... */ |
+ return EXIT_FAILURE; |
+} |
+ |
+static void |
+setabsolutes(void) |
+{ |
+ 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); |
+ exit(EXIT_FAILURE); |
+ } |
+ } else if (0 > (time_t) -1) { |
+ /* |
+ ** time_t is signed. Assume overflow wraps around. |
+ */ |
+ time_t t = 0; |
+ time_t t1 = 1; |
+ |
+ while (t < t1) { |
+ t = t1; |
+ t1 = 2 * t1 + 1; |
+ } |
+ |
+ absolute_max_time = t; |
+ t = -t; |
+ absolute_min_time = t - 1; |
+ if (t < absolute_min_time) |
+ absolute_min_time = t; |
+ } 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 |
+hunt(char *name, time_t lot, time_t hit) |
+{ |
+ time_t t; |
+ long diff; |
+ struct tm lotm; |
+ register struct tm * lotmp; |
+ struct tm tm; |
+ register struct tm * tmp; |
+ char loab[MAX_STRING_LENGTH]; |
+ |
+ lotmp = my_localtime(&lot); |
+ if (lotmp != NULL) { |
+ lotm = *lotmp; |
+ (void) strncpy(loab, abbr(&lotm), (sizeof loab) - 1); |
+ } |
+ for ( ; ; ) { |
+ diff = (long) (hit - lot); |
+ if (diff < 2) |
+ break; |
+ t = lot; |
+ t += diff / 2; |
+ if (t <= lot) |
+ ++t; |
+ else if (t >= hit) |
+ --t; |
+ tmp = my_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)) { |
+ lot = t; |
+ lotm = tm; |
+ lotmp = tmp; |
+ } else hit = t; |
+ } |
+ show(name, lot, TRUE); |
+ show(name, hit, TRUE); |
+ return hit; |
+} |
+ |
+/* |
+** Thanks to Paul Eggert for logic used in delta. |
+*/ |
+ |
+static long |
+delta(newp, oldp) |
+struct tm * newp; |
+struct tm * oldp; |
+{ |
+ register long result; |
+ register int tmy; |
+ |
+ if (newp->tm_year < oldp->tm_year) |
+ return -delta(oldp, newp); |
+ result = 0; |
+ for (tmy = oldp->tm_year; tmy < newp->tm_year; ++tmy) |
+ result += DAYSPERNYEAR + isleap_sum(tmy, TM_YEAR_BASE); |
+ result += newp->tm_yday - oldp->tm_yday; |
+ result *= HOURSPERDAY; |
+ result += newp->tm_hour - oldp->tm_hour; |
+ result *= MINSPERHOUR; |
+ result += newp->tm_min - oldp->tm_min; |
+ result *= SECSPERMIN; |
+ result += newp->tm_sec - oldp->tm_sec; |
+ return result; |
+} |
+ |
+static void |
+show(char *zone, time_t t, int v) |
+{ |
+ register struct tm * tmp; |
+ |
+ (void) printf("%-*s ", (int) longest, zone); |
+ if (v) { |
+ tmp = gmtime(&t); |
+ if (tmp == NULL) { |
+ (void) printf(tformat(), t); |
+ } else { |
+ dumptime(tmp); |
+ (void) printf(" UTC"); |
+ } |
+ (void) printf(" = "); |
+ } |
+ tmp = my_localtime(&t); |
+ dumptime(tmp); |
+ if (tmp != NULL) { |
+ if (*abbr(tmp) != '\0') |
+ (void) printf(" %s", abbr(tmp)); |
+ if (v) { |
+ (void) printf(" isdst=%d", tmp->tm_isdst); |
+#ifdef TM_GMTOFF |
+ (void) printf(" gmtoff=%ld", tmp->TM_GMTOFF); |
+#endif /* defined TM_GMTOFF */ |
+ } |
+ } |
+ (void) printf("\n"); |
+ if (tmp != NULL && *abbr(tmp) != '\0') |
+ abbrok(abbr(tmp), zone); |
+} |
+ |
+static char * |
+abbr(tmp) |
+struct tm * tmp; |
+{ |
+ register char * result; |
+ static char nada; |
+ |
+ if (tmp->tm_isdst != 0 && tmp->tm_isdst != 1) |
+ return &nada; |
+ result = tzname[tmp->tm_isdst]; |
+ return (result == NULL) ? &nada : result; |
+} |
+ |
+/* |
+** The code below can fail on certain theoretical systems; |
+** it works on all known real-world systems as of 2004-12-30. |
+*/ |
+ |
+static const char * |
+tformat(void) |
+{ |
+ if (0.5 == (time_t) 0.5) { /* floating */ |
+ if (sizeof (time_t) > sizeof (double)) |
+ return "%Lg"; |
+ return "%g"; |
+ } |
+ if (0 > (time_t) -1) { /* signed */ |
+ if (sizeof (time_t) > sizeof (long)) |
+ return "%lld"; |
+ if (sizeof (time_t) > sizeof (int)) |
+ return "%ld"; |
+ return "%d"; |
+ } |
+ if (sizeof (time_t) > sizeof (unsigned long)) |
+ return "%llu"; |
+ if (sizeof (time_t) > sizeof (unsigned int)) |
+ return "%lu"; |
+ return "%u"; |
+} |
+ |
+static void |
+dumptime(timeptr) |
+register const struct tm * timeptr; |
+{ |
+ static const char wday_name[][3] = { |
+ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" |
+ }; |
+ static const char mon_name[][3] = { |
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun", |
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" |
+ }; |
+ register const char * wn; |
+ register const char * mn; |
+ 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 |
+ ** with other (perhaps experimental) versions, paranoia is in order. |
+ */ |
+ if (timeptr->tm_wday < 0 || timeptr->tm_wday >= |
+ (int) (sizeof wday_name / sizeof wday_name[0])) |
+ wn = "???"; |
+ else wn = wday_name[timeptr->tm_wday]; |
+ if (timeptr->tm_mon < 0 || timeptr->tm_mon >= |
+ (int) (sizeof mon_name / sizeof mon_name[0])) |
+ mn = "???"; |
+ else mn = mon_name[timeptr->tm_mon]; |
+ (void) printf("%.3s %.3s%3d %.2d:%.2d:%.2d ", |
+ wn, mn, |
+ timeptr->tm_mday, timeptr->tm_hour, |
+ timeptr->tm_min, timeptr->tm_sec); |
+#define DIVISOR 10 |
+ trail = timeptr->tm_year % DIVISOR + TM_YEAR_BASE % DIVISOR; |
+ lead = timeptr->tm_year / DIVISOR + TM_YEAR_BASE / DIVISOR + |
+ trail / DIVISOR; |
+ trail %= DIVISOR; |
+ if (trail < 0 && lead > 0) { |
+ trail += DIVISOR; |
+ --lead; |
+ } else if (lead < 0 && trail > 0) { |
+ trail -= DIVISOR; |
+ ++lead; |
+ } |
+ if (lead == 0) |
+ (void) printf("%d", trail); |
+ else (void) printf("%d%d", lead, ((trail < 0) ? -trail : trail)); |
+} |
+ |
+#ifdef ICU |
+static time_t |
+huntICU(char *name, time_t lot, time_t hit, FILE * fp) |
+{ |
+ time_t t; |
+ long diff; |
+ struct tm lotm; |
+ register struct tm * lotmp; |
+ struct tm tm; |
+ register struct tm * tmp; |
+ char loab[MAX_STRING_LENGTH]; |
+ |
+ lotmp = my_localtime(&lot); |
+ if (lotmp != NULL) { |
+ lotm = *lotmp; |
+ (void) strncpy(loab, abbr(&lotm), (sizeof loab) - 1); |
+ } |
+ for ( ; ; ) { |
+ diff = (long) (hit - lot); |
+ if (diff < 2) |
+ break; |
+ t = lot; |
+ t += diff / 2; |
+ if (t <= lot) |
+ ++t; |
+ else if (t >= hit) |
+ --t; |
+ tmp = my_localtime(&t); |
+ if (tmp != NULL) |
+ tm = *tmp; |
+ /* We do not want to capture transitions just for |
+ * abbreviated zone name changes */ |
+ if ((lotmp == NULL || tmp == NULL) ? (lotmp == tmp) : |
+ (delta(&tm, &lotm) == (t - lot) && |
+ tm.tm_isdst == lotm.tm_isdst)) { |
+ lot = t; |
+ lotm = tm; |
+ lotmp = tmp; |
+ } else hit = t; |
+ } |
+ showICU(fp, name, lot, hit); |
+ return hit; |
+} |
+ |
+static void showICU(FILE * fp, char *zone, time_t t1, time_t t2) |
+{ |
+ if (fp == NULL) { |
+ fp = stdout; |
+ } |
+ dumptimeICU(fp, t1); |
+ fprintf(fp, " > "); |
+ dumptimeICU(fp, t2); |
+ fprintf(fp, "\n"); |
+} |
+ |
+static void dumptimeICU(FILE * fp, time_t t) |
+{ |
+ static const char wday_name[][3] = { |
+ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" |
+ }; |
+ struct tm gmt; |
+ struct tm loc; |
+ register int lead; |
+ register int trail; |
+ long offset; |
+ long hour, min, sec; |
+ |
+ loc = *my_localtime(&t); |
+ |
+ trail = loc.tm_year % DIVISOR + TM_YEAR_BASE % DIVISOR; |
+ lead = loc.tm_year / DIVISOR + TM_YEAR_BASE / DIVISOR + trail / DIVISOR; |
+ trail %= DIVISOR; |
+ if (trail < 0 && lead > 0) { |
+ trail += DIVISOR; |
+ --lead; |
+ } else if (lead < 0 && trail > 0) { |
+ trail -= DIVISOR; |
+ ++lead; |
+ } |
+ |
+ fprintf(fp, "%04d-%02d-%02d", lead * DIVISOR + trail, loc.tm_mon + 1, loc.tm_mday); |
+ fprintf(fp, " %.3s ", wday_name[loc.tm_wday]); |
+ fprintf(fp, "%02d:%02d:%02d", loc.tm_hour, loc.tm_min, loc.tm_sec); |
+ |
+ gmt = *gmtime(&t); |
+ offset = delta(&loc, &gmt); |
+ if (offset < 0) { |
+ offset = -offset; |
+ fprintf(fp, "-"); |
+ } else { |
+ fprintf(fp, "+"); |
+ } |
+ |
+ sec = offset % 60; |
+ offset = (offset - sec) / 60; |
+ min = offset % 60; |
+ hour = offset / 60; |
+ |
+ fprintf(fp, "%02d", hour); |
+ fprintf(fp, "%02d", min); |
+ fprintf(fp, "%02d", sec); |
+ fprintf(fp, "[DST=%d]", loc.tm_isdst); |
+} |
+ |
+static int getall(struct listentry ** namelist) { |
+ int count = 0; |
+ struct listentry dummyentry; |
+ struct listentry * last = &dummyentry; |
+ |
+ getzones(TZDIR, NULL, &last, &count); |
+ if (count > 0) { |
+ *namelist = dummyentry.next; |
+ } |
+ |
+ return count; |
+} |
+ |
+static void getzones(char * basedir, char * relpath, struct listentry ** last, int * count) { |
+ char path[FILENAME_MAX + 1]; |
+ struct dirent * dir; |
+ DIR * dp; |
+ |
+ strcpy(path, basedir); |
+ if (relpath != NULL) { |
+ strcat(path, "/"); |
+ strcat(path, relpath); |
+ } |
+ |
+ if ((dp = opendir(path)) == NULL) { |
+ /* file */ |
+ if (strstr(relpath, ".tab") == NULL) { |
+ char * pzonename; |
+ listentry * pentry; |
+ |
+ if ((pzonename = malloc(strlen(relpath) + 1)) == NULL) { |
+ exit(EXIT_FAILURE); |
+ } |
+ strcpy(pzonename, relpath); |
+ |
+ if ((pentry = malloc(sizeof(listentry))) == NULL) { |
+ exit(EXIT_FAILURE); |
+ } |
+ |
+ pentry->name = pzonename; |
+ pentry->next = NULL; |
+ (*last)->next = pentry; |
+ *last = pentry; |
+ (*count)++; |
+ } |
+ } else { |
+ /* directory */ |
+ while ((dir = readdir(dp)) != NULL) { |
+ char subpath[FILENAME_MAX + 1]; |
+ |
+ if (strcmp(dir->d_name, ".") == 0 |
+ || strcmp(dir->d_name, "..") == 0) { |
+ continue; |
+ } |
+ if (relpath != NULL) { |
+ strcpy(subpath, relpath); |
+ strcat(subpath, "/"); |
+ strcat(subpath, dir->d_name); |
+ } else { |
+ strcpy(subpath, dir->d_name); |
+ } |
+ getzones(basedir, subpath, last, count); |
+ } |
+ closedir(dp); |
+ } |
+} |
+#endif |
Property changes on: icu46/source/tools/tzcode/zdump.c |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |