updated to tzcode2007a

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19755 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Jérôme Duval 2007-01-09 23:16:26 +00:00
parent f21b85581f
commit 9481ed48de
8 changed files with 946 additions and 340 deletions

View File

@ -4,7 +4,7 @@
/* /*
** This file is in the public domain, so clarified as of ** This file is in the public domain, so clarified as of
** 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov). ** 1996-06-05 by Arthur David Olson.
*/ */
/* /*
@ -21,7 +21,7 @@
#ifndef lint #ifndef lint
#ifndef NOID #ifndef NOID
static char privatehid[] = "@(#)private.h 7.55"; static char privatehid[] = "@(#)private.h 8.2";
#endif /* !defined NOID */ #endif /* !defined NOID */
#endif /* !defined lint */ #endif /* !defined lint */
@ -89,7 +89,7 @@ static char privatehid[] = "@(#)private.h 7.55";
#include "stdio.h" #include "stdio.h"
#include "errno.h" #include "errno.h"
#include "string.h" #include "string.h"
#include "limits.h" /* for CHAR_BIT */ #include "limits.h" /* for CHAR_BIT et al. */
#include "time.h" #include "time.h"
#include "stdlib.h" #include "stdlib.h"
@ -124,21 +124,52 @@ static char privatehid[] = "@(#)private.h 7.55";
/* Unlike <ctype.h>'s isdigit, this also works if c < 0 | c > UCHAR_MAX. */ /* Unlike <ctype.h>'s isdigit, this also works if c < 0 | c > UCHAR_MAX. */
#define is_digit(c) ((unsigned)(c) - '0' <= 9) #define is_digit(c) ((unsigned)(c) - '0' <= 9)
/*
** Define HAVE_STDINT_H's default value here, rather than at the
** start, since __GLIBC__'s value depends on previously-included
** files.
** (glibc 2.1 and later have stdint.h, even with pre-C99 compilers.)
*/
#ifndef HAVE_STDINT_H
#define HAVE_STDINT_H \
(199901 <= __STDC_VERSION__ || \
2 < (__GLIBC__ + (0 < __GLIBC_MINOR__)))
#endif /* !defined HAVE_STDINT_H */
#if HAVE_STDINT_H
#include "stdint.h"
#endif /* !HAVE_STDINT_H */
#ifndef INT_FAST64_MAX
/* Pre-C99 GCC compilers define __LONG_LONG_MAX__ instead of LLONG_MAX. */
#if defined LLONG_MAX || defined __LONG_LONG_MAX__
typedef long long int_fast64_t;
#else /* ! (defined LLONG_MAX || defined __LONG_LONG_MAX__) */
#if (LONG_MAX >> 31) < 0xffffffff
Please use a compiler that supports a 64-bit integer type (or wider);
you may need to compile with "-DHAVE_STDINT_H".
#endif /* (LONG_MAX >> 31) < 0xffffffff */
typedef long int_fast64_t;
#endif /* ! (defined LLONG_MAX || defined __LONG_LONG_MAX__) */
#endif /* !defined INT_FAST64_MAX */
#ifndef INT32_MAX
#define INT32_MAX 0x7fffffff
#endif /* !defined INT32_MAX */
#ifndef INT32_MIN
#define INT32_MIN (-1 - INT32_MAX)
#endif /* !defined INT32_MIN */
/* /*
** Workarounds for compilers/systems. ** Workarounds for compilers/systems.
*/ */
/* /*
** SunOS 4.1.1 cc lacks prototypes. ** If your compiler lacks prototypes, "#define P(x) ()".
*/ */
#ifndef P #ifndef P
#ifdef __STDC__
#define P(x) x #define P(x) x
#endif /* defined __STDC__ */
#ifndef __STDC__
#define P(x) ()
#endif /* !defined __STDC__ */
#endif /* !defined P */ #endif /* !defined P */
/* /*
@ -211,14 +242,14 @@ extern char * asctime_r();
** Private function declarations. ** Private function declarations.
*/ */
char * icalloc P((int nelem, int elsize)); char * icalloc P((int nelem, int elsize));
char * icatalloc P((char * old, const char * new)); char * icatalloc P((char * old, const char * new));
char * icpyalloc P((const char * string)); char * icpyalloc P((const char * string));
char * imalloc P((int n)); char * imalloc P((int n));
void * irealloc P((void * pointer, int size)); void * irealloc P((void * pointer, int size));
void icfree P((char * pointer)); void icfree P((char * pointer));
void ifree P((char * pointer)); void ifree P((char * pointer));
char * scheck P((const char *string, char *format)); const char * scheck P((const char * string, const char * format));
/* /*
** Finally, some convenience items. ** Finally, some convenience items.
@ -310,6 +341,26 @@ char *asctime_r P((struct tm const *, char *));
char *ctime_r P((time_t const *, char *)); char *ctime_r P((time_t const *, char *));
#endif /* HAVE_INCOMPATIBLE_CTIME_R */ #endif /* HAVE_INCOMPATIBLE_CTIME_R */
#ifndef YEARSPERREPEAT
#define YEARSPERREPEAT 400 /* years before a Gregorian repeat */
#endif /* !defined YEARSPERREPEAT */
/*
** The Gregorian year averages 365.2425 days, which is 31556952 seconds.
*/
#ifndef AVGSECSPERYEAR
#define AVGSECSPERYEAR 31556952L
#endif /* !defined AVGSECSPERYEAR */
#ifndef SECSPERREPEAT
#define SECSPERREPEAT ((int_fast64_t) YEARSPERREPEAT * (int_fast64_t) AVGSECSPERYEAR)
#endif /* !defined SECSPERREPEAT */
#ifndef SECSPERREPEAT_BITS
#define SECSPERREPEAT_BITS 34 /* ceil(log2(SECSPERREPEAT)) */
#endif /* !defined SECSPERREPEAT_BITS */
/* /*
** UNIX was a registered trademark of The Open Group in 2003. ** UNIX was a registered trademark of The Open Group in 2003.
*/ */

View File

@ -4,7 +4,7 @@
/* /*
** This file is in the public domain, so clarified as of ** This file is in the public domain, so clarified as of
** 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov). ** 1996-06-05 by Arthur David Olson.
*/ */
/* /*
@ -21,7 +21,7 @@
#ifndef lint #ifndef lint
#ifndef NOID #ifndef NOID
static char tzfilehid[] = "@(#)tzfile.h 7.17"; static char tzfilehid[] = "@(#)tzfile.h 8.1";
#endif /* !defined NOID */ #endif /* !defined NOID */
#endif /* !defined lint */ #endif /* !defined lint */
@ -49,7 +49,8 @@ static char tzfilehid[] = "@(#)tzfile.h 7.17";
struct tzhead { struct tzhead {
char tzh_magic[4]; /* TZ_MAGIC */ char tzh_magic[4]; /* TZ_MAGIC */
char tzh_reserved[16]; /* reserved for future use */ char tzh_version[1]; /* '\0' or '2' as of 2005 */
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 */
char tzh_leapcnt[4]; /* coded number of leap seconds */ char tzh_leapcnt[4]; /* coded number of leap seconds */
@ -83,19 +84,23 @@ struct tzhead {
** assumed to be local time ** assumed to be local time
*/ */
/*
** If tzh_version is '2' or greater, the above is followed by a second instance
** of tzhead and a second instance of the data in which each coded transition
** time uses 8 rather than 4 chars,
** then a POSIX-TZ-environment-variable-style string for use in handling
** instants after the last transition time stored in the file
** (with nothing between the newlines if there is no POSIX representation for
** such instants).
*/
/* /*
** In the current implementation, "tzset()" refuses to deal with files that ** In the current implementation, "tzset()" refuses to deal with files that
** exceed any of the limits below. ** exceed any of the limits below.
*/ */
#ifndef TZ_MAX_TIMES #ifndef TZ_MAX_TIMES
/* #define TZ_MAX_TIMES 1200
** The TZ_MAX_TIMES value below is enough to handle a bit more than a
** year's worth of solar time (corrected daily to the nearest second) or
** 138 years of Pacific Presidential Election time
** (where there are three time zone transitions every fourth year).
*/
#define TZ_MAX_TIMES 370
#endif /* !defined TZ_MAX_TIMES */ #endif /* !defined TZ_MAX_TIMES */
#ifndef TZ_MAX_TYPES #ifndef TZ_MAX_TYPES
@ -105,7 +110,7 @@ struct tzhead {
#ifdef NOSOLAR #ifdef NOSOLAR
/* /*
** Must be at least 14 for Europe/Riga as of Jan 12 1995, ** Must be at least 14 for Europe/Riga as of Jan 12 1995,
** as noted by Earl Chew <earl@hpato.aus.hp.com>. ** as noted by Earl Chew.
*/ */
#define TZ_MAX_TYPES 20 /* Maximum number of local time types */ #define TZ_MAX_TYPES 20 /* Maximum number of local time types */
#endif /* !defined NOSOLAR */ #endif /* !defined NOSOLAR */

View File

@ -1,6 +1,11 @@
/*
** This file is in the public domain, so clarified as of
** 2006-07-17 by Arthur David Olson.
*/
#ifndef lint #ifndef lint
#ifndef NOID #ifndef NOID
static char elsieid[] = "@(#)ialloc.c 8.29"; static char elsieid[] = "@(#)ialloc.c 8.30";
#endif /* !defined NOID */ #endif /* !defined NOID */
#endif /* !defined lint */ #endif /* !defined lint */

View File

@ -1,6 +1,11 @@
/*
** This file is in the public domain, so clarified as of
** 2006-07-17 by Arthur David Olson.
*/
#ifndef lint #ifndef lint
#ifndef NOID #ifndef NOID
static char elsieid[] = "@(#)scheck.c 8.16"; static char elsieid[] = "@(#)scheck.c 8.19";
#endif /* !defined lint */ #endif /* !defined lint */
#endif /* !defined NOID */ #endif /* !defined NOID */
@ -8,20 +13,19 @@ static char elsieid[] = "@(#)scheck.c 8.16";
#include "private.h" #include "private.h"
char * const char *
scheck(string, format) scheck(string, format)
const char * const string; const char * const string;
char * const format; const char * const format;
{ {
register char * fbuf; register char * fbuf;
register const char * fp; register const char * fp;
register char * tp; register char * tp;
register int c; register int c;
register char * result; register const char * result;
char dummy; char dummy;
static char nada;
result = &nada; result = "";
if (string == NULL || format == NULL) if (string == NULL || format == NULL)
return result; return result;
fbuf = imalloc((int) (2 * strlen(format) + 4)); fbuf = imalloc((int) (2 * strlen(format) + 4));

View File

@ -1,4 +1,4 @@
static char elsieid[] = "@(#)zdump.c 7.65"; static char elsieid[] = "@(#)zdump.c 8.3";
/* /*
** This code has been made independent of the rest of the time ** This code has been made independent of the rest of the time
@ -12,6 +12,10 @@ static char elsieid[] = "@(#)zdump.c 7.65";
#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 "float.h" /* for FLT_MAX and DBL_MAX */
#include "ctype.h" /* for isalpha et al. */
#ifndef isascii
#define isascii(x) 1
#endif /* !defined isascii */
#ifndef ZDUMP_LO_YEAR #ifndef ZDUMP_LO_YEAR
#define ZDUMP_LO_YEAR (-500) #define ZDUMP_LO_YEAR (-500)
@ -126,11 +130,7 @@ static char elsieid[] = "@(#)zdump.c 7.65";
#endif /* !defined TZ_DOMAIN */ #endif /* !defined TZ_DOMAIN */
#ifndef P #ifndef P
#ifdef __STDC__
#define P(x) x #define P(x) x
#else /* !defined __STDC__ */
#define P(x) ()
#endif /* !defined __STDC__ */
#endif /* !defined P */ #endif /* !defined P */
extern char ** environ; extern char ** environ;
@ -147,7 +147,7 @@ static char * progname;
static int warned; static int warned;
static char * abbr P((struct tm * tmp)); static char * abbr P((struct tm * tmp));
static void abbrok P((const char * abbr, const char * zone)); static void abbrok P((const char * abbrp, const char * zone));
static long delta P((struct tm * newp, struct tm * oldp)); static long delta P((struct tm * newp, struct tm * oldp));
static void dumptime P((const struct tm * tmp)); static void dumptime P((const struct tm * tmp));
static time_t hunt P((char * name, time_t lot, time_t hit)); static time_t hunt P((char * name, time_t lot, time_t hit));
@ -194,40 +194,40 @@ time_t * tp;
#endif /* !defined TYPECHECK */ #endif /* !defined TYPECHECK */
static void static void
abbrok(abbr, zone) abbrok(abbrp, zone)
const char * const abbr; const char * const abbrp;
const char * const zone; const char * const zone;
{ {
register int i;
register const char * cp; register const char * cp;
register char * wp; register char * wp;
if (warned) if (warned)
return; return;
cp = abbr; cp = abbrp;
wp = NULL; wp = NULL;
while (isascii(*cp) && isalpha(*cp)) while (isascii((unsigned char) *cp) && isalpha((unsigned char) *cp))
++cp; ++cp;
if (cp - abbr == 0) if (cp - abbrp == 0)
wp = _("lacks alphabetic at start"); wp = _("lacks alphabetic at start");
if (cp - abbr < 3) else if (cp - abbrp < 3)
wp = _("has fewer than 3 alphabetics"); wp = _("has fewer than 3 alphabetics");
if (cp - abbr > 6) else if (cp - abbrp > 6)
wp = _("has more than 6 alphabetics"); wp = _("has more than 6 alphabetics");
if (wp == NULL && (*cp == '+' || *cp == '-')) { if (wp == NULL && (*cp == '+' || *cp == '-')) {
++cp; ++cp;
if (isascii(*cp) && isdigit(*cp)) if (isascii((unsigned char) *cp) &&
if (*cp++ == '1' && *cp >= '0' && *cp <= '4') isdigit((unsigned char) *cp))
++cp; if (*cp++ == '1' && *cp >= '0' && *cp <= '4')
++cp;
if (*cp != '\0')
wp = _("differs from POSIX standard");
} }
if (*cp != '\0')
wp = _("differs from POSIX standard");
if (wp == NULL) if (wp == NULL)
return; return;
(void) fflush(stdout); (void) fflush(stdout);
(void) fprintf(stderr, (void) fprintf(stderr,
"%s: warning: zone \"%s\" abbreviation \"%s\" %s\n", _("%s: warning: zone \"%s\" abbreviation \"%s\" %s\n"),
progname, zone, abbr, wp); progname, zone, abbrp, wp);
warned = TRUE; warned = TRUE;
} }
@ -266,7 +266,7 @@ char * argv[];
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("%s\n", elsieid);
(void) exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }
vflag = 0; vflag = 0;
cutarg = NULL; cutarg = NULL;
@ -279,7 +279,7 @@ char * argv[];
(void) fprintf(stderr, (void) fprintf(stderr,
_("%s: usage is %s [ --version ] [ -v ] [ -c [loyear,]hiyear ] zonename ...\n"), _("%s: usage is %s [ --version ] [ -v ] [ -c [loyear,]hiyear ] zonename ...\n"),
progname, progname); progname, progname);
(void) exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (vflag) { if (vflag) {
if (cutarg != NULL) { if (cutarg != NULL) {
@ -296,7 +296,7 @@ _("%s: usage is %s [ --version ] [ -v ] [ -c [loyear,]hiyear ] zonename ...\n"),
} else { } else {
(void) fprintf(stderr, _("%s: wild -c argument %s\n"), (void) fprintf(stderr, _("%s: wild -c argument %s\n"),
progname, cutarg); progname, cutarg);
(void) exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
setabsolutes(); setabsolutes();
@ -319,7 +319,7 @@ _("%s: usage is %s [ --version ] [ -v ] [ -c [loyear,]hiyear ] zonename ...\n"),
if (fakeenv == NULL || if (fakeenv == NULL ||
(fakeenv[0] = (char *) malloc(longest + 4)) == NULL) { (fakeenv[0] = (char *) malloc(longest + 4)) == NULL) {
(void) perror(progname); (void) perror(progname);
(void) exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
to = 0; to = 0;
(void) strcpy(fakeenv[to++], "TZ="); (void) strcpy(fakeenv[to++], "TZ=");
@ -385,8 +385,8 @@ _("%s: usage is %s [ --version ] [ -v ] [ -c [loyear,]hiyear ] zonename ...\n"),
} }
if (fflush(stdout) || ferror(stdout)) { if (fflush(stdout) || ferror(stdout)) {
(void) fprintf(stderr, "%s: ", progname); (void) fprintf(stderr, "%s: ", progname);
(void) perror(_("Error writing standard output")); (void) perror(_("Error writing to standard output"));
(void) exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
/* If exit fails to exit... */ /* If exit fails to exit... */
@ -410,18 +410,25 @@ setabsolutes()
(void) fprintf(stderr, (void) fprintf(stderr,
_("%s: use of -v on system with floating time_t other than float or double\n"), _("%s: use of -v on system with floating time_t other than float or double\n"),
progname); progname);
(void) exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} else if (0 > (time_t) -1) { } else if (0 > (time_t) -1) {
/* /*
** time_t is signed. ** time_t is signed. Assume overflow wraps around.
*/ */
register time_t hibit; time_t t = 0;
time_t t1 = 1;
for (hibit = 1; (hibit * 2) != 0; hibit *= 2) while (t < t1) {
continue; t = t1;
absolute_min_time = hibit; t1 = 2 * t1 + 1;
absolute_max_time = -(hibit + 1); }
absolute_max_time = t;
t = -t;
absolute_min_time = t - 1;
if (t < absolute_min_time)
absolute_min_time = t;
} else { } else {
/* /*
** time_t is unsigned. ** time_t is unsigned.
@ -464,10 +471,7 @@ const long y;
} }
static time_t static time_t
hunt(name, lot, hit) hunt(char *name, time_t lot, time_t hit)
char * name;
time_t lot;
time_t hit;
{ {
time_t t; time_t t;
long diff; long diff;
@ -510,7 +514,7 @@ time_t hit;
} }
/* /*
** Thanks to Paul Eggert (eggert@twinsun.com) for logic used in delta. ** Thanks to Paul Eggert for logic used in delta.
*/ */
static long static long
@ -537,10 +541,7 @@ struct tm * oldp;
} }
static void static void
show(zone, t, v) show(char *zone, time_t t, int v)
char * zone;
time_t t;
int v;
{ {
register struct tm * tmp; register struct tm * tmp;

File diff suppressed because it is too large Load Diff

View File

@ -1,18 +1,17 @@
/* /*
** This file is in the public domain, so clarified as of ** This file is in the public domain, so clarified as of
** 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov). ** 1996-06-05 by Arthur David Olson.
*/ */
#ifndef lint #ifndef lint
#ifndef NOID #ifndef NOID
static char elsieid[] = "@(#)localtime.c 7.95"; static char elsieid[] = "@(#)localtime.c 8.5";
#endif /* !defined NOID */ #endif /* !defined NOID */
#endif /* !defined lint */ #endif /* !defined lint */
/* /*
** Leap second handling from Bradley White (bww@k.gp.cs.cmu.edu). ** Leap second handling from Bradley White.
** POSIX-style TZ environment variable handling from Guy Harris ** POSIX-style TZ environment variable handling from Guy Harris.
** (guy@auspex.com).
*/ */
/*LINTLIBRARY*/ /*LINTLIBRARY*/
@ -111,6 +110,8 @@ struct state {
int timecnt; int timecnt;
int typecnt; int typecnt;
int charcnt; int charcnt;
int goback;
int goahead;
time_t ats[TZ_MAX_TIMES]; time_t ats[TZ_MAX_TIMES];
unsigned char types[TZ_MAX_TIMES]; unsigned char types[TZ_MAX_TIMES];
struct ttinfo ttis[TZ_MAX_TYPES]; struct ttinfo ttis[TZ_MAX_TYPES];
@ -136,8 +137,10 @@ struct rule {
*/ */
static long detzcode P((const char * codep)); static long detzcode P((const char * codep));
static time_t detzcode64 P((const char * codep));
static int differ_by_repeat P((time_t t1, time_t t0));
static const char * getzname P((const char * strp)); static const char * getzname P((const char * strp));
static const char * getqzname P((const char * strp, const char delim)); static const char * getqzname P((const char * strp, const int delim));
static const char * getnum P((const char * strp, int * nump, int min, static const char * getnum P((const char * strp, int * nump, int min,
int max)); int max));
static const char * getsecs P((const char * strp, long * secsp)); static const char * getsecs P((const char * strp, long * secsp));
@ -174,7 +177,8 @@ static int tmcomp P((const struct tm * atmp,
const struct tm * btmp)); const struct tm * btmp));
static time_t transtime P((time_t janfirst, int year, static time_t transtime P((time_t janfirst, int year,
const struct rule * rulep, long offset)); const struct rule * rulep, long offset));
static int tzload P((const char * name, struct state * sp)); static int tzload P((const char * name, struct state * sp,
int doextend));
static int tzparse P((const char * name, struct state * sp, static int tzparse P((const char * name, struct state * sp,
int lastditch)); int lastditch));
@ -208,7 +212,7 @@ char * tzname[2] = {
** Except for the strftime function, these functions [asctime, ** Except for the strftime function, these functions [asctime,
** ctime, gmtime, localtime] return values in one of two static ** ctime, gmtime, localtime] return values in one of two static
** objects: a broken-down time structure and an array of char. ** objects: a broken-down time structure and an array of char.
** Thanks to Paul Eggert (eggert@twinsun.com) for noting this. ** Thanks to Paul Eggert for noting this.
*/ */
static struct tm tm; static struct tm tm;
@ -229,12 +233,25 @@ const char * const codep;
register long result; register long result;
register int i; register int i;
result = (codep[0] & 0x80) ? ~0L : 0L; result = (codep[0] & 0x80) ? ~0L : 0;
for (i = 0; i < 4; ++i) for (i = 0; i < 4; ++i)
result = (result << 8) | (codep[i] & 0xff); result = (result << 8) | (codep[i] & 0xff);
return result; return result;
} }
static time_t
detzcode64(codep)
const char * const codep;
{
register time_t result;
register int i;
result = (codep[0] & 0x80) ? (~(int_fast64_t) 0) : 0;
for (i = 0; i < 8; ++i)
result = result * 256 + (codep[i] & 0xff);
return result;
}
static void static void
settzname P((void)) settzname P((void))
{ {
@ -304,13 +321,33 @@ settzname P((void))
} }
static int static int
tzload(name, sp) differ_by_repeat(t1, t0)
const time_t t1;
const time_t t0;
{
if (TYPE_INTEGRAL(time_t) &&
TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS)
return 0;
return t1 - t0 == SECSPERREPEAT;
}
static int
tzload(name, sp, doextend)
register const char * name; register const char * name;
register struct state * const sp; register struct state * const sp;
register const int doextend;
{ {
register const char * p; register const char * p;
register int i; register int i;
register int fid; register int fid;
register int stored;
register int nread;
union {
struct tzhead tzhead;
char buf[2 * sizeof(struct tzhead) +
2 * sizeof *sp +
4 * TZ_MAX_TIMES];
} u;
if (name == NULL && (name = TZDEFAULT) == NULL) if (name == NULL && (name = TZDEFAULT) == NULL)
return -1; return -1;
@ -348,18 +385,13 @@ register struct state * const sp;
if ((fid = open(name, OPEN_MODE)) == -1) if ((fid = open(name, OPEN_MODE)) == -1)
return -1; return -1;
} }
{ nread = read(fid, u.buf, sizeof u.buf);
struct tzhead * tzhp; if (close(fid) < 0 || nread <= 0)
union { return -1;
struct tzhead tzhead; for (stored = 4; stored <= 8; stored *= 2) {
char buf[sizeof *sp + sizeof *tzhp];
} u;
int ttisstdcnt; int ttisstdcnt;
int ttisgmtcnt; int ttisgmtcnt;
i = read(fid, u.buf, sizeof u.buf);
if (close(fid) != 0)
return -1;
ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt); ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt);
ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt); ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt);
sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt); sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt);
@ -374,17 +406,19 @@ register struct state * const sp;
(ttisstdcnt != sp->typecnt && ttisstdcnt != 0) || (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) ||
(ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0)) (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0))
return -1; return -1;
if (i - (p - u.buf) < sp->timecnt * 4 + /* ats */ if (nread - (p - u.buf) <
sp->timecnt * stored + /* ats */
sp->timecnt + /* types */ sp->timecnt + /* types */
sp->typecnt * (4 + 2) + /* ttinfos */ sp->typecnt * 6 + /* ttinfos */
sp->charcnt + /* chars */ sp->charcnt + /* chars */
sp->leapcnt * (4 + 4) + /* lsinfos */ sp->leapcnt * (stored + 4) + /* lsinfos */
ttisstdcnt + /* ttisstds */ ttisstdcnt + /* ttisstds */
ttisgmtcnt) /* ttisgmts */ ttisgmtcnt) /* ttisgmts */
return -1; return -1;
for (i = 0; i < sp->timecnt; ++i) { for (i = 0; i < sp->timecnt; ++i) {
sp->ats[i] = detzcode(p); sp->ats[i] = (stored == 4) ?
p += 4; detzcode(p) : detzcode64(p);
p += stored;
} }
for (i = 0; i < sp->timecnt; ++i) { for (i = 0; i < sp->timecnt; ++i) {
sp->types[i] = (unsigned char) *p++; sp->types[i] = (unsigned char) *p++;
@ -412,8 +446,9 @@ register struct state * const sp;
register struct lsinfo * lsisp; register struct lsinfo * lsisp;
lsisp = &sp->lsis[i]; lsisp = &sp->lsis[i];
lsisp->ls_trans = detzcode(p); lsisp->ls_trans = (stored == 4) ?
p += 4; detzcode(p) : detzcode64(p);
p += stored;
lsisp->ls_corr = detzcode(p); lsisp->ls_corr = detzcode(p);
p += 4; p += 4;
} }
@ -470,7 +505,63 @@ register struct state * const sp;
} }
break; break;
} }
/*
** If this is an old file, we're done.
*/
if (u.tzhead.tzh_version[0] == '\0')
break;
nread -= p - u.buf;
for (i = 0; i < nread; ++i)
u.buf[i] = p[i];
/*
** If this is a narrow integer time_t system, we're done.
*/
if (stored >= (int) sizeof(time_t) && TYPE_INTEGRAL(time_t))
break;
} }
if (doextend && nread > 2 &&
u.buf[0] == '\n' && u.buf[nread - 1] == '\n' &&
sp->typecnt + 2 <= TZ_MAX_TYPES) {
struct state ts;
register int result;
u.buf[nread - 1] = '\0';
result = tzparse(&u.buf[1], &ts, FALSE);
if (result == 0 && ts.typecnt == 2 &&
sp->charcnt + ts.charcnt <= TZ_MAX_CHARS) {
for (i = 0; i < 2; ++i)
ts.ttis[i].tt_abbrind +=
sp->charcnt;
for (i = 0; i < ts.charcnt; ++i)
sp->chars[sp->charcnt++] =
ts.chars[i];
i = 0;
while (i < ts.timecnt &&
ts.ats[i] <=
sp->ats[sp->timecnt - 1])
++i;
while (i < ts.timecnt &&
sp->timecnt < TZ_MAX_TIMES) {
sp->ats[sp->timecnt] =
ts.ats[i];
sp->types[sp->timecnt] =
sp->typecnt +
ts.types[i];
++sp->timecnt;
++i;
}
sp->ttis[sp->typecnt++] = ts.ttis[0];
sp->ttis[sp->typecnt++] = ts.ttis[1];
}
}
i = 2 * YEARSPERREPEAT;
sp->goback = sp->goahead = sp->timecnt > i;
sp->goback = sp->goback && sp->types[i] == sp->types[0] &&
differ_by_repeat(sp->ats[i], sp->ats[0]);
sp->goahead = sp->goahead &&
sp->types[sp->timecnt - 1] == sp->types[sp->timecnt - 1 - i] &&
differ_by_repeat(sp->ats[sp->timecnt - 1],
sp->ats[sp->timecnt - 1 - i]);
return 0; return 0;
} }
@ -503,19 +594,17 @@ register const char * strp;
/* /*
** Given a pointer into an extended time zone string, scan until the ending ** Given a pointer into an extended time zone string, scan until the ending
** delimiter of the zone name is located. Return a pointer to the delimiter. ** delimiter of the zone name is located. Return a pointer to the delimiter.
** **
** As with getzname above, the legal character set is actually quite ** As with getzname above, the legal character set is actually quite
** restricted, with other characters producing undefined results. ** restricted, with other characters producing undefined results.
** We choose not to care - allowing almost anything to be in the zone abbrev. ** We don't do any checking here; checking is done later in common-case code.
*/ */
static const char * static const char *
getqzname(strp, delim) getqzname(register const char *strp, const int delim)
register const char * strp;
const char delim;
{ {
register char c; register int c;
while ((c = *strp) != '\0' && c != delim) while ((c = *strp) != '\0' && c != delim)
++strp; ++strp;
@ -824,7 +913,7 @@ const int lastditch;
if (name == NULL) if (name == NULL)
return -1; return -1;
} }
load_result = tzload(TZDEFRULES, sp); load_result = tzload(TZDEFRULES, sp, FALSE);
if (load_result != 0) if (load_result != 0)
sp->leapcnt = 0; /* so, we're off a little */ sp->leapcnt = 0; /* so, we're off a little */
if (*name != '\0') { if (*name != '\0') {
@ -866,11 +955,8 @@ const int lastditch;
return -1; return -1;
sp->typecnt = 2; /* standard time and DST */ sp->typecnt = 2; /* standard time and DST */
/* /*
** Two transitions per year, from EPOCH_YEAR to 2037. ** Two transitions per year, from EPOCH_YEAR forward.
*/ */
sp->timecnt = 2 * (2037 - EPOCH_YEAR + 1);
if (sp->timecnt > TZ_MAX_TIMES)
return -1;
sp->ttis[0].tt_gmtoff = -dstoffset; sp->ttis[0].tt_gmtoff = -dstoffset;
sp->ttis[0].tt_isdst = 1; sp->ttis[0].tt_isdst = 1;
sp->ttis[0].tt_abbrind = stdlen + 1; sp->ttis[0].tt_abbrind = stdlen + 1;
@ -880,7 +966,12 @@ const int lastditch;
atp = sp->ats; atp = sp->ats;
typep = sp->types; typep = sp->types;
janfirst = 0; janfirst = 0;
for (year = EPOCH_YEAR; year <= 2037; ++year) { sp->timecnt = 0;
for (year = EPOCH_YEAR;
sp->timecnt + 2 <= TZ_MAX_TIMES;
++year) {
time_t newfirst;
starttime = transtime(janfirst, year, &start, starttime = transtime(janfirst, year, &start,
stdoffset); stdoffset);
endtime = transtime(janfirst, year, &end, endtime = transtime(janfirst, year, &end,
@ -896,8 +987,13 @@ const int lastditch;
*atp++ = endtime; *atp++ = endtime;
*typep++ = 1; /* DST ends */ *typep++ = 1; /* DST ends */
} }
janfirst += year_lengths[isleap(year)] * sp->timecnt += 2;
newfirst = janfirst;
newfirst += year_lengths[isleap(year)] *
SECSPERDAY; SECSPERDAY;
if (newfirst <= janfirst)
break;
janfirst = newfirst;
} }
} else { } else {
register long theirstdoffset; register long theirstdoffset;
@ -1012,7 +1108,7 @@ static void
gmtload(sp) gmtload(sp)
struct state * const sp; struct state * const sp;
{ {
if (tzload(gmt, sp) != 0) if (tzload(gmt, sp, TRUE) != 0)
(void) tzparse(gmt, sp, TRUE); (void) tzparse(gmt, sp, TRUE);
} }
@ -1039,7 +1135,7 @@ tzsetwall P((void))
} }
} }
#endif /* defined ALL_STATE */ #endif /* defined ALL_STATE */
if (tzload((char *) NULL, lclptr) != 0) if (tzload((char *) NULL, lclptr, TRUE) != 0)
gmtload(lclptr); gmtload(lclptr);
settzname(); settzname();
} }
@ -1091,7 +1187,7 @@ tzset P((void))
lclptr->ttis[0].tt_gmtoff = 0; lclptr->ttis[0].tt_gmtoff = 0;
lclptr->ttis[0].tt_abbrind = 0; lclptr->ttis[0].tt_abbrind = 0;
(void) strcpy(lclptr->chars, gmt); (void) strcpy(lclptr->chars, gmt);
} else if (tzload(name, lclptr) != 0) } else if (tzload(name, lclptr, TRUE) != 0)
if (name[0] == ':' || tzparse(name, lclptr, FALSE) != 0) if (name[0] == ':' || tzparse(name, lclptr, FALSE) != 0)
(void) gmtload(lclptr); (void) gmtload(lclptr);
settzname(); settzname();
@ -1124,6 +1220,45 @@ struct tm * const tmp;
if (sp == NULL) if (sp == NULL)
return gmtsub(timep, offset, tmp); return gmtsub(timep, offset, tmp);
#endif /* defined ALL_STATE */ #endif /* defined ALL_STATE */
if ((sp->goback && t < sp->ats[0]) ||
(sp->goahead && t > sp->ats[sp->timecnt - 1])) {
time_t newt = t;
register time_t seconds;
register time_t tcycles;
register int_fast64_t icycles;
if (t < sp->ats[0])
seconds = sp->ats[0] - t;
else seconds = t - sp->ats[sp->timecnt - 1];
--seconds;
tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
++tcycles;
icycles = tcycles;
if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
return NULL;
seconds = icycles;
seconds *= YEARSPERREPEAT;
seconds *= AVGSECSPERYEAR;
if (t < sp->ats[0])
newt += seconds;
else newt -= seconds;
if (newt < sp->ats[0] ||
newt > sp->ats[sp->timecnt - 1])
return NULL; /* "cannot happen" */
result = localsub(&newt, offset, tmp);
if (result == tmp) {
register time_t newy;
newy = tmp->tm_year;
if (t < sp->ats[0])
newy -= icycles * YEARSPERREPEAT;
else newy += icycles * YEARSPERREPEAT;
tmp->tm_year = newy;
if (tmp->tm_year != newy)
return NULL;
}
return result;
}
if (sp->timecnt == 0 || t < sp->ats[0]) { if (sp->timecnt == 0 || t < sp->ats[0]) {
i = 0; i = 0;
while (sp->ttis[i].tt_isdst) while (sp->ttis[i].tt_isdst)
@ -1132,10 +1267,17 @@ struct tm * const tmp;
break; break;
} }
} else { } else {
for (i = 1; i < sp->timecnt; ++i) register int lo = 1;
if (t < sp->ats[i]) register int hi = sp->timecnt;
break;
i = (int) sp->types[i - 1]; while (lo < hi) {
register int mid = (lo + hi) >> 1;
if (t < sp->ats[mid])
hi = mid;
else lo = mid + 1;
}
i = (int) sp->types[lo - 1];
} }
ttisp = &sp->ttis[i]; ttisp = &sp->ttis[i];
/* /*
@ -1398,7 +1540,6 @@ register struct tm * const tmp;
** Adapted from code provided by Robert Elz, who writes: ** Adapted from code provided by Robert Elz, who writes:
** The "best" way to do mktime I think is based on an idea of Bob ** The "best" way to do mktime I think is based on an idea of Bob
** Kridle's (so its said...) from a long time ago. ** Kridle's (so its said...) from a long time ago.
** [kridle@xinet.com as of 1996-01-16.]
** It does a binary search of the time_t space. Since time_t's are ** It does a binary search of the time_t space. Since time_t's are
** just 32 bits, its a max of 32 iterations (even at 64 bits it ** just 32 bits, its a max of 32 iterations (even at 64 bits it
** would still be very reasonable). ** would still be very reasonable).
@ -1409,7 +1550,7 @@ register struct tm * const tmp;
#endif /* !defined WRONG */ #endif /* !defined WRONG */
/* /*
** Simplified normalize logic courtesy Paul Eggert (eggert@twinsun.com). ** Simplified normalize logic courtesy Paul Eggert.
*/ */
static int static int
@ -1603,9 +1744,13 @@ const int do_norm_secs;
if (dir != 0) { if (dir != 0) {
if (t == lo) { if (t == lo) {
++t; ++t;
if (t <= lo)
return WRONG;
++lo; ++lo;
} else if (t == hi) { } else if (t == hi) {
--t; --t;
if (t >= hi)
return WRONG;
--hi; --hi;
} }
if (lo > hi) if (lo > hi)
@ -1705,7 +1850,7 @@ const long offset;
t = time2(tmp, funcp, offset, &okay); t = time2(tmp, funcp, offset, &okay);
#ifdef PCTS #ifdef PCTS
/* /*
** PCTS code courtesy Grant Sullivan (grant@osf.org). ** PCTS code courtesy Grant Sullivan.
*/ */
if (okay) if (okay)
return t; return t;

View File

@ -1,6 +1,6 @@
#ifndef lint #ifndef lint
#ifndef NOID #ifndef NOID
static char elsieid[] = "@(#)strftime.c 7.75"; static char elsieid[] = "@(#)strftime.c 8.1";
/* /*
** Based on the UCB version with the ID appearing below. ** Based on the UCB version with the ID appearing below.
** This is ANSIish only when "multibyte character == plain character". ** This is ANSIish only when "multibyte character == plain character".