Updated to tzcode2005c.tar.gz

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@11228 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Jérôme Duval 2005-02-02 22:42:24 +00:00
parent fa12e0eeff
commit aafd5156d4

View File

@ -5,7 +5,7 @@
#ifndef lint
#ifndef NOID
static char elsieid[] = "@(#)localtime.c 7.80";
static char elsieid[] = "@(#)localtime.c 7.89";
#endif /* !defined NOID */
#endif /* !defined lint */
@ -55,7 +55,7 @@ static char elsieid[] = "@(#)localtime.c 7.80";
#define WILDABBR " "
#endif /* !defined WILDABBR */
static char wildabbr[] = "WILDABBR";
static char wildabbr[] = WILDABBR;
static const char gmt[] = "GMT";
@ -129,11 +129,12 @@ static const char * getsecs P((const char * strp, long * secsp));
static const char * getoffset P((const char * strp, long * offsetp));
static const char * getrule P((const char * strp, struct rule * rulep));
static void gmtload P((struct state * sp));
static void gmtsub P((const time_t * timep, long offset,
static struct tm * gmtsub P((const time_t * timep, long offset,
struct tm * tmp));
static void localsub P((const time_t * timep, long offset,
static struct tm * localsub P((const time_t * timep, long offset,
struct tm * tmp));
static int increment_overflow P((int * number, int delta));
static int leaps_thru_end_of P((int y));
static int long_increment_overflow P((long * number, int delta));
static int long_normalize_overflow P((long * tensptr,
int * unitsptr, int base));
@ -141,18 +142,18 @@ static int normalize_overflow P((int * tensptr, int * unitsptr,
int base));
static void settzname P((void));
static time_t time1 P((struct tm * tmp,
void(*funcp) P((const time_t *,
struct tm * (*funcp) P((const time_t *,
long, struct tm *)),
long offset));
static time_t time2 P((struct tm *tmp,
void(*funcp) P((const time_t *,
struct tm * (*funcp) P((const time_t *,
long, struct tm*)),
long offset, int * okayp));
static time_t time2sub P((struct tm *tmp,
void(*funcp) P((const time_t *,
struct tm * (*funcp) P((const time_t *,
long, struct tm*)),
long offset, int * okayp, int do_norm_secs));
static void timesub P((const time_t * timep, long offset,
static struct tm * timesub P((const time_t * timep, long offset,
const struct state * sp, struct tm * tmp));
static int tmcomp P((const struct tm * atmp,
const struct tm * btmp));
@ -409,6 +410,33 @@ register struct state * const sp;
return -1;
}
}
/*
** Out-of-sort ats should mean we're running on a
** signed time_t system but using a data file with
** unsigned values (or vice versa).
*/
for (i = 0; i < sp->timecnt - 2; ++i)
if (sp->ats[i] > sp->ats[i + 1]) {
++i;
if (TYPE_SIGNED(time_t)) {
/*
** Ignore the end (easy).
*/
sp->timecnt = i;
} else {
/*
** Ignore the beginning (harder).
*/
register int j;
for (j = 0; j + i < sp->timecnt; ++j) {
sp->ats[j] = sp->ats[j + i];
sp->types[j] = sp->types[j + i];
}
sp->timecnt = j;
}
break;
}
}
return 0;
}
@ -1010,7 +1038,7 @@ tzset P((void))
*/
/*ARGSUSED*/
static void
static struct tm *
localsub(timep, offset, tmp)
const time_t * const timep;
const long offset;
@ -1019,14 +1047,13 @@ struct tm * const tmp;
register struct state * sp;
register const struct ttinfo * ttisp;
register int i;
register struct tm * result;
const time_t t = *timep;
sp = lclptr;
#ifdef ALL_STATE
if (sp == NULL) {
gmtsub(timep, offset, tmp);
return;
}
if (sp == NULL)
return gmtsub(timep, offset, tmp);
#endif /* defined ALL_STATE */
if (sp->timecnt == 0 || t < sp->ats[0]) {
i = 0;
@ -1039,7 +1066,7 @@ struct tm * const tmp;
for (i = 1; i < sp->timecnt; ++i)
if (t < sp->ats[i])
break;
i = sp->types[i - 1];
i = (int) sp->types[i - 1];
}
ttisp = &sp->ttis[i];
/*
@ -1048,12 +1075,13 @@ struct tm * const tmp;
** t += ttisp->tt_gmtoff;
** timesub(&t, 0L, sp, tmp);
*/
timesub(&t, ttisp->tt_gmtoff, sp, tmp);
result = timesub(&t, ttisp->tt_gmtoff, sp, tmp);
tmp->tm_isdst = ttisp->tt_isdst;
tzname[tmp->tm_isdst] = &sp->chars[ttisp->tt_abbrind];
#ifdef TM_ZONE
tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind];
#endif /* defined TM_ZONE */
return result;
}
struct tm *
@ -1061,8 +1089,7 @@ localtime(timep)
const time_t * const timep;
{
tzset();
localsub(timep, 0L, &tm);
return &tm;
return localsub(timep, 0L, &tm);
}
/*
@ -1070,24 +1097,25 @@ const time_t * const timep;
*/
struct tm *
localtime_r(timep, tm)
localtime_r(timep, tmp)
const time_t * const timep;
struct tm * tm;
struct tm * tmp;
{
localsub(timep, 0L, tm);
return tm;
return localsub(timep, 0L, tmp);
}
/*
** gmtsub is to gmtime as localsub is to localtime.
*/
static void
static struct tm *
gmtsub(timep, offset, tmp)
const time_t * const timep;
const long offset;
struct tm * const tmp;
{
register struct tm * result;
if (!gmt_is_set) {
gmt_is_set = TRUE;
#ifdef ALL_STATE
@ -1096,7 +1124,7 @@ struct tm * const tmp;
#endif /* defined ALL_STATE */
gmtload(gmtptr);
}
timesub(timep, offset, gmtptr, tmp);
result = timesub(timep, offset, gmtptr, tmp);
#ifdef TM_ZONE
/*
** Could get fancy here and deliver something such as
@ -1116,14 +1144,14 @@ struct tm * const tmp;
#endif /* State Farm */
}
#endif /* defined TM_ZONE */
return result;
}
struct tm *
gmtime(timep)
const time_t * const timep;
{
gmtsub(timep, 0L, &tm);
return &tm;
return gmtsub(timep, 0L, &tm);
}
/*
@ -1131,12 +1159,11 @@ const time_t * const timep;
*/
struct tm *
gmtime_r(timep, tm)
gmtime_r(timep, tmp)
const time_t * const timep;
struct tm * tm;
struct tm * tmp;
{
gmtsub(timep, 0L, tm);
return tm;
return gmtsub(timep, 0L, tmp);
}
#ifdef STD_INSPIRED
@ -1146,13 +1173,25 @@ offtime(timep, offset)
const time_t * const timep;
const long offset;
{
gmtsub(timep, offset, &tm);
return &tm;
return gmtsub(timep, offset, &tm);
}
#endif /* defined STD_INSPIRED */
static void
/*
** Return the number of leap years through the end of the given year
** where, to make the math easy, the answer for year zero is defined as zero.
*/
static int
leaps_thru_end_of(y)
register const int y;
{
return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
-(leaps_thru_end_of(-(y + 1)) + 1);
}
static struct tm *
timesub(timep, offset, sp, tmp)
const time_t * const timep;
const long offset;
@ -1160,10 +1199,10 @@ register const struct state * const sp;
register struct tm * const tmp;
{
register const struct lsinfo * lp;
register long days;
register time_t tdays;
register int idays; /* unsigned would be so 2003 */
register long rem;
register long y;
register int yleap;
int y;
register const int * ip;
register long corr;
register int hit;
@ -1197,60 +1236,93 @@ register struct tm * const tmp;
break;
}
}
days = *timep / SECSPERDAY;
rem = *timep % SECSPERDAY;
#ifdef mc68k
if (*timep == 0x80000000) {
/*
** A 3B1 muffs the division on the most negative number.
*/
days = -24855;
rem = -11648;
y = EPOCH_YEAR;
tdays = *timep / SECSPERDAY;
rem = *timep - tdays * SECSPERDAY;
while (tdays < 0 || tdays >= year_lengths[isleap(y)]) {
int newy;
register time_t tdelta;
register int idelta;
register int leapdays;
tdelta = tdays / DAYSPERLYEAR;
idelta = tdelta;
if (tdelta - idelta >= 1 || idelta - tdelta >= 1)
return NULL;
if (idelta == 0)
idelta = (tdays < 0) ? -1 : 1;
newy = y;
if (increment_overflow(&newy, idelta))
return NULL;
leapdays = leaps_thru_end_of(newy - 1) -
leaps_thru_end_of(y - 1);
tdays -= ((time_t) newy - y) * DAYSPERNYEAR;
tdays -= leapdays;
y = newy;
}
#endif /* defined mc68k */
rem += (offset - corr);
{
register long seconds;
seconds = tdays * SECSPERDAY + 0.5;
tdays = seconds / SECSPERDAY;
rem += seconds - tdays * SECSPERDAY;
}
/*
** Given the range, we can now fearlessly cast...
*/
idays = tdays;
rem += offset - corr;
while (rem < 0) {
rem += SECSPERDAY;
--days;
--idays;
}
while (rem >= SECSPERDAY) {
rem -= SECSPERDAY;
++days;
++idays;
}
while (idays < 0) {
if (increment_overflow(&y, -1))
return NULL;
idays += year_lengths[isleap(y)];
}
while (idays >= year_lengths[isleap(y)]) {
idays -= year_lengths[isleap(y)];
if (increment_overflow(&y, 1))
return NULL;
}
tmp->tm_year = y;
if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE))
return NULL;
tmp->tm_yday = idays;
/*
** The "extra" mods below avoid overflow problems.
*/
tmp->tm_wday = EPOCH_WDAY +
((y - EPOCH_YEAR) % DAYSPERWEEK) *
(DAYSPERNYEAR % DAYSPERWEEK) +
leaps_thru_end_of(y - 1) -
leaps_thru_end_of(EPOCH_YEAR - 1) +
idays;
tmp->tm_wday %= DAYSPERWEEK;
if (tmp->tm_wday < 0)
tmp->tm_wday += DAYSPERWEEK;
tmp->tm_hour = (int) (rem / SECSPERHOUR);
rem = rem % SECSPERHOUR;
rem %= SECSPERHOUR;
tmp->tm_min = (int) (rem / SECSPERMIN);
/*
** A positive leap second requires a special
** representation. This uses "... ??:59:60" et seq.
*/
tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK);
if (tmp->tm_wday < 0)
tmp->tm_wday += DAYSPERWEEK;
y = EPOCH_YEAR;
#define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400)
while (days < 0 || days >= (long) year_lengths[yleap = isleap(y)]) {
register long newy;
newy = y + days / DAYSPERNYEAR;
if (days < 0)
--newy;
days -= (newy - y) * DAYSPERNYEAR +
LEAPS_THRU_END_OF(newy - 1) -
LEAPS_THRU_END_OF(y - 1);
y = newy;
}
tmp->tm_year = y - TM_YEAR_BASE;
tmp->tm_yday = (int) days;
ip = mon_lengths[yleap];
for (tmp->tm_mon = 0; days >= (long) ip[tmp->tm_mon]; ++(tmp->tm_mon))
days = days - (long) ip[tmp->tm_mon];
tmp->tm_mday = (int) (days + 1);
ip = mon_lengths[isleap(y)];
for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
idays -= ip[tmp->tm_mon];
tmp->tm_mday = (int) (idays + 1);
tmp->tm_isdst = 0;
#ifdef TM_GMTOFF
tmp->TM_GMTOFF = offset;
#endif /* defined TM_GMTOFF */
return tmp;
}
@ -1345,17 +1417,18 @@ register const struct tm * const btmp;
static time_t
time2sub(tmp, funcp, offset, okayp, do_norm_secs)
struct tm * const tmp;
void (* const funcp) P((const time_t*, long, struct tm*));
struct tm * (* const funcp) P((const time_t*, long, struct tm*));
const long offset;
int * const okayp;
const int do_norm_secs;
{
register const struct state * sp;
register int dir;
register int bits;
register int i, j;
register int saved_seconds;
register long li;
register time_t lo;
register time_t hi;
long y;
time_t newt;
time_t t;
@ -1429,27 +1502,49 @@ const int do_norm_secs;
yourtm.tm_sec = 0;
}
/*
** Divide the search space in half
** (this works whether time_t is signed or unsigned).
** Do a binary search (this works whatever time_t's type is).
*/
bits = TYPE_BIT(time_t) - 1;
/*
** If time_t is signed, then 0 is just above the median,
** assuming two's complement arithmetic.
** If time_t is unsigned, then (1 << bits) is just above the median.
*/
t = TYPE_SIGNED(time_t) ? 0 : (((time_t) 1) << bits);
if (!TYPE_SIGNED(time_t)) {
lo = 0;
hi = lo - 1;
} else if (!TYPE_INTEGRAL(time_t)) {
if (sizeof(time_t) > sizeof(float))
hi = (time_t) DBL_MAX;
else hi = (time_t) FLT_MAX;
lo = -hi;
} else {
lo = 1;
for (i = 0; i < (int) TYPE_BIT(time_t) - 1; ++i)
lo *= 2;
hi = -(lo + 1);
}
for ( ; ; ) {
(*funcp)(&t, offset, &mytm);
dir = tmcomp(&mytm, &yourtm);
t = lo / 2 + hi / 2;
if (t < lo)
t = lo;
else if (t > hi)
t = hi;
if ((*funcp)(&t, offset, &mytm) == NULL) {
/*
** Assume that t is too extreme to be represented in
** a struct tm; arrange things so that it is less
** extreme on the next pass.
*/
dir = (t > 0) ? 1 : -1;
} else dir = tmcomp(&mytm, &yourtm);
if (dir != 0) {
if (bits-- < 0)
if (t == lo) {
++t;
++lo;
} else if (t == hi) {
--t;
--hi;
}
if (lo > hi)
return WRONG;
if (bits < 0)
--t; /* may be needed if new t is minimal */
else if (dir > 0)
t -= ((time_t) 1) << bits;
else t += ((time_t) 1) << bits;
if (dir > 0)
hi = t;
else lo = t;
continue;
}
if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
@ -1478,7 +1573,8 @@ const int do_norm_secs;
continue;
newt = t + sp->ttis[j].tt_gmtoff -
sp->ttis[i].tt_gmtoff;
(*funcp)(&newt, offset, &mytm);
if ((*funcp)(&newt, offset, &mytm) == NULL)
continue;
if (tmcomp(&mytm, &yourtm) != 0)
continue;
if (mytm.tm_isdst != yourtm.tm_isdst)
@ -1497,15 +1593,15 @@ label:
if ((newt < t) != (saved_seconds < 0))
return WRONG;
t = newt;
(*funcp)(&t, offset, tmp);
*okayp = TRUE;
if ((*funcp)(&t, offset, tmp))
*okayp = TRUE;
return t;
}
static time_t
time2(tmp, funcp, offset, okayp)
struct tm * const tmp;
void (* const funcp) P((const time_t*, long, struct tm*));
struct tm * (* const funcp) P((const time_t*, long, struct tm*));
const long offset;
int * const okayp;
{
@ -1523,7 +1619,7 @@ int * const okayp;
static time_t
time1(tmp, funcp, offset)
struct tm * const tmp;
void (* const funcp) P((const time_t *, long, struct tm *));
struct tm * (* const funcp) P((const time_t *, long, struct tm *));
const long offset;
{
register time_t t;