summaryrefslogtreecommitdiffstats
path: root/lib/libc/stdtime/localtime.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libc/stdtime/localtime.c')
-rw-r--r--lib/libc/stdtime/localtime.c115
1 files changed, 59 insertions, 56 deletions
diff --git a/lib/libc/stdtime/localtime.c b/lib/libc/stdtime/localtime.c
index c4cfc88..ecb201b 100644
--- a/lib/libc/stdtime/localtime.c
+++ b/lib/libc/stdtime/localtime.c
@@ -1,8 +1,11 @@
-
+/*
+** This file is in the public domain, so clarified as of
+** June 5, 1996 by Arthur David Olson (arthur_david_olson@nih.gov).
+*/
#ifndef lint
#ifndef NOID
-static char elsieid[] = "@(#)localtime.c 7.44";
+static char elsieid[] = "@(#)localtime.c 7.57";
#endif /* !defined NOID */
#endif /* !defined lint */
@@ -200,7 +203,7 @@ const char * const codep;
register long result;
register int i;
- result = (codep[0] & 0x80) ? ~0L : 0L;
+ result = (codep[0] & 0x80) ? ~0L : 0L;
for (i = 0; i < 4; ++i)
result = (result << 8) | (codep[i] & 0xff);
return result;
@@ -209,8 +212,8 @@ const char * const codep;
static void
settzname P((void))
{
- register struct state * const sp = lclptr;
- register int i;
+ register struct state * const sp = lclptr;
+ register int i;
tzname[0] = wildabbr;
tzname[1] = wildabbr;
@@ -425,7 +428,7 @@ register const char * strp;
{
register char c;
- while ((c = *strp) != '\0' && !isdigit(c) && c != ',' && c != '-' &&
+ while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
c != '+')
++strp;
return strp;
@@ -448,15 +451,15 @@ const int max;
register char c;
register int num;
- if (strp == NULL || !isdigit(*strp))
+ if (strp == NULL || !is_digit(c = *strp))
return NULL;
num = 0;
- while ((c = *strp) != '\0' && isdigit(c)) {
+ do {
num = num * 10 + (c - '0');
if (num > max)
return NULL; /* illegal value */
- ++strp;
- }
+ c = *++strp;
+ } while (is_digit(c));
if (num < min)
return NULL; /* illegal value */
*nump = num;
@@ -518,14 +521,13 @@ getoffset(strp, offsetp)
register const char * strp;
long * const offsetp;
{
- register int neg;
+ register int neg = 0;
if (*strp == '-') {
neg = 1;
++strp;
- } else if (isdigit(*strp) || *strp++ == '+')
- neg = 0;
- else return NULL; /* illegal offset */
+ } else if (*strp == '+')
+ ++strp;
strp = getsecs(strp, offsetp);
if (strp == NULL)
return NULL; /* illegal time */
@@ -570,7 +572,7 @@ register struct rule * const rulep;
if (*strp++ != '.')
return NULL;
strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
- } else if (isdigit(*strp)) {
+ } else if (is_digit(*strp)) {
/*
** Day of year.
*/
@@ -812,7 +814,8 @@ const int lastditch;
for (i = 0; i < sp->timecnt; ++i) {
j = sp->types[i];
if (!sp->ttis[j].tt_isdst) {
- theirstdoffset = -sp->ttis[j].tt_gmtoff;
+ theirstdoffset =
+ -sp->ttis[j].tt_gmtoff;
break;
}
}
@@ -820,7 +823,8 @@ const int lastditch;
for (i = 0; i < sp->timecnt; ++i) {
j = sp->types[i];
if (sp->ttis[j].tt_isdst) {
- theirdstoffset = -sp->ttis[j].tt_gmtoff;
+ theirdstoffset =
+ -sp->ttis[j].tt_gmtoff;
break;
}
}
@@ -1284,30 +1288,27 @@ register struct tm * const tmp;
tmp->tm_hour = (int) (rem / SECSPERHOUR);
rem = rem % SECSPERHOUR;
tmp->tm_min = (int) (rem / SECSPERMIN);
- tmp->tm_sec = (int) (rem % SECSPERMIN);
- if (hit)
- /*
- ** A positive leap second requires a special
- ** representation. This uses "... ??:59:60" et seq.
- */
- tmp->tm_sec += hit;
+ /*
+ ** 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;
- if (days >= 0)
- for ( ; ; ) {
- yleap = isleap(y);
- if (days < (long) year_lengths[yleap])
- break;
- ++y;
- days = days - (long) year_lengths[yleap];
- }
- else do {
- --y;
- yleap = isleap(y);
- days = days + (long) year_lengths[yleap];
- } while (days < 0);
+#define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400)
+ while (days < 0 || days >= (long) year_lengths[yleap = isleap(y)]) {
+ register int 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];
@@ -1336,7 +1337,8 @@ const time_t * const timep;
/*
** 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. (mtxinu!kridle now).
+** 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).
@@ -1426,10 +1428,12 @@ int * const okayp;
while (yourtm.tm_mday <= 0) {
if (increment_overflow(&yourtm.tm_year, -1))
return WRONG;
- yourtm.tm_mday += year_lengths[isleap(yourtm.tm_year)];
+ i = yourtm.tm_year + (1 < yourtm.tm_mon);
+ yourtm.tm_mday += year_lengths[isleap(i)];
}
while (yourtm.tm_mday > DAYSPERLYEAR) {
- yourtm.tm_mday -= year_lengths[isleap(yourtm.tm_year)];
+ i = yourtm.tm_year + (1 < yourtm.tm_mon);
+ yourtm.tm_mday -= year_lengths[isleap(i)];
if (increment_overflow(&yourtm.tm_year, 1))
return WRONG;
}
@@ -1464,17 +1468,16 @@ int * const okayp;
yourtm.tm_sec = 0;
}
/*
- ** Calculate the number of magnitude bits in a time_t
- ** (this works regardless of whether time_t is
- ** signed or unsigned, though lint complains if unsigned).
+ ** Divide the search space in half
+ ** (this works whether time_t is signed or unsigned).
*/
- for (bits = 0, t = 1; t > 0; ++bits, t <<= 1)
- continue;
+ bits = TYPE_BIT(time_t) - 1;
/*
- ** If time_t is signed, then 0 is the median value,
- ** if time_t is unsigned, then 1 << bits is median.
+ ** 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 = (t < 0) ? 0 : ((time_t) 1 << bits);
+ t = TYPE_SIGNED(time_t) ? 0 : (((time_t) 1) << bits);
for ( ; ; ) {
(*funcp)(&t, offset, &mytm);
dir = tmcomp(&mytm, &yourtm);
@@ -1482,10 +1485,10 @@ int * const okayp;
if (bits-- < 0)
return WRONG;
if (bits < 0)
- --t;
+ --t; /* may be needed if new t is minimal */
else if (dir > 0)
- t -= (time_t) 1 << bits;
- else t += (time_t) 1 << bits;
+ t -= ((time_t) 1) << bits;
+ else t += ((time_t) 1) << bits;
continue;
}
if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
@@ -1506,10 +1509,10 @@ int * const okayp;
if (sp == NULL)
return WRONG;
#endif /* defined ALL_STATE */
- for (i = 0; i < sp->typecnt; ++i) {
+ for (i = sp->typecnt - 1; i >= 0; --i) {
if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
continue;
- for (j = 0; j < sp->typecnt; ++j) {
+ for (j = sp->typecnt - 1; j >= 0; --j) {
if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
continue;
newt = t + sp->ttis[j].tt_gmtoff -
@@ -1541,7 +1544,7 @@ label:
static time_t
time1(tmp, funcp, offset)
struct tm * const tmp;
-void (* const funcp) P((const time_t*, long, struct tm*));
+void (* const funcp) P((const time_t *, long, struct tm *));
const long offset;
{
register time_t t;
@@ -1580,10 +1583,10 @@ const long offset;
if (sp == NULL)
return WRONG;
#endif /* defined ALL_STATE */
- for (samei = 0; samei < sp->typecnt; ++samei) {
+ for (samei = sp->typecnt - 1; samei >= 0; --samei) {
if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
continue;
- for (otheri = 0; otheri < sp->typecnt; ++otheri) {
+ for (otheri = sp->typecnt - 1; otheri >= 0; --otheri) {
if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
continue;
tmp->tm_sec += sp->ttis[otheri].tt_gmtoff -
OpenPOWER on IntegriCloud