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
** 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 NOID
static char privatehid[] = "@(#)private.h 7.55";
static char privatehid[] = "@(#)private.h 8.2";
#endif /* !defined NOID */
#endif /* !defined lint */
@ -89,7 +89,7 @@ static char privatehid[] = "@(#)private.h 7.55";
#include "stdio.h"
#include "errno.h"
#include "string.h"
#include "limits.h" /* for CHAR_BIT */
#include "limits.h" /* for CHAR_BIT et al. */
#include "time.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. */
#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.
*/
/*
** SunOS 4.1.1 cc lacks prototypes.
** If your compiler lacks prototypes, "#define P(x) ()".
*/
#ifndef P
#ifdef __STDC__
#define P(x) x
#endif /* defined __STDC__ */
#ifndef __STDC__
#define P(x) ()
#endif /* !defined __STDC__ */
#endif /* !defined P */
/*
@ -211,14 +242,14 @@ extern char * asctime_r();
** Private function declarations.
*/
char * icalloc P((int nelem, int elsize));
char * icatalloc P((char * old, const char * new));
char * icpyalloc P((const char * string));
char * imalloc P((int n));
void * irealloc P((void * pointer, int size));
void icfree P((char * pointer));
void ifree P((char * pointer));
char * scheck P((const char *string, char *format));
char * icalloc P((int nelem, int elsize));
char * icatalloc P((char * old, const char * new));
char * icpyalloc P((const char * string));
char * imalloc P((int n));
void * irealloc P((void * pointer, int size));
void icfree P((char * pointer));
void ifree P((char * pointer));
const char * scheck P((const char * string, const char * format));
/*
** Finally, some convenience items.
@ -310,6 +341,26 @@ char *asctime_r P((struct tm const *, char *));
char *ctime_r P((time_t const *, char *));
#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.
*/

View File

@ -4,7 +4,7 @@
/*
** 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 NOID
static char tzfilehid[] = "@(#)tzfile.h 7.17";
static char tzfilehid[] = "@(#)tzfile.h 8.1";
#endif /* !defined NOID */
#endif /* !defined lint */
@ -49,7 +49,8 @@ static char tzfilehid[] = "@(#)tzfile.h 7.17";
struct tzhead {
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_ttisstdcnt[4]; /* coded number of trans. time flags */
char tzh_leapcnt[4]; /* coded number of leap seconds */
@ -83,19 +84,23 @@ struct tzhead {
** 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
** exceed any of the limits below.
*/
#ifndef TZ_MAX_TIMES
/*
** 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
#define TZ_MAX_TIMES 1200
#endif /* !defined TZ_MAX_TIMES */
#ifndef TZ_MAX_TYPES
@ -105,7 +110,7 @@ struct tzhead {
#ifdef NOSOLAR
/*
** 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 */
#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 NOID
static char elsieid[] = "@(#)ialloc.c 8.29";
static char elsieid[] = "@(#)ialloc.c 8.30";
#endif /* !defined NOID */
#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 NOID
static char elsieid[] = "@(#)scheck.c 8.16";
static char elsieid[] = "@(#)scheck.c 8.19";
#endif /* !defined lint */
#endif /* !defined NOID */
@ -8,20 +13,19 @@ static char elsieid[] = "@(#)scheck.c 8.16";
#include "private.h"
char *
const char *
scheck(string, format)
const char * const string;
char * const format;
const char * const format;
{
register char * fbuf;
register const char * fp;
register char * tp;
register int c;
register char * result;
register const char * result;
char dummy;
static char nada;
result = &nada;
result = "";
if (string == NULL || format == NULL)
return result;
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
@ -12,6 +12,10 @@ static char elsieid[] = "@(#)zdump.c 7.65";
#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. */
#ifndef isascii
#define isascii(x) 1
#endif /* !defined isascii */
#ifndef ZDUMP_LO_YEAR
#define ZDUMP_LO_YEAR (-500)
@ -126,11 +130,7 @@ static char elsieid[] = "@(#)zdump.c 7.65";
#endif /* !defined TZ_DOMAIN */
#ifndef P
#ifdef __STDC__
#define P(x) x
#else /* !defined __STDC__ */
#define P(x) ()
#endif /* !defined __STDC__ */
#endif /* !defined P */
extern char ** environ;
@ -147,7 +147,7 @@ static char * progname;
static int warned;
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 void dumptime P((const struct tm * tmp));
static time_t hunt P((char * name, time_t lot, time_t hit));
@ -194,40 +194,40 @@ time_t * tp;
#endif /* !defined TYPECHECK */
static void
abbrok(abbr, zone)
const char * const abbr;
abbrok(abbrp, zone)
const char * const abbrp;
const char * const zone;
{
register int i;
register const char * cp;
register char * wp;
if (warned)
return;
cp = abbr;
cp = abbrp;
wp = NULL;
while (isascii(*cp) && isalpha(*cp))
while (isascii((unsigned char) *cp) && isalpha((unsigned char) *cp))
++cp;
if (cp - abbr == 0)
if (cp - abbrp == 0)
wp = _("lacks alphabetic at start");
if (cp - abbr < 3)
else if (cp - abbrp < 3)
wp = _("has fewer than 3 alphabetics");
if (cp - abbr > 6)
else if (cp - abbrp > 6)
wp = _("has more than 6 alphabetics");
if (wp == NULL && (*cp == '+' || *cp == '-')) {
++cp;
if (isascii(*cp) && isdigit(*cp))
if (*cp++ == '1' && *cp >= '0' && *cp <= '4')
++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 (*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, abbr, wp);
_("%s: warning: zone \"%s\" abbreviation \"%s\" %s\n"),
progname, zone, abbrp, wp);
warned = TRUE;
}
@ -266,7 +266,7 @@ char * argv[];
for (i = 1; i < argc; ++i)
if (strcmp(argv[i], "--version") == 0) {
(void) printf("%s\n", elsieid);
(void) exit(EXIT_SUCCESS);
exit(EXIT_SUCCESS);
}
vflag = 0;
cutarg = NULL;
@ -279,7 +279,7 @@ char * argv[];
(void) fprintf(stderr,
_("%s: usage is %s [ --version ] [ -v ] [ -c [loyear,]hiyear ] zonename ...\n"),
progname, progname);
(void) exit(EXIT_FAILURE);
exit(EXIT_FAILURE);
}
if (vflag) {
if (cutarg != NULL) {
@ -296,7 +296,7 @@ _("%s: usage is %s [ --version ] [ -v ] [ -c [loyear,]hiyear ] zonename ...\n"),
} else {
(void) fprintf(stderr, _("%s: wild -c argument %s\n"),
progname, cutarg);
(void) exit(EXIT_FAILURE);
exit(EXIT_FAILURE);
}
}
setabsolutes();
@ -319,7 +319,7 @@ _("%s: usage is %s [ --version ] [ -v ] [ -c [loyear,]hiyear ] zonename ...\n"),
if (fakeenv == NULL ||
(fakeenv[0] = (char *) malloc(longest + 4)) == NULL) {
(void) perror(progname);
(void) exit(EXIT_FAILURE);
exit(EXIT_FAILURE);
}
to = 0;
(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)) {
(void) fprintf(stderr, "%s: ", progname);
(void) perror(_("Error writing standard output"));
(void) exit(EXIT_FAILURE);
(void) perror(_("Error writing to standard output"));
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
/* If exit fails to exit... */
@ -410,18 +410,25 @@ setabsolutes()
(void) fprintf(stderr,
_("%s: use of -v on system with floating time_t other than float or double\n"),
progname);
(void) exit(EXIT_FAILURE);
exit(EXIT_FAILURE);
}
} 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)
continue;
absolute_min_time = hibit;
absolute_max_time = -(hibit + 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.
@ -464,10 +471,7 @@ const long y;
}
static time_t
hunt(name, lot, hit)
char * name;
time_t lot;
time_t hit;
hunt(char *name, time_t lot, time_t hit)
{
time_t t;
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
@ -537,10 +541,7 @@ struct tm * oldp;
}
static void
show(zone, t, v)
char * zone;
time_t t;
int v;
show(char *zone, time_t t, int v)
{
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
** 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov).
** 1996-06-05 by Arthur David Olson.
*/
#ifndef lint
#ifndef NOID
static char elsieid[] = "@(#)localtime.c 7.95";
static char elsieid[] = "@(#)localtime.c 8.5";
#endif /* !defined NOID */
#endif /* !defined lint */
/*
** Leap second handling from Bradley White (bww@k.gp.cs.cmu.edu).
** POSIX-style TZ environment variable handling from Guy Harris
** (guy@auspex.com).
** Leap second handling from Bradley White.
** POSIX-style TZ environment variable handling from Guy Harris.
*/
/*LINTLIBRARY*/
@ -111,6 +110,8 @@ struct state {
int timecnt;
int typecnt;
int charcnt;
int goback;
int goahead;
time_t ats[TZ_MAX_TIMES];
unsigned char types[TZ_MAX_TIMES];
struct ttinfo ttis[TZ_MAX_TYPES];
@ -136,8 +137,10 @@ struct rule {
*/
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 * 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,
int max));
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));
static time_t transtime P((time_t janfirst, int year,
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,
int lastditch));
@ -208,7 +212,7 @@ char * tzname[2] = {
** Except for the strftime function, these functions [asctime,
** ctime, gmtime, localtime] return values in one of two static
** 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;
@ -229,12 +233,25 @@ const char * const codep;
register long result;
register int i;
result = (codep[0] & 0x80) ? ~0L : 0L;
result = (codep[0] & 0x80) ? ~0L : 0;
for (i = 0; i < 4; ++i)
result = (result << 8) | (codep[i] & 0xff);
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
settzname P((void))
{
@ -304,13 +321,33 @@ settzname P((void))
}
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 struct state * const sp;
register const int doextend;
{
register const char * p;
register int i;
register int fid;
register const char * p;
register int i;
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)
return -1;
@ -348,18 +385,13 @@ register struct state * const sp;
if ((fid = open(name, OPEN_MODE)) == -1)
return -1;
}
{
struct tzhead * tzhp;
union {
struct tzhead tzhead;
char buf[sizeof *sp + sizeof *tzhp];
} u;
nread = read(fid, u.buf, sizeof u.buf);
if (close(fid) < 0 || nread <= 0)
return -1;
for (stored = 4; stored <= 8; stored *= 2) {
int ttisstdcnt;
int ttisgmtcnt;
i = read(fid, u.buf, sizeof u.buf);
if (close(fid) != 0)
return -1;
ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt);
ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt);
sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt);
@ -374,17 +406,19 @@ register struct state * const sp;
(ttisstdcnt != sp->typecnt && ttisstdcnt != 0) ||
(ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0))
return -1;
if (i - (p - u.buf) < sp->timecnt * 4 + /* ats */
if (nread - (p - u.buf) <
sp->timecnt * stored + /* ats */
sp->timecnt + /* types */
sp->typecnt * (4 + 2) + /* ttinfos */
sp->typecnt * 6 + /* ttinfos */
sp->charcnt + /* chars */
sp->leapcnt * (4 + 4) + /* lsinfos */
sp->leapcnt * (stored + 4) + /* lsinfos */
ttisstdcnt + /* ttisstds */
ttisgmtcnt) /* ttisgmts */
return -1;
for (i = 0; i < sp->timecnt; ++i) {
sp->ats[i] = detzcode(p);
p += 4;
sp->ats[i] = (stored == 4) ?
detzcode(p) : detzcode64(p);
p += stored;
}
for (i = 0; i < sp->timecnt; ++i) {
sp->types[i] = (unsigned char) *p++;
@ -412,8 +446,9 @@ register struct state * const sp;
register struct lsinfo * lsisp;
lsisp = &sp->lsis[i];
lsisp->ls_trans = detzcode(p);
p += 4;
lsisp->ls_trans = (stored == 4) ?
detzcode(p) : detzcode64(p);
p += stored;
lsisp->ls_corr = detzcode(p);
p += 4;
}
@ -470,7 +505,63 @@ register struct state * const sp;
}
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;
}
@ -503,19 +594,17 @@ register const char * strp;
/*
** 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
** 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 *
getqzname(strp, delim)
register const char * strp;
const char delim;
getqzname(register const char *strp, const int delim)
{
register char c;
register int c;
while ((c = *strp) != '\0' && c != delim)
++strp;
@ -824,7 +913,7 @@ const int lastditch;
if (name == NULL)
return -1;
}
load_result = tzload(TZDEFRULES, sp);
load_result = tzload(TZDEFRULES, sp, FALSE);
if (load_result != 0)
sp->leapcnt = 0; /* so, we're off a little */
if (*name != '\0') {
@ -866,11 +955,8 @@ const int lastditch;
return -1;
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_isdst = 1;
sp->ttis[0].tt_abbrind = stdlen + 1;
@ -880,7 +966,12 @@ const int lastditch;
atp = sp->ats;
typep = sp->types;
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,
stdoffset);
endtime = transtime(janfirst, year, &end,
@ -896,8 +987,13 @@ const int lastditch;
*atp++ = endtime;
*typep++ = 1; /* DST ends */
}
janfirst += year_lengths[isleap(year)] *
sp->timecnt += 2;
newfirst = janfirst;
newfirst += year_lengths[isleap(year)] *
SECSPERDAY;
if (newfirst <= janfirst)
break;
janfirst = newfirst;
}
} else {
register long theirstdoffset;
@ -1012,7 +1108,7 @@ static void
gmtload(sp)
struct state * const sp;
{
if (tzload(gmt, sp) != 0)
if (tzload(gmt, sp, TRUE) != 0)
(void) tzparse(gmt, sp, TRUE);
}
@ -1039,7 +1135,7 @@ tzsetwall P((void))
}
}
#endif /* defined ALL_STATE */
if (tzload((char *) NULL, lclptr) != 0)
if (tzload((char *) NULL, lclptr, TRUE) != 0)
gmtload(lclptr);
settzname();
}
@ -1091,7 +1187,7 @@ tzset P((void))
lclptr->ttis[0].tt_gmtoff = 0;
lclptr->ttis[0].tt_abbrind = 0;
(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)
(void) gmtload(lclptr);
settzname();
@ -1124,6 +1220,45 @@ struct tm * const tmp;
if (sp == NULL)
return gmtsub(timep, offset, tmp);
#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]) {
i = 0;
while (sp->ttis[i].tt_isdst)
@ -1132,10 +1267,17 @@ struct tm * const tmp;
break;
}
} else {
for (i = 1; i < sp->timecnt; ++i)
if (t < sp->ats[i])
break;
i = (int) sp->types[i - 1];
register int lo = 1;
register int hi = sp->timecnt;
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];
/*
@ -1398,7 +1540,6 @@ register struct tm * const tmp;
** Adapted from code provided by Robert Elz, who writes:
** 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@xinet.com as of 1996-01-16.]
** 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
** would still be very reasonable).
@ -1409,7 +1550,7 @@ register struct tm * const tmp;
#endif /* !defined WRONG */
/*
** Simplified normalize logic courtesy Paul Eggert (eggert@twinsun.com).
** Simplified normalize logic courtesy Paul Eggert.
*/
static int
@ -1603,9 +1744,13 @@ const int do_norm_secs;
if (dir != 0) {
if (t == lo) {
++t;
if (t <= lo)
return WRONG;
++lo;
} else if (t == hi) {
--t;
if (t >= hi)
return WRONG;
--hi;
}
if (lo > hi)
@ -1705,7 +1850,7 @@ const long offset;
t = time2(tmp, funcp, offset, &okay);
#ifdef PCTS
/*
** PCTS code courtesy Grant Sullivan (grant@osf.org).
** PCTS code courtesy Grant Sullivan.
*/
if (okay)
return t;

View File

@ -1,6 +1,6 @@
#ifndef lint
#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.
** This is ANSIish only when "multibyte character == plain character".