Deleted Added
full compact
localtime.c (15927) localtime.c (17209)
1/*
2** This file is in the public domain, so clarified as of
3** June 5, 1996 by Arthur David Olson (arthur_david_olson@nih.gov).
4*/
1
5
2
3#ifndef lint
4#ifndef NOID
6#ifndef lint
7#ifndef NOID
5static char elsieid[] = "@(#)localtime.c 7.44";
8static char elsieid[] = "@(#)localtime.c 7.57";
6#endif /* !defined NOID */
7#endif /* !defined lint */
8
9/*
10** Leap second handling from Bradley White (bww@k.gp.cs.cmu.edu).
11** POSIX-style TZ environment variable handling from Guy Harris
12** (guy@auspex.com).
13*/

--- 181 unchanged lines hidden (view full) ---

195
196static long
197detzcode(codep)
198const char * const codep;
199{
200 register long result;
201 register int i;
202
9#endif /* !defined NOID */
10#endif /* !defined lint */
11
12/*
13** Leap second handling from Bradley White (bww@k.gp.cs.cmu.edu).
14** POSIX-style TZ environment variable handling from Guy Harris
15** (guy@auspex.com).
16*/

--- 181 unchanged lines hidden (view full) ---

198
199static long
200detzcode(codep)
201const char * const codep;
202{
203 register long result;
204 register int i;
205
203 result = (codep[0] & 0x80) ? ~0L : 0L;
206 result = (codep[0] & 0x80) ? ~0L : 0L;
204 for (i = 0; i < 4; ++i)
205 result = (result << 8) | (codep[i] & 0xff);
206 return result;
207}
208
209static void
210settzname P((void))
211{
207 for (i = 0; i < 4; ++i)
208 result = (result << 8) | (codep[i] & 0xff);
209 return result;
210}
211
212static void
213settzname P((void))
214{
212 register struct state * const sp = lclptr;
213 register int i;
215 register struct state * const sp = lclptr;
216 register int i;
214
215 tzname[0] = wildabbr;
216 tzname[1] = wildabbr;
217#ifdef USG_COMPAT
218 daylight = 0;
219 timezone = 0;
220#endif /* defined USG_COMPAT */
221#ifdef ALTZONE

--- 198 unchanged lines hidden (view full) ---

420*/
421
422static const char *
423getzname(strp)
424register const char * strp;
425{
426 register char c;
427
217
218 tzname[0] = wildabbr;
219 tzname[1] = wildabbr;
220#ifdef USG_COMPAT
221 daylight = 0;
222 timezone = 0;
223#endif /* defined USG_COMPAT */
224#ifdef ALTZONE

--- 198 unchanged lines hidden (view full) ---

423*/
424
425static const char *
426getzname(strp)
427register const char * strp;
428{
429 register char c;
430
428 while ((c = *strp) != '\0' && !isdigit(c) && c != ',' && c != '-' &&
431 while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
429 c != '+')
430 ++strp;
431 return strp;
432}
433
434/*
435** Given a pointer into a time zone string, extract a number from that string.
436** Check that the number is within a specified range; if it is not, return

--- 6 unchanged lines hidden (view full) ---

443register const char * strp;
444int * const nump;
445const int min;
446const int max;
447{
448 register char c;
449 register int num;
450
432 c != '+')
433 ++strp;
434 return strp;
435}
436
437/*
438** Given a pointer into a time zone string, extract a number from that string.
439** Check that the number is within a specified range; if it is not, return

--- 6 unchanged lines hidden (view full) ---

446register const char * strp;
447int * const nump;
448const int min;
449const int max;
450{
451 register char c;
452 register int num;
453
451 if (strp == NULL || !isdigit(*strp))
454 if (strp == NULL || !is_digit(c = *strp))
452 return NULL;
453 num = 0;
455 return NULL;
456 num = 0;
454 while ((c = *strp) != '\0' && isdigit(c)) {
457 do {
455 num = num * 10 + (c - '0');
456 if (num > max)
457 return NULL; /* illegal value */
458 num = num * 10 + (c - '0');
459 if (num > max)
460 return NULL; /* illegal value */
458 ++strp;
459 }
461 c = *++strp;
462 } while (is_digit(c));
460 if (num < min)
461 return NULL; /* illegal value */
462 *nump = num;
463 return strp;
464}
465
466/*
467** Given a pointer into a time zone string, extract a number of seconds,

--- 45 unchanged lines hidden (view full) ---

513** Otherwise, return a pointer to the first character not part of the time.
514*/
515
516static const char *
517getoffset(strp, offsetp)
518register const char * strp;
519long * const offsetp;
520{
463 if (num < min)
464 return NULL; /* illegal value */
465 *nump = num;
466 return strp;
467}
468
469/*
470** Given a pointer into a time zone string, extract a number of seconds,

--- 45 unchanged lines hidden (view full) ---

516** Otherwise, return a pointer to the first character not part of the time.
517*/
518
519static const char *
520getoffset(strp, offsetp)
521register const char * strp;
522long * const offsetp;
523{
521 register int neg;
524 register int neg = 0;
522
523 if (*strp == '-') {
524 neg = 1;
525 ++strp;
525
526 if (*strp == '-') {
527 neg = 1;
528 ++strp;
526 } else if (isdigit(*strp) || *strp++ == '+')
527 neg = 0;
528 else return NULL; /* illegal offset */
529 } else if (*strp == '+')
530 ++strp;
529 strp = getsecs(strp, offsetp);
530 if (strp == NULL)
531 return NULL; /* illegal time */
532 if (neg)
533 *offsetp = -*offsetp;
534 return strp;
535}
536

--- 28 unchanged lines hidden (view full) ---

565 if (*strp++ != '.')
566 return NULL;
567 strp = getnum(strp, &rulep->r_week, 1, 5);
568 if (strp == NULL)
569 return NULL;
570 if (*strp++ != '.')
571 return NULL;
572 strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
531 strp = getsecs(strp, offsetp);
532 if (strp == NULL)
533 return NULL; /* illegal time */
534 if (neg)
535 *offsetp = -*offsetp;
536 return strp;
537}
538

--- 28 unchanged lines hidden (view full) ---

567 if (*strp++ != '.')
568 return NULL;
569 strp = getnum(strp, &rulep->r_week, 1, 5);
570 if (strp == NULL)
571 return NULL;
572 if (*strp++ != '.')
573 return NULL;
574 strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
573 } else if (isdigit(*strp)) {
575 } else if (is_digit(*strp)) {
574 /*
575 ** Day of year.
576 */
577 rulep->r_type = DAY_OF_YEAR;
578 strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
579 } else return NULL; /* invalid format */
580 if (strp == NULL)
581 return NULL;

--- 225 unchanged lines hidden (view full) ---

807 return -1;
808 /*
809 ** Initial values of theirstdoffset and theirdstoffset.
810 */
811 theirstdoffset = 0;
812 for (i = 0; i < sp->timecnt; ++i) {
813 j = sp->types[i];
814 if (!sp->ttis[j].tt_isdst) {
576 /*
577 ** Day of year.
578 */
579 rulep->r_type = DAY_OF_YEAR;
580 strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
581 } else return NULL; /* invalid format */
582 if (strp == NULL)
583 return NULL;

--- 225 unchanged lines hidden (view full) ---

809 return -1;
810 /*
811 ** Initial values of theirstdoffset and theirdstoffset.
812 */
813 theirstdoffset = 0;
814 for (i = 0; i < sp->timecnt; ++i) {
815 j = sp->types[i];
816 if (!sp->ttis[j].tt_isdst) {
815 theirstdoffset = -sp->ttis[j].tt_gmtoff;
817 theirstdoffset =
818 -sp->ttis[j].tt_gmtoff;
816 break;
817 }
818 }
819 theirdstoffset = 0;
820 for (i = 0; i < sp->timecnt; ++i) {
821 j = sp->types[i];
822 if (sp->ttis[j].tt_isdst) {
819 break;
820 }
821 }
822 theirdstoffset = 0;
823 for (i = 0; i < sp->timecnt; ++i) {
824 j = sp->types[i];
825 if (sp->ttis[j].tt_isdst) {
823 theirdstoffset = -sp->ttis[j].tt_gmtoff;
826 theirdstoffset =
827 -sp->ttis[j].tt_gmtoff;
824 break;
825 }
826 }
827 /*
828 ** Initially we're assumed to be in standard time.
829 */
830 isdst = FALSE;
831 theiroffset = theirstdoffset;

--- 447 unchanged lines hidden (view full) ---

1279 }
1280 while (rem >= SECSPERDAY) {
1281 rem -= SECSPERDAY;
1282 ++days;
1283 }
1284 tmp->tm_hour = (int) (rem / SECSPERHOUR);
1285 rem = rem % SECSPERHOUR;
1286 tmp->tm_min = (int) (rem / SECSPERMIN);
828 break;
829 }
830 }
831 /*
832 ** Initially we're assumed to be in standard time.
833 */
834 isdst = FALSE;
835 theiroffset = theirstdoffset;

--- 447 unchanged lines hidden (view full) ---

1283 }
1284 while (rem >= SECSPERDAY) {
1285 rem -= SECSPERDAY;
1286 ++days;
1287 }
1288 tmp->tm_hour = (int) (rem / SECSPERHOUR);
1289 rem = rem % SECSPERHOUR;
1290 tmp->tm_min = (int) (rem / SECSPERMIN);
1287 tmp->tm_sec = (int) (rem % SECSPERMIN);
1288 if (hit)
1289 /*
1290 ** A positive leap second requires a special
1291 ** representation. This uses "... ??:59:60" et seq.
1292 */
1293 tmp->tm_sec += hit;
1291 /*
1292 ** A positive leap second requires a special
1293 ** representation. This uses "... ??:59:60" et seq.
1294 */
1295 tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
1294 tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK);
1295 if (tmp->tm_wday < 0)
1296 tmp->tm_wday += DAYSPERWEEK;
1297 y = EPOCH_YEAR;
1296 tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK);
1297 if (tmp->tm_wday < 0)
1298 tmp->tm_wday += DAYSPERWEEK;
1299 y = EPOCH_YEAR;
1298 if (days >= 0)
1299 for ( ; ; ) {
1300 yleap = isleap(y);
1301 if (days < (long) year_lengths[yleap])
1302 break;
1303 ++y;
1304 days = days - (long) year_lengths[yleap];
1305 }
1306 else do {
1307 --y;
1308 yleap = isleap(y);
1309 days = days + (long) year_lengths[yleap];
1310 } while (days < 0);
1300#define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400)
1301 while (days < 0 || days >= (long) year_lengths[yleap = isleap(y)]) {
1302 register int newy;
1303
1304 newy = y + days / DAYSPERNYEAR;
1305 if (days < 0)
1306 --newy;
1307 days -= (newy - y) * DAYSPERNYEAR +
1308 LEAPS_THRU_END_OF(newy - 1) -
1309 LEAPS_THRU_END_OF(y - 1);
1310 y = newy;
1311 }
1311 tmp->tm_year = y - TM_YEAR_BASE;
1312 tmp->tm_yday = (int) days;
1313 ip = mon_lengths[yleap];
1314 for (tmp->tm_mon = 0; days >= (long) ip[tmp->tm_mon]; ++(tmp->tm_mon))
1315 days = days - (long) ip[tmp->tm_mon];
1316 tmp->tm_mday = (int) (days + 1);
1317 tmp->tm_isdst = 0;
1318#ifdef TM_GMTOFF

--- 12 unchanged lines hidden (view full) ---

1331** asctime(localtime(timer))
1332*/
1333 return asctime(localtime(timep));
1334}
1335
1336/*
1337** Adapted from code provided by Robert Elz, who writes:
1338** The "best" way to do mktime I think is based on an idea of Bob
1312 tmp->tm_year = y - TM_YEAR_BASE;
1313 tmp->tm_yday = (int) days;
1314 ip = mon_lengths[yleap];
1315 for (tmp->tm_mon = 0; days >= (long) ip[tmp->tm_mon]; ++(tmp->tm_mon))
1316 days = days - (long) ip[tmp->tm_mon];
1317 tmp->tm_mday = (int) (days + 1);
1318 tmp->tm_isdst = 0;
1319#ifdef TM_GMTOFF

--- 12 unchanged lines hidden (view full) ---

1332** asctime(localtime(timer))
1333*/
1334 return asctime(localtime(timep));
1335}
1336
1337/*
1338** Adapted from code provided by Robert Elz, who writes:
1339** The "best" way to do mktime I think is based on an idea of Bob
1339** Kridle's (so its said...) from a long time ago. (mtxinu!kridle now).
1340** Kridle's (so its said...) from a long time ago.
1341** [kridle@xinet.com as of 1996-01-16.]
1340** It does a binary search of the time_t space. Since time_t's are
1341** just 32 bits, its a max of 32 iterations (even at 64 bits it
1342** would still be very reasonable).
1343*/
1344
1345#ifndef WRONG
1346#define WRONG (-1)
1347#endif /* !defined WRONG */

--- 73 unchanged lines hidden (view full) ---

1421 ** Turn yourtm.tm_year into an actual year number for now.
1422 ** It is converted back to an offset from TM_YEAR_BASE later.
1423 */
1424 if (increment_overflow(&yourtm.tm_year, TM_YEAR_BASE))
1425 return WRONG;
1426 while (yourtm.tm_mday <= 0) {
1427 if (increment_overflow(&yourtm.tm_year, -1))
1428 return WRONG;
1342** It does a binary search of the time_t space. Since time_t's are
1343** just 32 bits, its a max of 32 iterations (even at 64 bits it
1344** would still be very reasonable).
1345*/
1346
1347#ifndef WRONG
1348#define WRONG (-1)
1349#endif /* !defined WRONG */

--- 73 unchanged lines hidden (view full) ---

1423 ** Turn yourtm.tm_year into an actual year number for now.
1424 ** It is converted back to an offset from TM_YEAR_BASE later.
1425 */
1426 if (increment_overflow(&yourtm.tm_year, TM_YEAR_BASE))
1427 return WRONG;
1428 while (yourtm.tm_mday <= 0) {
1429 if (increment_overflow(&yourtm.tm_year, -1))
1430 return WRONG;
1429 yourtm.tm_mday += year_lengths[isleap(yourtm.tm_year)];
1431 i = yourtm.tm_year + (1 < yourtm.tm_mon);
1432 yourtm.tm_mday += year_lengths[isleap(i)];
1430 }
1431 while (yourtm.tm_mday > DAYSPERLYEAR) {
1433 }
1434 while (yourtm.tm_mday > DAYSPERLYEAR) {
1432 yourtm.tm_mday -= year_lengths[isleap(yourtm.tm_year)];
1435 i = yourtm.tm_year + (1 < yourtm.tm_mon);
1436 yourtm.tm_mday -= year_lengths[isleap(i)];
1433 if (increment_overflow(&yourtm.tm_year, 1))
1434 return WRONG;
1435 }
1436 for ( ; ; ) {
1437 i = mon_lengths[isleap(yourtm.tm_year)][yourtm.tm_mon];
1438 if (yourtm.tm_mday <= i)
1439 break;
1440 yourtm.tm_mday -= i;

--- 18 unchanged lines hidden (view full) ---

1459 return WRONG;
1460 saved_seconds = yourtm.tm_sec;
1461 yourtm.tm_sec = SECSPERMIN - 1;
1462 } else {
1463 saved_seconds = yourtm.tm_sec;
1464 yourtm.tm_sec = 0;
1465 }
1466 /*
1437 if (increment_overflow(&yourtm.tm_year, 1))
1438 return WRONG;
1439 }
1440 for ( ; ; ) {
1441 i = mon_lengths[isleap(yourtm.tm_year)][yourtm.tm_mon];
1442 if (yourtm.tm_mday <= i)
1443 break;
1444 yourtm.tm_mday -= i;

--- 18 unchanged lines hidden (view full) ---

1463 return WRONG;
1464 saved_seconds = yourtm.tm_sec;
1465 yourtm.tm_sec = SECSPERMIN - 1;
1466 } else {
1467 saved_seconds = yourtm.tm_sec;
1468 yourtm.tm_sec = 0;
1469 }
1470 /*
1467 ** Calculate the number of magnitude bits in a time_t
1468 ** (this works regardless of whether time_t is
1469 ** signed or unsigned, though lint complains if unsigned).
1471 ** Divide the search space in half
1472 ** (this works whether time_t is signed or unsigned).
1470 */
1473 */
1471 for (bits = 0, t = 1; t > 0; ++bits, t <<= 1)
1472 continue;
1474 bits = TYPE_BIT(time_t) - 1;
1473 /*
1475 /*
1474 ** If time_t is signed, then 0 is the median value,
1475 ** if time_t is unsigned, then 1 << bits is median.
1476 ** If time_t is signed, then 0 is just above the median,
1477 ** assuming two's complement arithmetic.
1478 ** If time_t is unsigned, then (1 << bits) is just above the median.
1476 */
1479 */
1477 t = (t < 0) ? 0 : ((time_t) 1 << bits);
1480 t = TYPE_SIGNED(time_t) ? 0 : (((time_t) 1) << bits);
1478 for ( ; ; ) {
1479 (*funcp)(&t, offset, &mytm);
1480 dir = tmcomp(&mytm, &yourtm);
1481 if (dir != 0) {
1482 if (bits-- < 0)
1483 return WRONG;
1484 if (bits < 0)
1481 for ( ; ; ) {
1482 (*funcp)(&t, offset, &mytm);
1483 dir = tmcomp(&mytm, &yourtm);
1484 if (dir != 0) {
1485 if (bits-- < 0)
1486 return WRONG;
1487 if (bits < 0)
1485 --t;
1488 --t; /* may be needed if new t is minimal */
1486 else if (dir > 0)
1489 else if (dir > 0)
1487 t -= (time_t) 1 << bits;
1488 else t += (time_t) 1 << bits;
1490 t -= ((time_t) 1) << bits;
1491 else t += ((time_t) 1) << bits;
1489 continue;
1490 }
1491 if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
1492 break;
1493 /*
1494 ** Right time, wrong type.
1495 ** Hunt for right time, right type.
1496 ** It's okay to guess wrong since the guess

--- 4 unchanged lines hidden (view full) ---

1501 */
1502 sp = (const struct state *)
1503 (((void *) funcp == (void *) localsub) ?
1504 lclptr : gmtptr);
1505#ifdef ALL_STATE
1506 if (sp == NULL)
1507 return WRONG;
1508#endif /* defined ALL_STATE */
1492 continue;
1493 }
1494 if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
1495 break;
1496 /*
1497 ** Right time, wrong type.
1498 ** Hunt for right time, right type.
1499 ** It's okay to guess wrong since the guess

--- 4 unchanged lines hidden (view full) ---

1504 */
1505 sp = (const struct state *)
1506 (((void *) funcp == (void *) localsub) ?
1507 lclptr : gmtptr);
1508#ifdef ALL_STATE
1509 if (sp == NULL)
1510 return WRONG;
1511#endif /* defined ALL_STATE */
1509 for (i = 0; i < sp->typecnt; ++i) {
1512 for (i = sp->typecnt - 1; i >= 0; --i) {
1510 if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
1511 continue;
1513 if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
1514 continue;
1512 for (j = 0; j < sp->typecnt; ++j) {
1515 for (j = sp->typecnt - 1; j >= 0; --j) {
1513 if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
1514 continue;
1515 newt = t + sp->ttis[j].tt_gmtoff -
1516 sp->ttis[i].tt_gmtoff;
1517 (*funcp)(&newt, offset, &mytm);
1518 if (tmcomp(&mytm, &yourtm) != 0)
1519 continue;
1520 if (mytm.tm_isdst != yourtm.tm_isdst)

--- 15 unchanged lines hidden (view full) ---

1536 (*funcp)(&t, offset, tmp);
1537 *okayp = TRUE;
1538 return t;
1539}
1540
1541static time_t
1542time1(tmp, funcp, offset)
1543struct tm * const tmp;
1516 if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
1517 continue;
1518 newt = t + sp->ttis[j].tt_gmtoff -
1519 sp->ttis[i].tt_gmtoff;
1520 (*funcp)(&newt, offset, &mytm);
1521 if (tmcomp(&mytm, &yourtm) != 0)
1522 continue;
1523 if (mytm.tm_isdst != yourtm.tm_isdst)

--- 15 unchanged lines hidden (view full) ---

1539 (*funcp)(&t, offset, tmp);
1540 *okayp = TRUE;
1541 return t;
1542}
1543
1544static time_t
1545time1(tmp, funcp, offset)
1546struct tm * const tmp;
1544void (* const funcp) P((const time_t*, long, struct tm*));
1547void (* const funcp) P((const time_t *, long, struct tm *));
1545const long offset;
1546{
1547 register time_t t;
1548 register const struct state * sp;
1549 register int samei, otheri;
1550 int okay;
1551
1552 if (tmp->tm_isdst > 1)

--- 22 unchanged lines hidden (view full) ---

1575 ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
1576 */
1577 sp = (const struct state *) (((void *) funcp == (void *) localsub) ?
1578 lclptr : gmtptr);
1579#ifdef ALL_STATE
1580 if (sp == NULL)
1581 return WRONG;
1582#endif /* defined ALL_STATE */
1548const long offset;
1549{
1550 register time_t t;
1551 register const struct state * sp;
1552 register int samei, otheri;
1553 int okay;
1554
1555 if (tmp->tm_isdst > 1)

--- 22 unchanged lines hidden (view full) ---

1578 ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
1579 */
1580 sp = (const struct state *) (((void *) funcp == (void *) localsub) ?
1581 lclptr : gmtptr);
1582#ifdef ALL_STATE
1583 if (sp == NULL)
1584 return WRONG;
1585#endif /* defined ALL_STATE */
1583 for (samei = 0; samei < sp->typecnt; ++samei) {
1586 for (samei = sp->typecnt - 1; samei >= 0; --samei) {
1584 if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
1585 continue;
1587 if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
1588 continue;
1586 for (otheri = 0; otheri < sp->typecnt; ++otheri) {
1589 for (otheri = sp->typecnt - 1; otheri >= 0; --otheri) {
1587 if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
1588 continue;
1589 tmp->tm_sec += sp->ttis[otheri].tt_gmtoff -
1590 sp->ttis[samei].tt_gmtoff;
1591 tmp->tm_isdst = !tmp->tm_isdst;
1592 t = time2(tmp, funcp, offset, &okay);
1593 if (okay)
1594 return t;

--- 148 unchanged lines hidden ---
1590 if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
1591 continue;
1592 tmp->tm_sec += sp->ttis[otheri].tt_gmtoff -
1593 sp->ttis[samei].tt_gmtoff;
1594 tmp->tm_isdst = !tmp->tm_isdst;
1595 t = time2(tmp, funcp, offset, &okay);
1596 if (okay)
1597 return t;

--- 148 unchanged lines hidden ---