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 --- |