ICU-10827 Updated ICU modified version of tzcode to 2014b level.

X-SVN-Rev: 35684
This commit is contained in:
Yoshito Umaoka 2014-05-02 23:24:38 +00:00
parent a45f7faf63
commit 114c7abe69
10 changed files with 1487 additions and 1259 deletions

View File

@ -9,12 +9,6 @@
** whereas the output of asctime is supposed to be constant. ** whereas the output of asctime is supposed to be constant.
*/ */
#ifndef lint
#ifndef NOID
static char elsieid[] = "@(#)asctime.c 8.2";
#endif /* !defined NOID */
#endif /* !defined lint */
/*LINTLIBRARY*/ /*LINTLIBRARY*/
#include "private.h" #include "private.h"
@ -75,9 +69,7 @@ static char buf_asctime[MAX_ASCTIME_BUF_SIZE];
*/ */
char * char *
asctime_r(timeptr, buf) asctime_r(register const struct tm *timeptr, char *buf)
register const struct tm * timeptr;
char * buf;
{ {
static const char wday_name[][3] = { static const char wday_name[][3] = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
@ -91,6 +83,10 @@ char * buf;
char year[INT_STRLEN_MAXIMUM(int) + 2]; char year[INT_STRLEN_MAXIMUM(int) + 2];
char result[MAX_ASCTIME_BUF_SIZE]; char result[MAX_ASCTIME_BUF_SIZE];
if (timeptr == NULL) {
errno = EINVAL;
return strcpy(buf, "??? ??? ?? ??:??:?? ????\n");
}
if (timeptr->tm_wday < 0 || timeptr->tm_wday >= DAYSPERWEEK) if (timeptr->tm_wday < 0 || timeptr->tm_wday >= DAYSPERWEEK)
wn = "???"; wn = "???";
else wn = wday_name[timeptr->tm_wday]; else wn = wday_name[timeptr->tm_wday];
@ -113,10 +109,9 @@ char * buf;
timeptr->tm_mday, timeptr->tm_hour, timeptr->tm_mday, timeptr->tm_hour,
timeptr->tm_min, timeptr->tm_sec, timeptr->tm_min, timeptr->tm_sec,
year); year);
if (strlen(result) < STD_ASCTIME_BUF_SIZE || buf == buf_asctime) { if (strlen(result) < STD_ASCTIME_BUF_SIZE || buf == buf_asctime)
(void) strcpy(buf, result); return strcpy(buf, result);
return buf; else {
} else {
#ifdef EOVERFLOW #ifdef EOVERFLOW
errno = EOVERFLOW; errno = EOVERFLOW;
#else /* !defined EOVERFLOW */ #else /* !defined EOVERFLOW */
@ -131,8 +126,7 @@ char * buf;
*/ */
char * char *
asctime(timeptr) asctime(register const struct tm *timeptr)
register const struct tm * timeptr;
{ {
return asctime_r(timeptr, buf_asctime); return asctime_r(timeptr, buf_asctime);
} }

View File

@ -3,49 +3,12 @@
** 2006-07-17 by Arthur David Olson. ** 2006-07-17 by Arthur David Olson.
*/ */
#ifndef lint
#ifndef NOID
static char elsieid[] = "@(#)ialloc.c 8.30";
#endif /* !defined NOID */
#endif /* !defined lint */
/*LINTLIBRARY*/ /*LINTLIBRARY*/
#include "private.h" #include "private.h"
#define nonzero(n) (((n) == 0) ? 1 : (n))
char * char *
imalloc(n) icatalloc(char *const old, const char *const new)
const int n;
{
return malloc((size_t) nonzero(n));
}
char *
icalloc(nelem, elsize)
int nelem;
int elsize;
{
if (nelem == 0 || elsize == 0)
nelem = elsize = 1;
return calloc((size_t) nelem, (size_t) elsize);
}
void *
irealloc(pointer, size)
void * const pointer;
const int size;
{
if (pointer == NULL)
return imalloc(size);
return realloc((void *) pointer, (size_t) nonzero(size));
}
char *
icatalloc(old, new)
char * const old;
const char * const new;
{ {
register char * result; register char * result;
register int oldsize, newsize; register int oldsize, newsize;
@ -56,31 +19,14 @@ const char * const new;
else if (newsize == 0) else if (newsize == 0)
return old; return old;
else oldsize = strlen(old); else oldsize = strlen(old);
if ((result = irealloc(old, oldsize + newsize + 1)) != NULL) if ((result = realloc(old, oldsize + newsize + 1)) != NULL)
if (new != NULL) if (new != NULL)
(void) strcpy(result + oldsize, new); (void) strcpy(result + oldsize, new);
return result; return result;
} }
char * char *
icpyalloc(string) icpyalloc(const char *const string)
const char * const string;
{ {
return icatalloc((char *) NULL, string); return icatalloc(NULL, string);
}
void
ifree(p)
char * const p;
{
if (p != NULL)
(void) free(p);
}
void
icfree(p)
char * const p;
{
if (p != NULL)
(void) free(p);
} }

View File

@ -1,7 +1,7 @@
/* /*
******************************************************************************* *******************************************************************************
* *
* Copyright (C) 2007, International Business Machines * Copyright (C) 2007-2014, International Business Machines
* Corporation and others. All Rights Reserved. * Corporation and others. All Rights Reserved.
* *
******************************************************************************* *******************************************************************************
@ -196,9 +196,6 @@ private:
hi = gcal->getTime(status); hi = gcal->getTime(status);
} }
void dumpZone(ostream& out, const char* linesep, UnicodeString tzid, int32_t low, int32_t high) {
}
TimeZone* timezone; TimeZone* timezone;
int32_t loyear; int32_t loyear;
int32_t hiyear; int32_t hiyear;

File diff suppressed because it is too large Load Diff

View File

@ -15,16 +15,6 @@
** Thank you! ** Thank you!
*/ */
/*
** ID
*/
#ifndef lint
#ifndef NOID
static char privatehid[] = "@(#)private.h 8.6";
#endif /* !defined NOID */
#endif /* !defined lint */
#define GRANDPARENTED "Local time zone must be set--see zic manual page" #define GRANDPARENTED "Local time zone must be set--see zic manual page"
/* /*
@ -44,6 +34,10 @@ static char privatehid[] = "@(#)private.h 8.6";
#define HAVE_INCOMPATIBLE_CTIME_R 0 #define HAVE_INCOMPATIBLE_CTIME_R 0
#endif /* !defined INCOMPATIBLE_CTIME_R */ #endif /* !defined INCOMPATIBLE_CTIME_R */
#ifndef HAVE_LINK
#define HAVE_LINK 1
#endif /* !defined HAVE_LINK */
#ifndef HAVE_SETTIMEOFDAY #ifndef HAVE_SETTIMEOFDAY
#define HAVE_SETTIMEOFDAY 3 #define HAVE_SETTIMEOFDAY 3
#endif /* !defined HAVE_SETTIMEOFDAY */ #endif /* !defined HAVE_SETTIMEOFDAY */
@ -134,19 +128,76 @@ static char privatehid[] = "@(#)private.h 8.6";
#include "stdint.h" #include "stdint.h"
#endif /* !HAVE_STDINT_H */ #endif /* !HAVE_STDINT_H */
#ifndef HAVE_INTTYPES_H
# define HAVE_INTTYPES_H HAVE_STDINT_H
#endif
#if HAVE_INTTYPES_H
# include <inttypes.h>
#endif
#ifndef INT_FAST64_MAX #ifndef INT_FAST64_MAX
/* Pre-C99 GCC compilers define __LONG_LONG_MAX__ instead of LLONG_MAX. */ /* Pre-C99 GCC compilers define __LONG_LONG_MAX__ instead of LLONG_MAX. */
#if defined LLONG_MAX || defined __LONG_LONG_MAX__ #if defined LLONG_MAX || defined __LONG_LONG_MAX__
typedef long long int_fast64_t; typedef long long int_fast64_t;
# ifdef LLONG_MAX
# define INT_FAST64_MIN LLONG_MIN
# define INT_FAST64_MAX LLONG_MAX
# else
# define INT_FAST64_MIN __LONG_LONG_MIN__
# define INT_FAST64_MAX __LONG_LONG_MAX__
# endif
# define SCNdFAST64 "lld"
#else /* ! (defined LLONG_MAX || defined __LONG_LONG_MAX__) */ #else /* ! (defined LLONG_MAX || defined __LONG_LONG_MAX__) */
#if (LONG_MAX >> 31) < 0xffffffff #if (LONG_MAX >> 31) < 0xffffffff
Please use a compiler that supports a 64-bit integer type (or wider); Please use a compiler that supports a 64-bit integer type (or wider);
you may need to compile with "-DHAVE_STDINT_H". you may need to compile with "-DHAVE_STDINT_H".
#endif /* (LONG_MAX >> 31) < 0xffffffff */ #endif /* (LONG_MAX >> 31) < 0xffffffff */
typedef long int_fast64_t; typedef long int_fast64_t;
# define INT_FAST64_MIN LONG_MIN
# define INT_FAST64_MAX LONG_MAX
# define SCNdFAST64 "ld"
#endif /* ! (defined LLONG_MAX || defined __LONG_LONG_MAX__) */ #endif /* ! (defined LLONG_MAX || defined __LONG_LONG_MAX__) */
#endif /* !defined INT_FAST64_MAX */ #endif /* !defined INT_FAST64_MAX */
#ifndef INT_FAST32_MAX
# if INT_MAX >> 31 == 0
typedef long int_fast32_t;
# else
typedef int int_fast32_t;
# endif
#endif
#ifndef INTMAX_MAX
# if defined LLONG_MAX || defined __LONG_LONG_MAX__
typedef long long intmax_t;
# define strtoimax strtoll
# define PRIdMAX "lld"
# ifdef LLONG_MAX
# define INTMAX_MAX LLONG_MAX
# define INTMAX_MIN LLONG_MIN
# else
# define INTMAX_MAX __LONG_LONG_MAX__
# define INTMAX_MIN __LONG_LONG_MIN__
# endif
# else
typedef long intmax_t;
# define strtoimax strtol
# define PRIdMAX "ld"
# define INTMAX_MAX LONG_MAX
# define INTMAX_MIN LONG_MIN
# endif
#endif
#ifndef UINTMAX_MAX
# if defined ULLONG_MAX || defined __LONG_LONG_MAX__
typedef unsigned long long uintmax_t;
# define PRIuMAX "llu"
# else
typedef unsigned long uintmax_t;
# define PRIuMAX "lu"
# endif
#endif
#ifndef INT32_MAX #ifndef INT32_MAX
#define INT32_MAX 0x7fffffff #define INT32_MAX 0x7fffffff
#endif /* !defined INT32_MAX */ #endif /* !defined INT32_MAX */
@ -154,6 +205,32 @@ typedef long int_fast64_t;
#define INT32_MIN (-1 - INT32_MAX) #define INT32_MIN (-1 - INT32_MAX)
#endif /* !defined INT32_MIN */ #endif /* !defined INT32_MIN */
#ifndef SIZE_MAX
#define SIZE_MAX ((size_t) -1)
#endif
#if 2 < __GNUC__ + (96 <= __GNUC_MINOR__)
# define ATTRIBUTE_CONST __attribute__ ((const))
# define ATTRIBUTE_PURE __attribute__ ((__pure__))
# define ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec))
#else
# define ATTRIBUTE_CONST /* empty */
# define ATTRIBUTE_PURE /* empty */
# define ATTRIBUTE_FORMAT(spec) /* empty */
#endif
#if !defined _Noreturn && __STDC_VERSION__ < 201112
# if 2 < __GNUC__ + (8 <= __GNUC_MINOR__)
# define _Noreturn __attribute__ ((__noreturn__))
# else
# define _Noreturn
# endif
#endif
#if __STDC_VERSION__ < 199901 && !defined restrict
# define restrict /* empty */
#endif
/* /*
** Workarounds for compilers/systems. ** Workarounds for compilers/systems.
*/ */
@ -168,17 +245,64 @@ typedef long int_fast64_t;
extern char * asctime_r(struct tm const *, char *); extern char * asctime_r(struct tm const *, char *);
#endif #endif
/*
** Compile with -Dtime_tz=T to build the tz package with a private
** time_t type equivalent to T rather than the system-supplied time_t.
** This debugging feature can test unusual design decisions
** (e.g., time_t wider than 'long', or unsigned time_t) even on
** typical platforms.
*/
#ifdef time_tz
static time_t sys_time(time_t *x) { return time(x); }
# undef ctime
# define ctime tz_ctime
# undef ctime_r
# define ctime_r tz_ctime_r
# undef difftime
# define difftime tz_difftime
# undef gmtime
# define gmtime tz_gmtime
# undef gmtime_r
# define gmtime_r tz_gmtime_r
# undef localtime
# define localtime tz_localtime
# undef localtime_r
# define localtime_r tz_localtime_r
# undef mktime
# define mktime tz_mktime
# undef time
# define time tz_time
# undef time_t
# define time_t tz_time_t
typedef time_tz time_t;
char *ctime(time_t const *);
char *ctime_r(time_t const *, char *);
double difftime(time_t, time_t);
struct tm *gmtime(time_t const *);
struct tm *gmtime_r(time_t const *restrict, struct tm *restrict);
struct tm *localtime(time_t const *);
struct tm *localtime_r(time_t const *restrict, struct tm *restrict);
time_t mktime(struct tm *);
static time_t
time(time_t *p)
{
time_t r = sys_time(0);
if (p)
*p = r;
return r;
}
#endif
/* /*
** Private function declarations. ** Private function declarations.
*/ */
char * icalloc(int nelem, int elsize);
char * icatalloc(char * old, const char * new); char * icatalloc(char * old, const char * new);
char * icpyalloc(const char * string); char * icpyalloc(const char * string);
char * imalloc(int n);
void * irealloc(void * pointer, int size);
void icfree(char * pointer);
void ifree(char * pointer);
const char * scheck(const char * string, const char * format); const char * scheck(const char * string, const char * format);
/* /*
@ -201,14 +325,15 @@ const char * scheck(const char * string, const char * format);
#define TYPE_SIGNED(type) (((type) -1) < 0) #define TYPE_SIGNED(type) (((type) -1) < 0)
#endif /* !defined TYPE_SIGNED */ #endif /* !defined TYPE_SIGNED */
/* /* The minimum and maximum finite time values. */
** Since the definition of TYPE_INTEGRAL contains floating point numbers, static time_t const time_t_min =
** it cannot be used in preprocessor directives. (TYPE_SIGNED(time_t)
*/ ? (time_t) -1 << (CHAR_BIT * sizeof (time_t) - 1)
: 0);
#ifndef TYPE_INTEGRAL static time_t const time_t_max =
#define TYPE_INTEGRAL(type) (((type) 0.5) != 0.5) (TYPE_SIGNED(time_t)
#endif /* !defined TYPE_INTEGRAL */ ? - (~ 0 < 0) - ((time_t) -1 << (CHAR_BIT * sizeof (time_t) - 1))
: -1);
#ifndef INT_STRLEN_MAXIMUM #ifndef INT_STRLEN_MAXIMUM
/* /*

View File

@ -3,20 +3,12 @@
** 2006-07-17 by Arthur David Olson. ** 2006-07-17 by Arthur David Olson.
*/ */
#ifndef lint
#ifndef NOID
static char elsieid[] = "@(#)scheck.c 8.19";
#endif /* !defined lint */
#endif /* !defined NOID */
/*LINTLIBRARY*/ /*LINTLIBRARY*/
#include "private.h" #include "private.h"
const char * const char *
scheck(string, format) scheck(const char *const string, const char *const format)
const char * const string;
const char * const format;
{ {
register char * fbuf; register char * fbuf;
register const char * fp; register const char * fp;
@ -28,36 +20,45 @@ const char * const format;
result = ""; result = "";
if (string == NULL || format == NULL) if (string == NULL || format == NULL)
return result; return result;
fbuf = imalloc((int) (2 * strlen(format) + 4)); fbuf = malloc(2 * strlen(format) + 4);
if (fbuf == NULL) if (fbuf == NULL)
return result; return result;
fp = format; fp = format;
tp = fbuf; tp = fbuf;
/*
** Copy directives, suppressing each conversion that is not
** already suppressed. Scansets containing '%' are not
** supported; e.g., the conversion specification "%[%]" is not
** supported. Also, multibyte characters containing a
** non-leading '%' byte are not supported.
*/
while ((*tp++ = c = *fp++) != '\0') { while ((*tp++ = c = *fp++) != '\0') {
if (c != '%') if (c != '%')
continue; continue;
if (*fp == '%') { if (is_digit(*fp)) {
*tp++ = *fp++; char const *f = fp;
continue; char *t = tp;
do {
*t++ = c = *f++;
} while (is_digit(c));
if (c == '$') {
fp = f;
tp = t;
}
} }
*tp++ = '*'; *tp++ = '*';
if (*fp == '*') if (*fp == '*')
++fp; ++fp;
while (is_digit(*fp))
*tp++ = *fp++;
if (*fp == 'l' || *fp == 'h')
*tp++ = *fp++;
else if (*fp == '[')
do *tp++ = *fp++;
while (*fp != '\0' && *fp != ']');
if ((*tp++ = *fp++) == '\0') if ((*tp++ = *fp++) == '\0')
break; break;
} }
*(tp - 1) = '%'; *(tp - 1) = '%';
*tp++ = 'c'; *tp++ = 'c';
*tp = '\0'; *tp = '\0';
if (sscanf(string, fbuf, &dummy) != 1) if (sscanf(string, fbuf, &dummy) != 1)
result = (char *) format; result = format;
ifree(fbuf); free(fbuf);
return result; return result;
} }

View File

@ -304,9 +304,9 @@ void readzoneinfo(ifstream& file, ZoneInfo& info, bool is64bitData) {
} }
// skip additional Olson byte version // skip additional Olson byte version
file.read(buf, 1); file.read(buf, 1);
// if '\0', we have just one copy of data, if '2', there is additional // if '\0', we have just one copy of data, if '2' or '3', there is additional
// 64 bit version at the end. // 64 bit version at the end.
if(buf[0]!=0 && buf[0]!='2') { if(buf[0]!=0 && buf[0]!='2' && buf[0]!='3') {
throw invalid_argument("Bad Olson version info"); throw invalid_argument("Bad Olson version info");
} }

View File

@ -15,16 +15,6 @@
** Thank you! ** Thank you!
*/ */
/*
** ID
*/
#ifndef lint
#ifndef NOID
static char tzfilehid[] = "@(#)tzfile.h 8.1";
#endif /* !defined NOID */
#endif /* !defined lint */
/* /*
** Information about time zone files. ** Information about time zone files.
*/ */
@ -49,7 +39,7 @@ static char tzfilehid[] = "@(#)tzfile.h 8.1";
struct tzhead { struct tzhead {
char tzh_magic[4]; /* TZ_MAGIC */ char tzh_magic[4]; /* TZ_MAGIC */
char tzh_version[1]; /* '\0' or '2' as of 2005 */ char tzh_version[1]; /* '\0' or '2' or '3' as of 2013 */
char tzh_reserved[15]; /* reserved--must be zero */ char tzh_reserved[15]; /* reserved--must be zero */
char tzh_ttisgmtcnt[4]; /* coded number of trans. time flags */ char tzh_ttisgmtcnt[4]; /* coded number of trans. time flags */
char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */ char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */
@ -65,7 +55,7 @@ struct tzhead {
** tzh_timecnt (char [4])s coded transition times a la time(2) ** tzh_timecnt (char [4])s coded transition times a la time(2)
** tzh_timecnt (unsigned char)s types of local time starting at above ** tzh_timecnt (unsigned char)s types of local time starting at above
** tzh_typecnt repetitions of ** tzh_typecnt repetitions of
** one (char [4]) coded UTC offset in seconds ** one (char [4]) coded UT offset in seconds
** one (unsigned char) used to set tm_isdst ** one (unsigned char) used to set tm_isdst
** one (unsigned char) that's an abbreviation list index ** one (unsigned char) that's an abbreviation list index
** tzh_charcnt (char)s '\0'-terminated zone abbreviations ** tzh_charcnt (char)s '\0'-terminated zone abbreviations
@ -78,7 +68,7 @@ struct tzhead {
** if absent, transition times are ** if absent, transition times are
** assumed to be wall clock time ** assumed to be wall clock time
** tzh_ttisgmtcnt (char)s indexed by type; if TRUE, transition ** tzh_ttisgmtcnt (char)s indexed by type; if TRUE, transition
** time is UTC, if FALSE, ** time is UT, if FALSE,
** transition time is local time ** transition time is local time
** if absent, transition times are ** if absent, transition times are
** assumed to be local time ** assumed to be local time
@ -92,6 +82,13 @@ struct tzhead {
** instants after the last transition time stored in the file ** instants after the last transition time stored in the file
** (with nothing between the newlines if there is no POSIX representation for ** (with nothing between the newlines if there is no POSIX representation for
** such instants). ** such instants).
**
** If tz_version is '3' or greater, the above is extended as follows.
** First, the POSIX TZ string's hour offset may range from -167
** through 167 as compared to the POSIX-required 0 through 24.
** Second, its DST start time may be January 1 at 00:00 and its stop
** time December 31 at 24:00 plus the difference between DST and
** standard time, indicating DST all year.
*/ */
/* /*
@ -100,20 +97,12 @@ struct tzhead {
*/ */
#ifndef TZ_MAX_TIMES #ifndef TZ_MAX_TIMES
#define TZ_MAX_TIMES 1200 #define TZ_MAX_TIMES 2000
#endif /* !defined TZ_MAX_TIMES */ #endif /* !defined TZ_MAX_TIMES */
#ifndef TZ_MAX_TYPES #ifndef TZ_MAX_TYPES
#ifndef NOSOLAR /* This must be at least 17 for Europe/Samara and Europe/Vilnius. */
#define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */ #define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */
#endif /* !defined NOSOLAR */
#ifdef NOSOLAR
/*
** Must be at least 14 for Europe/Riga as of Jan 12 1995,
** as noted by Earl Chew.
*/
#define TZ_MAX_TYPES 20 /* Maximum number of local time types */
#endif /* !defined NOSOLAR */
#endif /* !defined TZ_MAX_TYPES */ #endif /* !defined TZ_MAX_TYPES */
#ifndef TZ_MAX_CHARS #ifndef TZ_MAX_CHARS
@ -132,7 +121,7 @@ struct tzhead {
#define DAYSPERNYEAR 365 #define DAYSPERNYEAR 365
#define DAYSPERLYEAR 366 #define DAYSPERLYEAR 366
#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR) #define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
#define SECSPERDAY ((long) SECSPERHOUR * HOURSPERDAY) #define SECSPERDAY ((int_fast32_t) SECSPERHOUR * HOURSPERDAY)
#define MONSPERYEAR 12 #define MONSPERYEAR 12
#define TM_SUNDAY 0 #define TM_SUNDAY 0

View File

@ -1,25 +1,29 @@
static char elsieid[] = "@(#)zdump.c 8.8"; /*
** This file is in the public domain, so clarified as of
** 2009-05-17 by Arthur David Olson.
*/
#include "version.h"
/* /*
** This code has been made independent of the rest of the time ** This code has been made independent of the rest of the time
** conversion package to increase confidence in the verification it provides. ** conversion package to increase confidence in the verification it provides.
** You can use this code to help in verifying other implementations. ** You can use this code to help in verifying other implementations.
**
** However, include private.h when debugging, so that it overrides
** time_t consistently with the rest of the package.
*/ */
/* #ifdef time_tz
* ICU note: Mr. Arthur David Olson (olsona@dc37a.nci.nih.gov) stated that # include "private.h"
* "zdump.c is indeed in the public domain" in e-mail on Feb 22, 2007. #endif
* 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 "stdio.h" /* for stdout, stderr, perror */
#include "string.h" /* for strcpy */ #include "string.h" /* for strcpy */
#include "sys/types.h" /* for time_t */ #include "sys/types.h" /* for time_t */
#include "time.h" /* for struct tm */ #include "time.h" /* for struct tm */
#include "stdlib.h" /* for exit, malloc, atoi */ #include "stdlib.h" /* for exit, malloc, atoi */
#include "float.h" /* for FLT_MAX and DBL_MAX */ #include "limits.h" /* for CHAR_BIT, LLONG_MAX */
#include "ctype.h" /* for isalpha et al. */ #include "ctype.h" /* for isalpha et al. */
/* Enable extensions and modifications for ICU. */ /* Enable extensions and modifications for ICU. */
@ -33,6 +37,52 @@ static char elsieid[] = "@(#)zdump.c 8.8";
#define isascii(x) 1 #define isascii(x) 1
#endif /* !defined isascii */ #endif /* !defined isascii */
/*
** Substitutes for pre-C99 compilers.
** Much of this section of code is stolen from private.h.
*/
#ifndef HAVE_STDINT_H
# define HAVE_STDINT_H \
(199901 <= __STDC_VERSION__ || 2 < (__GLIBC__ + (0 < __GLIBC_MINOR__)))
#endif
#if HAVE_STDINT_H
# include "stdint.h"
#endif
#ifndef HAVE_INTTYPES_H
# define HAVE_INTTYPES_H HAVE_STDINT_H
#endif
#if HAVE_INTTYPES_H
# include <inttypes.h>
#endif
#ifndef INT_FAST32_MAX
# if INT_MAX >> 31 == 0
typedef long int_fast32_t;
# else
typedef int int_fast32_t;
# endif
#endif
#ifndef INTMAX_MAX
# if defined LLONG_MAX || defined __LONG_LONG_MAX__
typedef long long intmax_t;
# define strtoimax strtoll
# define PRIdMAX "lld"
# ifdef LLONG_MAX
# define INTMAX_MAX LLONG_MAX
# else
# define INTMAX_MAX __LONG_LONG_MAX__
# endif
# else
typedef long intmax_t;
# define strtoimax strtol
# define PRIdMAX "ld"
# define INTMAX_MAX LONG_MAX
# endif
#endif
#ifndef ZDUMP_LO_YEAR #ifndef ZDUMP_LO_YEAR
#define ZDUMP_LO_YEAR (-500) #define ZDUMP_LO_YEAR (-500)
#endif /* !defined ZDUMP_LO_YEAR */ #endif /* !defined ZDUMP_LO_YEAR */
@ -100,9 +150,20 @@ static char elsieid[] = "@(#)zdump.c 8.8";
#define isleap_sum(a, b) isleap((a) % 400 + (b) % 400) #define isleap_sum(a, b) isleap((a) % 400 + (b) % 400)
#endif /* !defined isleap_sum */ #endif /* !defined isleap_sum */
#define SECSPERDAY ((long) SECSPERHOUR * HOURSPERDAY) #define SECSPERDAY ((int_fast32_t) SECSPERHOUR * HOURSPERDAY)
#define SECSPERNYEAR (SECSPERDAY * DAYSPERNYEAR) #define SECSPERNYEAR (SECSPERDAY * DAYSPERNYEAR)
#define SECSPERLYEAR (SECSPERNYEAR + SECSPERDAY) #define SECSPERLYEAR (SECSPERNYEAR + SECSPERDAY)
#define SECSPER400YEARS (SECSPERNYEAR * (intmax_t) (300 + 3) \
+ SECSPERLYEAR * (intmax_t) (100 - 3))
/*
** True if SECSPER400YEARS is known to be representable as an
** intmax_t. It's OK that SECSPER400YEARS_FITS can in theory be false
** even if SECSPER400YEARS is representable, because when that happens
** the code merely runs a bit more slowly, and this slowness doesn't
** occur on any practical platform.
*/
enum { SECSPER400YEARS_FITS = SECSPERLYEAR <= INTMAX_MAX / 400 };
#ifndef HAVE_GETTEXT #ifndef HAVE_GETTEXT
#define HAVE_GETTEXT 0 #define HAVE_GETTEXT 0
@ -122,13 +183,11 @@ static char elsieid[] = "@(#)zdump.c 8.8";
#endif /* !defined lint */ #endif /* !defined lint */
#endif /* !defined GNUC_or_lint */ #endif /* !defined GNUC_or_lint */
#ifndef INITIALIZE #if 2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__)
#ifdef GNUC_or_lint # define ATTRIBUTE_PURE __attribute__ ((__pure__))
#define INITIALIZE(x) ((x) = 0) #else
#else /* !defined GNUC_or_lint */ # define ATTRIBUTE_PURE /* empty */
#define INITIALIZE(x) #endif
#endif /* !defined GNUC_or_lint */
#endif /* !defined INITIALIZE */
/* /*
** For the benefit of GNU folk... ** For the benefit of GNU folk...
@ -155,21 +214,27 @@ extern char * optarg;
extern int optind; extern int optind;
extern char * tzname[2]; extern char * tzname[2];
static time_t absolute_min_time; /* The minimum and maximum finite time values. */
static time_t absolute_max_time; static time_t const absolute_min_time =
((time_t) -1 < 0
? (time_t) -1 << (CHAR_BIT * sizeof (time_t) - 1)
: 0);
static time_t const absolute_max_time =
((time_t) -1 < 0
? - (~ 0 < 0) - ((time_t) -1 << (CHAR_BIT * sizeof (time_t) - 1))
: -1);
static size_t longest; static size_t longest;
static char * progname; static char * progname;
static int warned; static int warned;
static char * abbr(struct tm * tmp); static char * abbr(struct tm * tmp);
static void abbrok(const char * abbrp, const char * zone); static void abbrok(const char * abbrp, const char * zone);
static long delta(struct tm * newp, struct tm * oldp); static intmax_t delta(struct tm * newp, struct tm * oldp) ATTRIBUTE_PURE;
static void dumptime(const struct tm * tmp); static void dumptime(const struct tm * tmp);
static time_t hunt(char * name, time_t lot, time_t hit); 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 void show(char * zone, time_t t, int v);
static const char * tformat(void); static const char * tformat(void);
static time_t yeartot(long y); static time_t yeartot(intmax_t y) ATTRIBUTE_PURE;
#ifdef ICU #ifdef ICU
typedef struct listentry { typedef struct listentry {
char * name; char * name;
@ -187,8 +252,7 @@ static void getzones(char * basedir, char * subdir, struct listentry ** last, in
#define my_localtime localtime #define my_localtime localtime
#else /* !defined TYPECHECK */ #else /* !defined TYPECHECK */
static struct tm * static struct tm *
my_localtime(tp) my_localtime(time_t *tp)
time_t * tp;
{ {
register struct tm * tmp; register struct tm * tmp;
@ -199,7 +263,7 @@ time_t * tp;
tm = *tmp; tm = *tmp;
t = mktime(&tm); t = mktime(&tm);
if (t - *tp >= 1 || *tp - t >= 1) { if (t != *tp) {
(void) fflush(stdout); (void) fflush(stdout);
(void) fprintf(stderr, "\n%s: ", progname); (void) fprintf(stderr, "\n%s: ", progname);
(void) fprintf(stderr, tformat(), *tp); (void) fprintf(stderr, tformat(), *tp);
@ -221,12 +285,10 @@ time_t * tp;
#endif /* !defined TYPECHECK */ #endif /* !defined TYPECHECK */
static void static void
abbrok(abbrp, zone) abbrok(const char *const abbrp, const char *const zone)
const char * const abbrp;
const char * const zone;
{ {
register const char * cp; register const char * cp;
register char * wp; register const char * wp;
if (warned) if (warned)
return; return;
@ -259,27 +321,24 @@ const char * const zone;
} }
static void static void
usage(const char *progname, FILE *stream, int status) usage(FILE * const stream, const int status)
{ {
(void) fprintf(stream, (void) fprintf(stream,
_("%s: usage is %s [ --version ] [ --help ] [ -v ] [ -c [loyear,]hiyear ] zonename ...\n\ _("%s: usage: %s [--version] [--help] [-{vV}] [-{ct} [lo,]hi] zonename ...\n"
\n\ "\n"
Report bugs to tz@elsie.nci.nih.gov.\n"), "Report bugs to %s.\n"),
progname, progname); progname, progname, REPORT_BUGS_TO);
exit(status); exit(status);
} }
int int
main(argc, argv) main(int argc, char *argv[])
int argc;
char * argv[];
{ {
register int i; register int i;
register int c;
register int vflag; register int vflag;
register int Vflag;
register char * cutarg; register char * cutarg;
register long cutloyear = ZDUMP_LO_YEAR; register char * cuttimes;
register long cuthiyear = ZDUMP_HI_YEAR;
register time_t cutlotime; register time_t cutlotime;
register time_t cuthitime; register time_t cuthitime;
register char ** fakeenv; register char ** fakeenv;
@ -299,8 +358,8 @@ char * argv[];
FILE * fp = stdout; FILE * fp = stdout;
#endif #endif
INITIALIZE(cutlotime); cutlotime = absolute_min_time;
INITIALIZE(cuthitime); cuthitime = absolute_max_time;
#if HAVE_GETTEXT #if HAVE_GETTEXT
(void) setlocale(LC_ALL, ""); (void) setlocale(LC_ALL, "");
#ifdef TZ_DOMAINDIR #ifdef TZ_DOMAINDIR
@ -311,49 +370,54 @@ char * argv[];
progname = argv[0]; progname = argv[0];
for (i = 1; i < argc; ++i) for (i = 1; i < argc; ++i)
if (strcmp(argv[i], "--version") == 0) { if (strcmp(argv[i], "--version") == 0) {
(void) printf("%s\n", elsieid); (void) printf("zdump %s%s\n", PKGVERSION, TZVERSION);
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} else if (strcmp(argv[i], "--help") == 0) { } else if (strcmp(argv[i], "--help") == 0) {
usage(progname, stdout, EXIT_SUCCESS); usage(stdout, EXIT_SUCCESS);
} }
vflag = 0; vflag = Vflag = 0;
cutarg = NULL; cutarg = cuttimes = NULL;
#ifdef ICU #ifdef ICU
aflag = 0; aflag = 0;
iflag = 0; iflag = 0;
dirarg = NULL; dirarg = NULL;
nextopt = 1; for (;;)
while(nextopt) { switch(getopt(argc, argv, "ac:d:it:vV")) {
c = getopt(argc, argv, "ac:d:iv"); case 'a': aflag = 1; break;
switch(c) { case 'c': cutarg = optarg; break;
case 'a': case 'd': dirarg = optarg; break;
aflag = 1; case 'i': iflag = 1; break;
break; case 't': cuttimes = optarg; break;
case 'c': case 'v': vflag = 1; break;
cutarg = optarg; case 'V': Vflag = 1; break;
break; case -1:
case 'd': if (! (optind == argc - 1 && strcmp(argv[optind], "=") == 0))
dirarg = optarg; goto arg_processing_done;
break; /* Fall through. */
case 'i':
iflag = 1;
break;
case 'v':
vflag = 1;
break;
default: default:
nextopt = 0;
break;
}
}
if ((c != EOF && c != -1) ||
(optind == argc - 1 && strcmp(argv[optind], "=") == 0)) {
(void) fprintf(stderr, (void) fprintf(stderr,
_("%s: usage is %s [ --version ] [ -a ] [ -v ] [ -i ] [ -c [loyear,]hiyear ] [ -d dir ] [ zonename ... ]\n"), _("%s: usage is %s [ --version ] [ -a ] [ -v ] [ -V ] [ -i ] [ -c [loyear,]hiyear ] [ -t [lotime,]hitime] ][ -d dir ] [ zonename ... ]\n"),
progname, progname); progname, progname);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
#else
for (;;)
switch (getopt(argc, argv, "c:t:vV")) {
case 'c': cutarg = optarg; break;
case 't': cuttimes = optarg; break;
case 'v': vflag = 1; break;
case 'V': Vflag = 1; break;
case -1:
if (! (optind == argc - 1 && strcmp(argv[optind], "=") == 0))
goto arg_processing_done;
/* Fall through. */
default:
usage(stderr, EXIT_FAILURE);
}
#endif
arg_processing_done:;
#ifdef ICU
if (dirarg != NULL) { if (dirarg != NULL) {
DIR * dp; DIR * dp;
/* create the output directory */ /* create the output directory */
@ -364,37 +428,63 @@ char * argv[];
} }
closedir(dp); closedir(dp);
} }
#else #endif ICU
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) { if (vflag | Vflag) {
intmax_t lo;
intmax_t hi;
char *loend, *hiend;
register intmax_t cutloyear = ZDUMP_LO_YEAR;
register intmax_t cuthiyear = ZDUMP_HI_YEAR;
if (cutarg != NULL) {
lo = strtoimax(cutarg, &loend, 10);
if (cutarg != loend && !*loend) {
hi = lo;
cuthiyear = hi;
} else if (cutarg != loend && *loend == ','
&& (hi = strtoimax(loend + 1, &hiend, 10),
loend + 1 != hiend && !*hiend)) {
cutloyear = lo;
cuthiyear = hi; cuthiyear = hi;
} else if (sscanf(cutarg, "%ld,%ld%c",
&lo, &hi, &dummy) == 2) {
cutloyear = lo;
cuthiyear = hi;
} else { } else {
(void) fprintf(stderr, _("%s: wild -c argument %s\n"), (void) fprintf(stderr, _("%s: wild -c argument %s\n"),
progname, cutarg); progname, cutarg);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
setabsolutes(); if (cutarg != NULL || cuttimes == NULL) {
cutlotime = yeartot(cutloyear); cutlotime = yeartot(cutloyear);
cuthitime = yeartot(cuthiyear); cuthitime = yeartot(cuthiyear);
}
if (cuttimes != NULL) {
lo = strtoimax(cuttimes, &loend, 10);
if (cuttimes != loend && !*loend) {
hi = lo;
if (hi < cuthitime) {
if (hi < absolute_min_time)
hi = absolute_min_time;
cuthitime = hi;
}
} else if (cuttimes != loend && *loend == ','
&& (hi = strtoimax(loend + 1, &hiend, 10),
loend + 1 != hiend && !*hiend)) {
if (cutlotime < lo) {
if (absolute_max_time < lo)
lo = absolute_max_time;
cutlotime = lo;
}
if (hi < cuthitime) {
if (hi < absolute_min_time)
hi = absolute_min_time;
cuthitime = hi;
}
} else {
(void) fprintf(stderr,
_("%s: wild -t argument %s\n"),
progname, cuttimes);
exit(EXIT_FAILURE);
}
}
} }
#ifdef ICU #ifdef ICU
@ -434,10 +524,9 @@ char * argv[];
for (i = 0; environ[i] != NULL; ++i) for (i = 0; environ[i] != NULL; ++i)
continue; continue;
fakeenv = (char **) malloc((size_t) ((i + 2) * fakeenv = malloc((i + 2) * sizeof *fakeenv);
sizeof *fakeenv)); if (fakeenv == NULL
if (fakeenv == NULL || || (fakeenv[0] = malloc(longest + 4)) == NULL) {
(fakeenv[0] = (char *) malloc(longest + 4)) == NULL) {
(void) perror(progname); (void) perror(progname);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -453,7 +542,7 @@ char * argv[];
static char buf[MAX_STRING_LENGTH]; static char buf[MAX_STRING_LENGTH];
(void) strcpy(&fakeenv[0][3], argv[i]); (void) strcpy(&fakeenv[0][3], argv[i]);
if (!vflag) { if (! (vflag | Vflag)) {
show(argv[i], now, FALSE); show(argv[i], now, FALSE);
continue; continue;
} }
@ -493,9 +582,11 @@ char * argv[];
* a transition when -i option is set */ * a transition when -i option is set */
if (!iflag) { if (!iflag) {
#endif #endif
show(argv[i], t, TRUE); if (!Vflag) {
t += SECSPERHOUR * HOURSPERDAY; show(argv[i], t, TRUE);
show(argv[i], t, TRUE); t += SECSPERDAY;
show(argv[i], t, TRUE);
}
#ifdef ICU #ifdef ICU
} }
#endif #endif
@ -507,9 +598,11 @@ char * argv[];
(void) strncpy(buf, abbr(&tm), (sizeof buf) - 1); (void) strncpy(buf, abbr(&tm), (sizeof buf) - 1);
} }
for ( ; ; ) { for ( ; ; ) {
if (t >= cuthitime || t >= cuthitime - SECSPERHOUR * 12) newt = (t < absolute_max_time - SECSPERDAY / 2
? t + SECSPERDAY / 2
: absolute_max_time);
if (cuthitime <= newt)
break; break;
newt = t + SECSPERHOUR * 12;
newtmp = localtime(&newt); newtmp = localtime(&newt);
if (newtmp != NULL) if (newtmp != NULL)
newtm = *newtmp; newtm = *newtmp;
@ -556,12 +649,13 @@ char * argv[];
/* skip displaying info for the highest time, which is actually not /* skip displaying info for the highest time, which is actually not
* a transition when -i option is used*/ * a transition when -i option is used*/
#endif #endif
t = absolute_max_time; if (!Vflag) {
t -= SECSPERHOUR * HOURSPERDAY; t = absolute_max_time;
show(argv[i], t, TRUE); t -= SECSPERDAY;
t += SECSPERHOUR * HOURSPERDAY; show(argv[i], t, TRUE);
show(argv[i], t, TRUE); t += SECSPERDAY;
show(argv[i], t, TRUE);
}
#ifdef ICU #ifdef ICU
} }
/* close file */ /* close file */
@ -592,79 +686,45 @@ char * argv[];
return EXIT_FAILURE; 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 static time_t
yeartot(y) yeartot(const intmax_t y)
const long y;
{ {
register long myy; register intmax_t myy, seconds, years;
register long seconds; register time_t t;
register time_t t;
myy = EPOCH_YEAR; myy = EPOCH_YEAR;
t = 0; t = 0;
while (myy != y) { while (myy < y) {
if (myy < y) { if (SECSPER400YEARS_FITS && 400 <= y - myy) {
intmax_t diff400 = (y - myy) / 400;
if (INTMAX_MAX / SECSPER400YEARS < diff400)
return absolute_max_time;
seconds = diff400 * SECSPER400YEARS;
years = diff400 * 400;
} else {
seconds = isleap(myy) ? SECSPERLYEAR : SECSPERNYEAR; seconds = isleap(myy) ? SECSPERLYEAR : SECSPERNYEAR;
++myy; years = 1;
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;
} }
myy += years;
if (t > absolute_max_time - seconds)
return absolute_max_time;
t += seconds;
}
while (y < myy) {
if (SECSPER400YEARS_FITS && y + 400 <= myy && myy < 0) {
intmax_t diff400 = (myy - y) / 400;
if (INTMAX_MAX / SECSPER400YEARS < diff400)
return absolute_min_time;
seconds = diff400 * SECSPER400YEARS;
years = diff400 * 400;
} else {
seconds = isleap(myy - 1) ? SECSPERLYEAR : SECSPERNYEAR;
years = 1;
}
myy -= years;
if (t < absolute_min_time + seconds)
return absolute_min_time;
t -= seconds;
} }
return t; return t;
} }
@ -673,7 +733,6 @@ static time_t
hunt(char *name, time_t lot, time_t hit) hunt(char *name, time_t lot, time_t hit)
{ {
time_t t; time_t t;
long diff;
struct tm lotm; struct tm lotm;
register struct tm * lotmp; register struct tm * lotmp;
struct tm tm; struct tm tm;
@ -686,7 +745,7 @@ hunt(char *name, time_t lot, time_t hit)
(void) strncpy(loab, abbr(&lotm), (sizeof loab) - 1); (void) strncpy(loab, abbr(&lotm), (sizeof loab) - 1);
} }
for ( ; ; ) { for ( ; ; ) {
diff = (long) (hit - lot); time_t diff = hit - lot;
if (diff < 2) if (diff < 2)
break; break;
t = lot; t = lot;
@ -716,13 +775,11 @@ hunt(char *name, time_t lot, time_t hit)
** Thanks to Paul Eggert for logic used in delta. ** Thanks to Paul Eggert for logic used in delta.
*/ */
static long static intmax_t
delta(newp, oldp) delta(struct tm * newp, struct tm *oldp)
struct tm * newp;
struct tm * oldp;
{ {
register long result; register intmax_t result;
register int tmy; register int tmy;
if (newp->tm_year < oldp->tm_year) if (newp->tm_year < oldp->tm_year)
return -delta(oldp, newp); return -delta(oldp, newp);
@ -751,7 +808,7 @@ show(char *zone, time_t t, int v)
(void) printf(tformat(), t); (void) printf(tformat(), t);
} else { } else {
dumptime(tmp); dumptime(tmp);
(void) printf(" UTC"); (void) printf(" UT");
} }
(void) printf(" = "); (void) printf(" = ");
} }
@ -773,8 +830,7 @@ show(char *zone, time_t t, int v)
} }
static char * static char *
abbr(tmp) abbr(struct tm *tmp)
struct tm * tmp;
{ {
register char * result; register char * result;
static char nada; static char nada;
@ -793,18 +849,19 @@ struct tm * tmp;
static const char * static const char *
tformat(void) 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 (0 > (time_t) -1) { /* signed */
if (sizeof (time_t) == sizeof (intmax_t))
return "%"PRIdMAX;
if (sizeof (time_t) > sizeof (long)) if (sizeof (time_t) > sizeof (long))
return "%lld"; return "%lld";
if (sizeof (time_t) > sizeof (int)) if (sizeof (time_t) > sizeof (int))
return "%ld"; return "%ld";
return "%d"; return "%d";
} }
#ifdef PRIuMAX
if (sizeof (time_t) == sizeof (uintmax_t))
return "%"PRIuMAX;
#endif
if (sizeof (time_t) > sizeof (unsigned long)) if (sizeof (time_t) > sizeof (unsigned long))
return "%llu"; return "%llu";
if (sizeof (time_t) > sizeof (unsigned int)) if (sizeof (time_t) > sizeof (unsigned int))
@ -813,8 +870,7 @@ tformat(void)
} }
static void static void
dumptime(timeptr) dumptime(register const struct tm *timeptr)
register const struct tm * timeptr;
{ {
static const char wday_name[][3] = { static const char wday_name[][3] = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"

File diff suppressed because it is too large Load Diff