1/* 2** This file is in the public domain, so clarified as of 3** 1996-06-05 by Arthur David Olson. 4*/ 5 6#ifndef lint 7#ifndef NOID 8static char elsieid[] = "@(#)localtime.c 8.5"; 9#endif /* !defined NOID */ 10#endif /* !defined lint */ 11 12/* 13** Leap second handling from Bradley White. 14** POSIX-style TZ environment variable handling from Guy Harris. 15*/ 16 17/*LINTLIBRARY*/ 18 19#include "private.h" 20#include "tzfile.h" 21#include "fcntl.h" 22#include "float.h" /* for FLT_MAX and DBL_MAX */ 23 24#ifndef TZ_ABBR_MAX_LEN 25#define TZ_ABBR_MAX_LEN 16 26#endif /* !defined TZ_ABBR_MAX_LEN */ 27 28#ifndef TZ_ABBR_CHAR_SET 29#define TZ_ABBR_CHAR_SET \ 30 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._" 31#endif /* !defined TZ_ABBR_CHAR_SET */ 32 33#ifndef TZ_ABBR_ERR_CHAR 34#define TZ_ABBR_ERR_CHAR '_' 35#endif /* !defined TZ_ABBR_ERR_CHAR */ 36 37/* 38** SunOS 4.1.1 headers lack O_BINARY. 39*/ 40 41#ifdef O_BINARY 42#define OPEN_MODE (O_RDONLY | O_BINARY) 43#endif /* defined O_BINARY */ 44#ifndef O_BINARY 45#define OPEN_MODE O_RDONLY 46#endif /* !defined O_BINARY */ 47 48#ifndef WILDABBR 49/* 50** Someone might make incorrect use of a time zone abbreviation: 51** 1. They might reference tzname[0] before calling tzset (explicitly 52** or implicitly). 53** 2. They might reference tzname[1] before calling tzset (explicitly 54** or implicitly). 55** 3. They might reference tzname[1] after setting to a time zone 56** in which Daylight Saving Time is never observed. 57** 4. They might reference tzname[0] after setting to a time zone 58** in which Standard Time is never observed. 59** 5. They might reference tm.TM_ZONE after calling offtime. 60** What's best to do in the above cases is open to debate; 61** for now, we just set things up so that in any of the five cases 62** WILDABBR is used. Another possibility: initialize tzname[0] to the 63** string "tzname[0] used before set", and similarly for the other cases. 64** And another: initialize tzname[0] to "ERA", with an explanation in the 65** manual page of what this "time zone abbreviation" means (doing this so 66** that tzname[0] has the "normal" length of three characters). 67*/ 68#define WILDABBR " " 69#endif /* !defined WILDABBR */ 70 71static char wildabbr[] = WILDABBR; 72 73static const char gmt[] = "GMT"; 74 75/* 76** The DST rules to use if TZ has no rules and we can't load TZDEFRULES. 77** We default to US rules as of 1999-08-17. 78** POSIX 1003.1 section 8.1.1 says that the default DST rules are 79** implementation dependent; for historical reasons, US rules are a 80** common default. 81*/ 82#ifndef TZDEFRULESTRING 83#define TZDEFRULESTRING ",M4.1.0,M10.5.0" 84#endif /* !defined TZDEFDST */ 85 86struct ttinfo { /* time type information */ 87 long tt_gmtoff; /* UTC offset in seconds */ 88 int tt_isdst; /* used to set tm_isdst */ 89 int tt_abbrind; /* abbreviation list index */ 90 int tt_ttisstd; /* TRUE if transition is std time */ 91 int tt_ttisgmt; /* TRUE if transition is UTC */ 92}; 93 94struct lsinfo { /* leap second information */ 95 time_t ls_trans; /* transition time */ 96 long ls_corr; /* correction to apply */ 97}; 98 99#define BIGGEST(a, b) (((a) > (b)) ? (a) : (b)) 100 101#ifdef TZNAME_MAX 102#define MY_TZNAME_MAX TZNAME_MAX 103#endif /* defined TZNAME_MAX */ 104#ifndef TZNAME_MAX 105#define MY_TZNAME_MAX 255 106#endif /* !defined TZNAME_MAX */ 107 108struct state { 109 int leapcnt; 110 int timecnt; 111 int typecnt; 112 int charcnt; 113 int goback; 114 int goahead; 115 time_t ats[TZ_MAX_TIMES]; 116 unsigned char types[TZ_MAX_TIMES]; 117 struct ttinfo ttis[TZ_MAX_TYPES]; 118 char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt), 119 (2 * (MY_TZNAME_MAX + 1)))]; 120 struct lsinfo lsis[TZ_MAX_LEAPS]; 121}; 122 123struct rule { 124 int r_type; /* type of rule--see below */ 125 int r_day; /* day number of rule */ 126 int r_week; /* week number of rule */ 127 int r_mon; /* month number of rule */ 128 long r_time; /* transition time of rule */ 129}; 130 131#define JULIAN_DAY 0 /* Jn - Julian day */ 132#define DAY_OF_YEAR 1 /* n - day of year */ 133#define MONTH_NTH_DAY_OF_WEEK 2 /* Mm.n.d - month, week, day of week */ 134 135/* 136** Prototypes for static functions. 137*/ 138 139static long detzcode P((const char * codep)); 140static time_t detzcode64 P((const char * codep)); 141static int differ_by_repeat P((time_t t1, time_t t0)); 142static const char * getzname P((const char * strp)); 143static const char * getqzname P((const char * strp, const int delim)); 144static const char * getnum P((const char * strp, int * nump, int min, 145 int max)); 146static const char * getsecs P((const char * strp, long * secsp)); 147static const char * getoffset P((const char * strp, long * offsetp)); 148static const char * getrule P((const char * strp, struct rule * rulep)); 149static void gmtload P((struct state * sp)); 150static struct tm * gmtsub P((const time_t * timep, long offset, 151 struct tm * tmp)); 152static struct tm * localsub P((const time_t * timep, long offset, 153 struct tm * tmp)); 154static int increment_overflow P((int * number, int delta)); 155static int leaps_thru_end_of P((int y)); 156static int long_increment_overflow P((long * number, int delta)); 157static int long_normalize_overflow P((long * tensptr, 158 int * unitsptr, int base)); 159static int normalize_overflow P((int * tensptr, int * unitsptr, 160 int base)); 161static void settzname P((void)); 162static time_t time1 P((struct tm * tmp, 163 struct tm * (*funcp) P((const time_t *, 164 long, struct tm *)), 165 long offset)); 166static time_t time2 P((struct tm *tmp, 167 struct tm * (*funcp) P((const time_t *, 168 long, struct tm*)), 169 long offset, int * okayp)); 170static time_t time2sub P((struct tm *tmp, 171 struct tm * (*funcp) P((const time_t *, 172 long, struct tm*)), 173 long offset, int * okayp, int do_norm_secs)); 174static struct tm * timesub P((const time_t * timep, long offset, 175 const struct state * sp, struct tm * tmp)); 176static int tmcomp P((const struct tm * atmp, 177 const struct tm * btmp)); 178static time_t transtime P((time_t janfirst, int year, 179 const struct rule * rulep, long offset)); 180static int tzload P((const char * name, struct state * sp, 181 int doextend)); 182static int tzparse P((const char * name, struct state * sp, 183 int lastditch)); 184 185#ifdef ALL_STATE 186static struct state * lclptr; 187static struct state * gmtptr; 188#endif /* defined ALL_STATE */ 189 190#ifndef ALL_STATE 191static struct state lclmem; 192static struct state gmtmem; 193#define lclptr (&lclmem) 194#define gmtptr (&gmtmem) 195#endif /* State Farm */ 196 197#ifndef TZ_STRLEN_MAX 198#define TZ_STRLEN_MAX 255 199#endif /* !defined TZ_STRLEN_MAX */ 200 201static char lcl_TZname[TZ_STRLEN_MAX + 1]; 202static int lcl_is_set; 203static int gmt_is_set; 204 205#if 0 206char * tzname[2] = { 207 wildabbr, 208 wildabbr 209}; 210#endif 211 212/* 213** Section 4.12.3 of X3.159-1989 requires that 214** Except for the strftime function, these functions [asctime, 215** ctime, gmtime, localtime] return values in one of two static 216** objects: a broken-down time structure and an array of char. 217** Thanks to Paul Eggert for noting this. 218*/ 219 220static struct tm tm; 221 222#if 0 223#ifdef USG_COMPAT 224time_t timezone = 0; 225int daylight = 0; 226#endif /* defined USG_COMPAT */ 227#endif 228 229#ifdef ALTZONE 230time_t altzone = 0; 231#endif /* defined ALTZONE */ 232 233#ifdef __HAIKU__ 234# include <FindDirectory.h> 235 236static const char* 237get_timezones_directory(void) 238{ 239 static char path[PATH_MAX]; 240 if (path[0] != '\0') 241 return path; 242 243 if (find_directory(B_SYSTEM_DATA_DIRECTORY, -1, false, path, sizeof(path)) 244 == B_OK) { 245 strlcat(path, "/timezones", sizeof(path)); 246 } else 247 strcpy(path, "/boot/system/data/timezones"); 248 249 return path; 250} 251#endif 252 253static long 254detzcode(codep) 255const char * const codep; 256{ 257 register long result; 258 register int i; 259 260 result = (codep[0] & 0x80) ? ~0L : 0; 261 for (i = 0; i < 4; ++i) 262 result = (result << 8) | (codep[i] & 0xff); 263 return result; 264} 265 266static time_t 267detzcode64(codep) 268const char * const codep; 269{ 270 register time_t result; 271 register int i; 272 273 result = (codep[0] & 0x80) ? (~(int_fast64_t) 0) : 0; 274 for (i = 0; i < 8; ++i) 275 result = result * 256 + (codep[i] & 0xff); 276 return result; 277} 278 279static void 280settzname P((void)) 281{ 282 register struct state * const sp = lclptr; 283 register int i; 284 285 tzname[0] = wildabbr; 286 tzname[1] = wildabbr; 287#ifdef USG_COMPAT 288 daylight = 0; 289 timezone = 0; 290#endif /* defined USG_COMPAT */ 291#ifdef ALTZONE 292 altzone = 0; 293#endif /* defined ALTZONE */ 294#ifdef ALL_STATE 295 if (sp == NULL) { 296 tzname[0] = tzname[1] = gmt; 297 return; 298 } 299#endif /* defined ALL_STATE */ 300 for (i = 0; i < sp->typecnt; ++i) { 301 register const struct ttinfo * const ttisp = &sp->ttis[i]; 302 303 tzname[ttisp->tt_isdst] = 304 &sp->chars[ttisp->tt_abbrind]; 305#ifdef USG_COMPAT 306 if (ttisp->tt_isdst) 307 daylight = 1; 308 if (i == 0 || !ttisp->tt_isdst) 309 timezone = -(ttisp->tt_gmtoff); 310#endif /* defined USG_COMPAT */ 311#ifdef ALTZONE 312 if (i == 0 || ttisp->tt_isdst) 313 altzone = -(ttisp->tt_gmtoff); 314#endif /* defined ALTZONE */ 315 } 316 /* 317 ** And to get the latest zone names into tzname. . . 318 */ 319 for (i = 0; i < sp->timecnt; ++i) { 320 register const struct ttinfo * const ttisp = 321 &sp->ttis[ 322 sp->types[i]]; 323 324 tzname[ttisp->tt_isdst] = 325 &sp->chars[ttisp->tt_abbrind]; 326 } 327 /* 328 ** Finally, scrub the abbreviations. 329 ** First, replace bogus characters. 330 */ 331 for (i = 0; i < sp->charcnt; ++i) 332 if (strchr(TZ_ABBR_CHAR_SET, sp->chars[i]) == NULL) 333 sp->chars[i] = TZ_ABBR_ERR_CHAR; 334 /* 335 ** Second, truncate long abbreviations. 336 */ 337 for (i = 0; i < sp->typecnt; ++i) { 338 register const struct ttinfo * const ttisp = &sp->ttis[i]; 339 register char * cp = &sp->chars[ttisp->tt_abbrind]; 340 341 if (strlen(cp) > TZ_ABBR_MAX_LEN && 342 strcmp(cp, GRANDPARENTED) != 0) 343 *(cp + TZ_ABBR_MAX_LEN) = '\0'; 344 } 345} 346 347static int 348differ_by_repeat(t1, t0) 349const time_t t1; 350const time_t t0; 351{ 352 if (TYPE_INTEGRAL(time_t) && 353 TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS) 354 return 0; 355 return t1 - t0 == SECSPERREPEAT; 356} 357 358static int 359tzload(name, sp, doextend) 360register const char * name; 361register struct state * const sp; 362register const int doextend; 363{ 364 register const char * p; 365 register int i; 366 register int fid; 367 register int stored; 368 register int nread; 369 union { 370 struct tzhead tzhead; 371 char buf[2 * sizeof(struct tzhead) + 372 2 * sizeof *sp + 373 4 * TZ_MAX_TIMES]; 374 } u; 375 376 if (name == NULL && (name = TZDEFAULT) == NULL) 377 return -1; 378 { 379 register int doaccess; 380 /* 381 ** Section 4.9.1 of the C standard says that 382 ** "FILENAME_MAX expands to an integral constant expression 383 ** that is the size needed for an array of char large enough 384 ** to hold the longest file name string that the implementation 385 ** guarantees can be opened." 386 */ 387 char fullname[FILENAME_MAX + 1]; 388 389 if (name[0] == ':') 390 ++name; 391 doaccess = name[0] == '/'; 392 if (!doaccess) { 393 if ((p = TZDIR) == NULL) 394 return -1; 395 if ((strlen(p) + strlen(name) + 1) >= sizeof fullname) 396 return -1; 397 (void) strcpy(fullname, p); 398 (void) strcat(fullname, "/"); 399 (void) strcat(fullname, name); 400 /* 401 ** Set doaccess if '.' (as in "../") shows up in name. 402 */ 403 if (strchr(name, '.') != NULL) 404 doaccess = TRUE; 405 name = fullname; 406 } 407 if (doaccess && access(name, R_OK) != 0) 408 return -1; 409 if ((fid = open(name, OPEN_MODE)) == -1) 410 return -1; 411 } 412 nread = read(fid, u.buf, sizeof u.buf); 413 if (close(fid) < 0 || nread <= 0) 414 return -1; 415 for (stored = 4; stored <= 8; stored *= 2) { 416 int ttisstdcnt; 417 int ttisgmtcnt; 418 419 ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt); 420 ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt); 421 sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt); 422 sp->timecnt = (int) detzcode(u.tzhead.tzh_timecnt); 423 sp->typecnt = (int) detzcode(u.tzhead.tzh_typecnt); 424 sp->charcnt = (int) detzcode(u.tzhead.tzh_charcnt); 425 p = u.tzhead.tzh_charcnt + sizeof u.tzhead.tzh_charcnt; 426 if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS || 427 sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES || 428 sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES || 429 sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS || 430 (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) || 431 (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0)) 432 return -1; 433 if (nread - (p - u.buf) < 434 sp->timecnt * stored + /* ats */ 435 sp->timecnt + /* types */ 436 sp->typecnt * 6 + /* ttinfos */ 437 sp->charcnt + /* chars */ 438 sp->leapcnt * (stored + 4) + /* lsinfos */ 439 ttisstdcnt + /* ttisstds */ 440 ttisgmtcnt) /* ttisgmts */ 441 return -1; 442 for (i = 0; i < sp->timecnt; ++i) { 443 sp->ats[i] = (stored == 4) ? 444 detzcode(p) : detzcode64(p); 445 p += stored; 446 } 447 for (i = 0; i < sp->timecnt; ++i) { 448 sp->types[i] = (unsigned char) *p++; 449 if (sp->types[i] >= sp->typecnt) 450 return -1; 451 } 452 for (i = 0; i < sp->typecnt; ++i) { 453 register struct ttinfo * ttisp; 454 455 ttisp = &sp->ttis[i]; 456 ttisp->tt_gmtoff = detzcode(p); 457 p += 4; 458 ttisp->tt_isdst = (unsigned char) *p++; 459 if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1) 460 return -1; 461 ttisp->tt_abbrind = (unsigned char) *p++; 462 if (ttisp->tt_abbrind < 0 || 463 ttisp->tt_abbrind > sp->charcnt) 464 return -1; 465 } 466 for (i = 0; i < sp->charcnt; ++i) 467 sp->chars[i] = *p++; 468 sp->chars[i] = '\0'; /* ensure '\0' at end */ 469 for (i = 0; i < sp->leapcnt; ++i) { 470 register struct lsinfo * lsisp; 471 472 lsisp = &sp->lsis[i]; 473 lsisp->ls_trans = (stored == 4) ? 474 detzcode(p) : detzcode64(p); 475 p += stored; 476 lsisp->ls_corr = detzcode(p); 477 p += 4; 478 } 479 for (i = 0; i < sp->typecnt; ++i) { 480 register struct ttinfo * ttisp; 481 482 ttisp = &sp->ttis[i]; 483 if (ttisstdcnt == 0) 484 ttisp->tt_ttisstd = FALSE; 485 else { 486 ttisp->tt_ttisstd = *p++; 487 if (ttisp->tt_ttisstd != TRUE && 488 ttisp->tt_ttisstd != FALSE) 489 return -1; 490 } 491 } 492 for (i = 0; i < sp->typecnt; ++i) { 493 register struct ttinfo * ttisp; 494 495 ttisp = &sp->ttis[i]; 496 if (ttisgmtcnt == 0) 497 ttisp->tt_ttisgmt = FALSE; 498 else { 499 ttisp->tt_ttisgmt = *p++; 500 if (ttisp->tt_ttisgmt != TRUE && 501 ttisp->tt_ttisgmt != FALSE) 502 return -1; 503 } 504 } 505 /* 506 ** Out-of-sort ats should mean we're running on a 507 ** signed time_t system but using a data file with 508 ** unsigned values (or vice versa). 509 */ 510 for (i = 0; i < sp->timecnt - 2; ++i) 511 if (sp->ats[i] > sp->ats[i + 1]) { 512 ++i; 513 if (TYPE_SIGNED(time_t)) { 514 /* 515 ** Ignore the end (easy). 516 */ 517 sp->timecnt = i; 518 } else { 519 /* 520 ** Ignore the beginning (harder). 521 */ 522 register int j; 523 524 for (j = 0; j + i < sp->timecnt; ++j) { 525 sp->ats[j] = sp->ats[j + i]; 526 sp->types[j] = sp->types[j + i]; 527 } 528 sp->timecnt = j; 529 } 530 break; 531 } 532 /* 533 ** If this is an old file, we're done. 534 */ 535 if (u.tzhead.tzh_version[0] == '\0') 536 break; 537 nread -= p - u.buf; 538 for (i = 0; i < nread; ++i) 539 u.buf[i] = p[i]; 540 /* 541 ** If this is a narrow integer time_t system, we're done. 542 */ 543 if (stored >= (int) sizeof(time_t) && TYPE_INTEGRAL(time_t)) 544 break; 545 } 546 if (doextend && nread > 2 && 547 u.buf[0] == '\n' && u.buf[nread - 1] == '\n' && 548 sp->typecnt + 2 <= TZ_MAX_TYPES) { 549 struct state ts; 550 register int result; 551 552 u.buf[nread - 1] = '\0'; 553 result = tzparse(&u.buf[1], &ts, FALSE); 554 if (result == 0 && ts.typecnt == 2 && 555 sp->charcnt + ts.charcnt <= TZ_MAX_CHARS) { 556 for (i = 0; i < 2; ++i) 557 ts.ttis[i].tt_abbrind += 558 sp->charcnt; 559 for (i = 0; i < ts.charcnt; ++i) 560 sp->chars[sp->charcnt++] = 561 ts.chars[i]; 562 i = 0; 563 while (i < ts.timecnt && 564 ts.ats[i] <= 565 sp->ats[sp->timecnt - 1]) 566 ++i; 567 while (i < ts.timecnt && 568 sp->timecnt < TZ_MAX_TIMES) { 569 sp->ats[sp->timecnt] = 570 ts.ats[i]; 571 sp->types[sp->timecnt] = 572 sp->typecnt + 573 ts.types[i]; 574 ++sp->timecnt; 575 ++i; 576 } 577 sp->ttis[sp->typecnt++] = ts.ttis[0]; 578 sp->ttis[sp->typecnt++] = ts.ttis[1]; 579 } 580 } 581 i = 2 * YEARSPERREPEAT; 582 sp->goback = sp->goahead = sp->timecnt > i; 583 sp->goback = sp->goback && sp->types[i] == sp->types[0] && 584 differ_by_repeat(sp->ats[i], sp->ats[0]); 585 sp->goahead = sp->goahead && 586 sp->types[sp->timecnt - 1] == sp->types[sp->timecnt - 1 - i] && 587 differ_by_repeat(sp->ats[sp->timecnt - 1], 588 sp->ats[sp->timecnt - 1 - i]); 589 return 0; 590} 591 592static const int mon_lengths[2][MONSPERYEAR] = { 593 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, 594 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } 595}; 596 597static const int year_lengths[2] = { 598 DAYSPERNYEAR, DAYSPERLYEAR 599}; 600 601/* 602** Given a pointer into a time zone string, scan until a character that is not 603** a valid character in a zone name is found. Return a pointer to that 604** character. 605*/ 606 607static const char * 608getzname(strp) 609register const char * strp; 610{ 611 register char c; 612 613 while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' && 614 c != '+') 615 ++strp; 616 return strp; 617} 618 619/* 620** Given a pointer into an extended time zone string, scan until the ending 621** delimiter of the zone name is located. Return a pointer to the delimiter. 622** 623** As with getzname above, the legal character set is actually quite 624** restricted, with other characters producing undefined results. 625** We don't do any checking here; checking is done later in common-case code. 626*/ 627 628static const char * 629getqzname(register const char *strp, const int delim) 630{ 631 register int c; 632 633 while ((c = *strp) != '\0' && c != delim) 634 ++strp; 635 return strp; 636} 637 638/* 639** Given a pointer into a time zone string, extract a number from that string. 640** Check that the number is within a specified range; if it is not, return 641** NULL. 642** Otherwise, return a pointer to the first character not part of the number. 643*/ 644 645static const char * 646getnum(strp, nump, min, max) 647register const char * strp; 648int * const nump; 649const int min; 650const int max; 651{ 652 register char c; 653 register int num; 654 655 if (strp == NULL || !is_digit(c = *strp)) 656 return NULL; 657 num = 0; 658 do { 659 num = num * 10 + (c - '0'); 660 if (num > max) 661 return NULL; /* illegal value */ 662 c = *++strp; 663 } while (is_digit(c)); 664 if (num < min) 665 return NULL; /* illegal value */ 666 *nump = num; 667 return strp; 668} 669 670/* 671** Given a pointer into a time zone string, extract a number of seconds, 672** in hh[:mm[:ss]] form, from the string. 673** If any error occurs, return NULL. 674** Otherwise, return a pointer to the first character not part of the number 675** of seconds. 676*/ 677 678static const char * 679getsecs(strp, secsp) 680register const char * strp; 681long * const secsp; 682{ 683 int num; 684 685 /* 686 ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like 687 ** "M10.4.6/26", which does not conform to Posix, 688 ** but which specifies the equivalent of 689 ** ``02:00 on the first Sunday on or after 23 Oct''. 690 */ 691 strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1); 692 if (strp == NULL) 693 return NULL; 694 *secsp = num * (long) SECSPERHOUR; 695 if (*strp == ':') { 696 ++strp; 697 strp = getnum(strp, &num, 0, MINSPERHOUR - 1); 698 if (strp == NULL) 699 return NULL; 700 *secsp += num * SECSPERMIN; 701 if (*strp == ':') { 702 ++strp; 703 /* `SECSPERMIN' allows for leap seconds. */ 704 strp = getnum(strp, &num, 0, SECSPERMIN); 705 if (strp == NULL) 706 return NULL; 707 *secsp += num; 708 } 709 } 710 return strp; 711} 712 713/* 714** Given a pointer into a time zone string, extract an offset, in 715** [+-]hh[:mm[:ss]] form, from the string. 716** If any error occurs, return NULL. 717** Otherwise, return a pointer to the first character not part of the time. 718*/ 719 720static const char * 721getoffset(strp, offsetp) 722register const char * strp; 723long * const offsetp; 724{ 725 register int neg = 0; 726 727 if (*strp == '-') { 728 neg = 1; 729 ++strp; 730 } else if (*strp == '+') 731 ++strp; 732 strp = getsecs(strp, offsetp); 733 if (strp == NULL) 734 return NULL; /* illegal time */ 735 if (neg) 736 *offsetp = -*offsetp; 737 return strp; 738} 739 740/* 741** Given a pointer into a time zone string, extract a rule in the form 742** date[/time]. See POSIX section 8 for the format of "date" and "time". 743** If a valid rule is not found, return NULL. 744** Otherwise, return a pointer to the first character not part of the rule. 745*/ 746 747static const char * 748getrule(strp, rulep) 749const char * strp; 750register struct rule * const rulep; 751{ 752 if (*strp == 'J') { 753 /* 754 ** Julian day. 755 */ 756 rulep->r_type = JULIAN_DAY; 757 ++strp; 758 strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR); 759 } else if (*strp == 'M') { 760 /* 761 ** Month, week, day. 762 */ 763 rulep->r_type = MONTH_NTH_DAY_OF_WEEK; 764 ++strp; 765 strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR); 766 if (strp == NULL) 767 return NULL; 768 if (*strp++ != '.') 769 return NULL; 770 strp = getnum(strp, &rulep->r_week, 1, 5); 771 if (strp == NULL) 772 return NULL; 773 if (*strp++ != '.') 774 return NULL; 775 strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1); 776 } else if (is_digit(*strp)) { 777 /* 778 ** Day of year. 779 */ 780 rulep->r_type = DAY_OF_YEAR; 781 strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1); 782 } else return NULL; /* invalid format */ 783 if (strp == NULL) 784 return NULL; 785 if (*strp == '/') { 786 /* 787 ** Time specified. 788 */ 789 ++strp; 790 strp = getsecs(strp, &rulep->r_time); 791 } else rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */ 792 return strp; 793} 794 795/* 796** Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the 797** year, a rule, and the offset from UTC at the time that rule takes effect, 798** calculate the Epoch-relative time that rule takes effect. 799*/ 800 801static time_t 802transtime(janfirst, year, rulep, offset) 803const time_t janfirst; 804const int year; 805register const struct rule * const rulep; 806const long offset; 807{ 808 register int leapyear; 809 register time_t value; 810 register int i; 811 int d, m1, yy0, yy1, yy2, dow; 812 813 INITIALIZE(value); 814 leapyear = isleap(year); 815 switch (rulep->r_type) { 816 817 case JULIAN_DAY: 818 /* 819 ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap 820 ** years. 821 ** In non-leap years, or if the day number is 59 or less, just 822 ** add SECSPERDAY times the day number-1 to the time of 823 ** January 1, midnight, to get the day. 824 */ 825 value = janfirst + (rulep->r_day - 1) * SECSPERDAY; 826 if (leapyear && rulep->r_day >= 60) 827 value += SECSPERDAY; 828 break; 829 830 case DAY_OF_YEAR: 831 /* 832 ** n - day of year. 833 ** Just add SECSPERDAY times the day number to the time of 834 ** January 1, midnight, to get the day. 835 */ 836 value = janfirst + rulep->r_day * SECSPERDAY; 837 break; 838 839 case MONTH_NTH_DAY_OF_WEEK: 840 /* 841 ** Mm.n.d - nth "dth day" of month m. 842 */ 843 value = janfirst; 844 for (i = 0; i < rulep->r_mon - 1; ++i) 845 value += mon_lengths[leapyear][i] * SECSPERDAY; 846 847 /* 848 ** Use Zeller's Congruence to get day-of-week of first day of 849 ** month. 850 */ 851 m1 = (rulep->r_mon + 9) % 12 + 1; 852 yy0 = (rulep->r_mon <= 2) ? (year - 1) : year; 853 yy1 = yy0 / 100; 854 yy2 = yy0 % 100; 855 dow = ((26 * m1 - 2) / 10 + 856 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7; 857 if (dow < 0) 858 dow += DAYSPERWEEK; 859 860 /* 861 ** "dow" is the day-of-week of the first day of the month. Get 862 ** the day-of-month (zero-origin) of the first "dow" day of the 863 ** month. 864 */ 865 d = rulep->r_day - dow; 866 if (d < 0) 867 d += DAYSPERWEEK; 868 for (i = 1; i < rulep->r_week; ++i) { 869 if (d + DAYSPERWEEK >= 870 mon_lengths[leapyear][rulep->r_mon - 1]) 871 break; 872 d += DAYSPERWEEK; 873 } 874 875 /* 876 ** "d" is the day-of-month (zero-origin) of the day we want. 877 */ 878 value += d * SECSPERDAY; 879 break; 880 } 881 882 /* 883 ** "value" is the Epoch-relative time of 00:00:00 UTC on the day in 884 ** question. To get the Epoch-relative time of the specified local 885 ** time on that day, add the transition time and the current offset 886 ** from UTC. 887 */ 888 return value + rulep->r_time + offset; 889} 890 891/* 892** Given a POSIX section 8-style TZ string, fill in the rule tables as 893** appropriate. 894*/ 895 896static int 897tzparse(name, sp, lastditch) 898const char * name; 899register struct state * const sp; 900const int lastditch; 901{ 902 const char * stdname; 903 const char * dstname; 904 size_t stdlen; 905 size_t dstlen; 906 long stdoffset; 907 long dstoffset; 908 register time_t * atp; 909 register unsigned char * typep; 910 register char * cp; 911 register int load_result; 912 913 INITIALIZE(dstname); 914 stdname = name; 915 if (lastditch) { 916 stdlen = strlen(name); /* length of standard zone name */ 917 name += stdlen; 918 if (stdlen >= sizeof sp->chars) 919 stdlen = (sizeof sp->chars) - 1; 920 stdoffset = 0; 921 } else { 922 if (*name == '<') { 923 name++; 924 stdname = name; 925 name = getqzname(name, '>'); 926 if (*name != '>') 927 return (-1); 928 stdlen = name - stdname; 929 name++; 930 } else { 931 name = getzname(name); 932 stdlen = name - stdname; 933 } 934 if (*name == '\0') 935 return -1; 936 name = getoffset(name, &stdoffset); 937 if (name == NULL) 938 return -1; 939 } 940 load_result = tzload(TZDEFRULES, sp, FALSE); 941 if (load_result != 0) 942 sp->leapcnt = 0; /* so, we're off a little */ 943 if (*name != '\0') { 944 if (*name == '<') { 945 dstname = ++name; 946 name = getqzname(name, '>'); 947 if (*name != '>') 948 return -1; 949 dstlen = name - dstname; 950 name++; 951 } else { 952 dstname = name; 953 name = getzname(name); 954 dstlen = name - dstname; /* length of DST zone name */ 955 } 956 if (*name != '\0' && *name != ',' && *name != ';') { 957 name = getoffset(name, &dstoffset); 958 if (name == NULL) 959 return -1; 960 } else dstoffset = stdoffset - SECSPERHOUR; 961 if (*name == '\0' && load_result != 0) 962 name = TZDEFRULESTRING; 963 if (*name == ',' || *name == ';') { 964 struct rule start; 965 struct rule end; 966 register int year; 967 register time_t janfirst; 968 time_t starttime; 969 time_t endtime; 970 971 ++name; 972 if ((name = getrule(name, &start)) == NULL) 973 return -1; 974 if (*name++ != ',') 975 return -1; 976 if ((name = getrule(name, &end)) == NULL) 977 return -1; 978 if (*name != '\0') 979 return -1; 980 sp->typecnt = 2; /* standard time and DST */ 981 /* 982 ** Two transitions per year, from EPOCH_YEAR forward. 983 */ 984 sp->ttis[0].tt_gmtoff = -dstoffset; 985 sp->ttis[0].tt_isdst = 1; 986 sp->ttis[0].tt_abbrind = stdlen + 1; 987 sp->ttis[1].tt_gmtoff = -stdoffset; 988 sp->ttis[1].tt_isdst = 0; 989 sp->ttis[1].tt_abbrind = 0; 990 atp = sp->ats; 991 typep = sp->types; 992 janfirst = 0; 993 sp->timecnt = 0; 994 for (year = EPOCH_YEAR; 995 sp->timecnt + 2 <= TZ_MAX_TIMES; 996 ++year) { 997 time_t newfirst; 998 999 starttime = transtime(janfirst, year, &start, 1000 stdoffset); 1001 endtime = transtime(janfirst, year, &end, 1002 dstoffset); 1003 if (starttime > endtime) { 1004 *atp++ = endtime; 1005 *typep++ = 1; /* DST ends */ 1006 *atp++ = starttime; 1007 *typep++ = 0; /* DST begins */ 1008 } else { 1009 *atp++ = starttime; 1010 *typep++ = 0; /* DST begins */ 1011 *atp++ = endtime; 1012 *typep++ = 1; /* DST ends */ 1013 } 1014 sp->timecnt += 2; 1015 newfirst = janfirst; 1016 newfirst += year_lengths[isleap(year)] * 1017 SECSPERDAY; 1018 if (newfirst <= janfirst) 1019 break; 1020 janfirst = newfirst; 1021 } 1022 } else { 1023 register long theirstdoffset; 1024 register long theirdstoffset; 1025 register long theiroffset; 1026 register int isdst; 1027 register int i; 1028 register int j; 1029 1030 if (*name != '\0') 1031 return -1; 1032 /* 1033 ** Initial values of theirstdoffset and theirdstoffset. 1034 */ 1035 theirstdoffset = 0; 1036 for (i = 0; i < sp->timecnt; ++i) { 1037 j = sp->types[i]; 1038 if (!sp->ttis[j].tt_isdst) { 1039 theirstdoffset = 1040 -sp->ttis[j].tt_gmtoff; 1041 break; 1042 } 1043 } 1044 theirdstoffset = 0; 1045 for (i = 0; i < sp->timecnt; ++i) { 1046 j = sp->types[i]; 1047 if (sp->ttis[j].tt_isdst) { 1048 theirdstoffset = 1049 -sp->ttis[j].tt_gmtoff; 1050 break; 1051 } 1052 } 1053 /* 1054 ** Initially we're assumed to be in standard time. 1055 */ 1056 isdst = FALSE; 1057 theiroffset = theirstdoffset; 1058 /* 1059 ** Now juggle transition times and types 1060 ** tracking offsets as you do. 1061 */ 1062 for (i = 0; i < sp->timecnt; ++i) { 1063 j = sp->types[i]; 1064 sp->types[i] = sp->ttis[j].tt_isdst; 1065 if (sp->ttis[j].tt_ttisgmt) { 1066 /* No adjustment to transition time */ 1067 } else { 1068 /* 1069 ** If summer time is in effect, and the 1070 ** transition time was not specified as 1071 ** standard time, add the summer time 1072 ** offset to the transition time; 1073 ** otherwise, add the standard time 1074 ** offset to the transition time. 1075 */ 1076 /* 1077 ** Transitions from DST to DDST 1078 ** will effectively disappear since 1079 ** POSIX provides for only one DST 1080 ** offset. 1081 */ 1082 if (isdst && !sp->ttis[j].tt_ttisstd) { 1083 sp->ats[i] += dstoffset - 1084 theirdstoffset; 1085 } else { 1086 sp->ats[i] += stdoffset - 1087 theirstdoffset; 1088 } 1089 } 1090 theiroffset = -sp->ttis[j].tt_gmtoff; 1091 if (sp->ttis[j].tt_isdst) 1092 theirdstoffset = theiroffset; 1093 else theirstdoffset = theiroffset; 1094 } 1095 /* 1096 ** Finally, fill in ttis. 1097 ** ttisstd and ttisgmt need not be handled. 1098 */ 1099 sp->ttis[0].tt_gmtoff = -stdoffset; 1100 sp->ttis[0].tt_isdst = FALSE; 1101 sp->ttis[0].tt_abbrind = 0; 1102 sp->ttis[1].tt_gmtoff = -dstoffset; 1103 sp->ttis[1].tt_isdst = TRUE; 1104 sp->ttis[1].tt_abbrind = stdlen + 1; 1105 sp->typecnt = 2; 1106 } 1107 } else { 1108 dstlen = 0; 1109 sp->typecnt = 1; /* only standard time */ 1110 sp->timecnt = 0; 1111 sp->ttis[0].tt_gmtoff = -stdoffset; 1112 sp->ttis[0].tt_isdst = 0; 1113 sp->ttis[0].tt_abbrind = 0; 1114 } 1115 sp->charcnt = stdlen + 1; 1116 if (dstlen != 0) 1117 sp->charcnt += dstlen + 1; 1118 if ((size_t) sp->charcnt > sizeof sp->chars) 1119 return -1; 1120 cp = sp->chars; 1121 (void) strncpy(cp, stdname, stdlen); 1122 cp += stdlen; 1123 *cp++ = '\0'; 1124 if (dstlen != 0) { 1125 (void) strncpy(cp, dstname, dstlen); 1126 *(cp + dstlen) = '\0'; 1127 } 1128 return 0; 1129} 1130 1131static void 1132gmtload(sp) 1133struct state * const sp; 1134{ 1135 if (tzload(gmt, sp, TRUE) != 0) 1136 (void) tzparse(gmt, sp, TRUE); 1137} 1138 1139#ifndef STD_INSPIRED 1140/* 1141** A non-static declaration of tzsetwall in a system header file 1142** may cause a warning about this upcoming static declaration... 1143*/ 1144static 1145#endif /* !defined STD_INSPIRED */ 1146void 1147tzsetwall P((void)) 1148{ 1149 if (lcl_is_set < 0) 1150 return; 1151 lcl_is_set = -1; 1152 1153#ifdef ALL_STATE 1154 if (lclptr == NULL) { 1155 lclptr = (struct state *) malloc(sizeof *lclptr); 1156 if (lclptr == NULL) { 1157 settzname(); /* all we can do */ 1158 return; 1159 } 1160 } 1161#endif /* defined ALL_STATE */ 1162 if (tzload((char *) NULL, lclptr, TRUE) != 0) 1163 gmtload(lclptr); 1164 settzname(); 1165} 1166 1167 1168#include <StorageDefs.h> 1169#include <syscalls.h> 1170 1171#if 0 1172void 1173tzset P((void)) 1174{ 1175 register const char * name; 1176 char tzfilename[B_PATH_NAME_LENGTH]; 1177 bool is_gmt; 1178 1179 name = getenv("TZ"); 1180 if (name == NULL) { 1181// _kern_get_tzfilename(tzfilename, sizeof(tzfilename), &is_gmt); 1182 if (tzfilename[0] == '\0') { 1183 tzsetwall(); 1184 return; 1185 } 1186 name = tzfilename; 1187 } 1188 1189 if (lcl_is_set > 0 && strcmp(lcl_TZname, name) == 0) 1190 return; 1191 lcl_is_set = strlen(name) < sizeof lcl_TZname; 1192 if (lcl_is_set) 1193 (void) strcpy(lcl_TZname, name); 1194 1195#ifdef ALL_STATE 1196 if (lclptr == NULL) { 1197 lclptr = (struct state *) malloc(sizeof *lclptr); 1198 if (lclptr == NULL) { 1199 settzname(); /* all we can do */ 1200 return; 1201 } 1202 } 1203#endif /* defined ALL_STATE */ 1204 if (*name == '\0') { 1205 /* 1206 ** User wants it fast rather than right. 1207 */ 1208 lclptr->leapcnt = 0; /* so, we're off a little */ 1209 lclptr->timecnt = 0; 1210 lclptr->typecnt = 0; 1211 lclptr->ttis[0].tt_isdst = 0; 1212 lclptr->ttis[0].tt_gmtoff = 0; 1213 lclptr->ttis[0].tt_abbrind = 0; 1214 (void) strcpy(lclptr->chars, gmt); 1215 } else if (tzload(name, lclptr, TRUE) != 0) 1216 if (name[0] == ':' || tzparse(name, lclptr, FALSE) != 0) 1217 (void) gmtload(lclptr); 1218 settzname(); 1219} 1220#endif 1221 1222/* 1223** The easy way to behave "as if no library function calls" localtime 1224** is to not call it--so we drop its guts into "localsub", which can be 1225** freely called. (And no, the PANS doesn't require the above behavior-- 1226** but it *is* desirable.) 1227** 1228** The unused offset argument is for the benefit of mktime variants. 1229*/ 1230 1231/*ARGSUSED*/ 1232static struct tm * 1233localsub(timep, offset, tmp) 1234const time_t * const timep; 1235const long offset; 1236struct tm * const tmp; 1237{ 1238 register struct state * sp; 1239 register const struct ttinfo * ttisp; 1240 register int i; 1241 register struct tm * result; 1242 const time_t t = *timep; 1243 1244 sp = lclptr; 1245#ifdef ALL_STATE 1246 if (sp == NULL) 1247 return gmtsub(timep, offset, tmp); 1248#endif /* defined ALL_STATE */ 1249 if ((sp->goback && t < sp->ats[0]) || 1250 (sp->goahead && t > sp->ats[sp->timecnt - 1])) { 1251 time_t newt = t; 1252 register time_t seconds; 1253 register time_t tcycles; 1254 register int_fast64_t icycles; 1255 1256 if (t < sp->ats[0]) 1257 seconds = sp->ats[0] - t; 1258 else seconds = t - sp->ats[sp->timecnt - 1]; 1259 --seconds; 1260 tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR; 1261 ++tcycles; 1262 icycles = tcycles; 1263 if (tcycles - icycles >= 1 || icycles - tcycles >= 1) 1264 return NULL; 1265 seconds = icycles; 1266 seconds *= YEARSPERREPEAT; 1267 seconds *= AVGSECSPERYEAR; 1268 if (t < sp->ats[0]) 1269 newt += seconds; 1270 else newt -= seconds; 1271 if (newt < sp->ats[0] || 1272 newt > sp->ats[sp->timecnt - 1]) 1273 return NULL; /* "cannot happen" */ 1274 result = localsub(&newt, offset, tmp); 1275 if (result == tmp) { 1276 register time_t newy; 1277 1278 newy = tmp->tm_year; 1279 if (t < sp->ats[0]) 1280 newy -= icycles * YEARSPERREPEAT; 1281 else newy += icycles * YEARSPERREPEAT; 1282 tmp->tm_year = newy; 1283 if (tmp->tm_year != newy) 1284 return NULL; 1285 } 1286 return result; 1287 } 1288 if (sp->timecnt == 0 || t < sp->ats[0]) { 1289 i = 0; 1290 while (sp->ttis[i].tt_isdst) 1291 if (++i >= sp->typecnt) { 1292 i = 0; 1293 break; 1294 } 1295 } else { 1296 register int lo = 1; 1297 register int hi = sp->timecnt; 1298 1299 while (lo < hi) { 1300 register int mid = (lo + hi) >> 1; 1301 1302 if (t < sp->ats[mid]) 1303 hi = mid; 1304 else lo = mid + 1; 1305 } 1306 i = (int) sp->types[lo - 1]; 1307 } 1308 ttisp = &sp->ttis[i]; 1309 /* 1310 ** To get (wrong) behavior that's compatible with System V Release 2.0 1311 ** you'd replace the statement below with 1312 ** t += ttisp->tt_gmtoff; 1313 ** timesub(&t, 0L, sp, tmp); 1314 */ 1315 result = timesub(&t, ttisp->tt_gmtoff, sp, tmp); 1316 tmp->tm_isdst = ttisp->tt_isdst; 1317 tzname[tmp->tm_isdst] = &sp->chars[ttisp->tt_abbrind]; 1318#ifdef TM_ZONE 1319 tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind]; 1320#endif /* defined TM_ZONE */ 1321 return result; 1322} 1323 1324#if 0 1325struct tm * 1326localtime(timep) 1327const time_t * const timep; 1328{ 1329 tzset(); 1330 return localsub(timep, 0L, &tm); 1331} 1332 1333/* 1334** Re-entrant version of localtime. 1335*/ 1336 1337struct tm * 1338localtime_r(timep, tmp) 1339const time_t * const timep; 1340struct tm * tmp; 1341{ 1342 return localsub(timep, 0L, tmp); 1343} 1344#endif 1345 1346/* 1347** gmtsub is to gmtime as localsub is to localtime. 1348*/ 1349 1350static struct tm * 1351gmtsub(timep, offset, tmp) 1352const time_t * const timep; 1353const long offset; 1354struct tm * const tmp; 1355{ 1356 register struct tm * result; 1357 1358 if (!gmt_is_set) { 1359 gmt_is_set = TRUE; 1360#ifdef ALL_STATE 1361 gmtptr = (struct state *) malloc(sizeof *gmtptr); 1362 if (gmtptr != NULL) 1363#endif /* defined ALL_STATE */ 1364 gmtload(gmtptr); 1365 } 1366 result = timesub(timep, offset, gmtptr, tmp); 1367#ifdef TM_ZONE 1368 /* 1369 ** Could get fancy here and deliver something such as 1370 ** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero, 1371 ** but this is no time for a treasure hunt. 1372 */ 1373 if (offset != 0) 1374 tmp->TM_ZONE = wildabbr; 1375 else { 1376#ifdef ALL_STATE 1377 if (gmtptr == NULL) 1378 tmp->TM_ZONE = gmt; 1379 else tmp->TM_ZONE = gmtptr->chars; 1380#endif /* defined ALL_STATE */ 1381#ifndef ALL_STATE 1382 tmp->TM_ZONE = gmtptr->chars; 1383#endif /* State Farm */ 1384 } 1385#endif /* defined TM_ZONE */ 1386 return result; 1387} 1388 1389#if 0 1390struct tm * 1391gmtime(timep) 1392const time_t * const timep; 1393{ 1394 return gmtsub(timep, 0L, &tm); 1395} 1396 1397/* 1398* Re-entrant version of gmtime. 1399*/ 1400 1401struct tm * 1402gmtime_r(timep, tmp) 1403const time_t * const timep; 1404struct tm * tmp; 1405{ 1406 return gmtsub(timep, 0L, tmp); 1407} 1408 1409#endif 1410 1411#ifdef STD_INSPIRED 1412 1413struct tm * 1414offtime(timep, offset) 1415const time_t * const timep; 1416const long offset; 1417{ 1418 return gmtsub(timep, offset, &tm); 1419} 1420 1421#endif /* defined STD_INSPIRED */ 1422 1423/* 1424** Return the number of leap years through the end of the given year 1425** where, to make the math easy, the answer for year zero is defined as zero. 1426*/ 1427 1428static int 1429leaps_thru_end_of(y) 1430register const int y; 1431{ 1432 return (y >= 0) ? (y / 4 - y / 100 + y / 400) : 1433 -(leaps_thru_end_of(-(y + 1)) + 1); 1434} 1435 1436static struct tm * 1437timesub(timep, offset, sp, tmp) 1438const time_t * const timep; 1439const long offset; 1440register const struct state * const sp; 1441register struct tm * const tmp; 1442{ 1443 register const struct lsinfo * lp; 1444 register time_t tdays; 1445 register int idays; /* unsigned would be so 2003 */ 1446 register long rem; 1447 int y; 1448 register const int * ip; 1449 register long corr; 1450 register int hit; 1451 register int i; 1452 1453 corr = 0; 1454 hit = 0; 1455#ifdef ALL_STATE 1456 i = (sp == NULL) ? 0 : sp->leapcnt; 1457#endif /* defined ALL_STATE */ 1458#ifndef ALL_STATE 1459 i = sp->leapcnt; 1460#endif /* State Farm */ 1461 while (--i >= 0) { 1462 lp = &sp->lsis[i]; 1463 if (*timep >= lp->ls_trans) { 1464 if (*timep == lp->ls_trans) { 1465 hit = ((i == 0 && lp->ls_corr > 0) || 1466 lp->ls_corr > sp->lsis[i - 1].ls_corr); 1467 if (hit) 1468 while (i > 0 && 1469 sp->lsis[i].ls_trans == 1470 sp->lsis[i - 1].ls_trans + 1 && 1471 sp->lsis[i].ls_corr == 1472 sp->lsis[i - 1].ls_corr + 1) { 1473 ++hit; 1474 --i; 1475 } 1476 } 1477 corr = lp->ls_corr; 1478 break; 1479 } 1480 } 1481 y = EPOCH_YEAR; 1482 tdays = *timep / SECSPERDAY; 1483 rem = *timep - tdays * SECSPERDAY; 1484 while (tdays < 0 || tdays >= year_lengths[isleap(y)]) { 1485 int newy; 1486 register time_t tdelta; 1487 register int idelta; 1488 register int leapdays; 1489 1490 tdelta = tdays / DAYSPERLYEAR; 1491 idelta = tdelta; 1492 if (tdelta - idelta >= 1 || idelta - tdelta >= 1) 1493 return NULL; 1494 if (idelta == 0) 1495 idelta = (tdays < 0) ? -1 : 1; 1496 newy = y; 1497 if (increment_overflow(&newy, idelta)) 1498 return NULL; 1499 leapdays = leaps_thru_end_of(newy - 1) - 1500 leaps_thru_end_of(y - 1); 1501 tdays -= ((time_t) newy - y) * DAYSPERNYEAR; 1502 tdays -= leapdays; 1503 y = newy; 1504 } 1505 { 1506 register long seconds; 1507 1508 seconds = tdays * SECSPERDAY + 0.5; 1509 tdays = seconds / SECSPERDAY; 1510 rem += seconds - tdays * SECSPERDAY; 1511 } 1512 /* 1513 ** Given the range, we can now fearlessly cast... 1514 */ 1515 idays = tdays; 1516 rem += offset - corr; 1517 while (rem < 0) { 1518 rem += SECSPERDAY; 1519 --idays; 1520 } 1521 while (rem >= SECSPERDAY) { 1522 rem -= SECSPERDAY; 1523 ++idays; 1524 } 1525 while (idays < 0) { 1526 if (increment_overflow(&y, -1)) 1527 return NULL; 1528 idays += year_lengths[isleap(y)]; 1529 } 1530 while (idays >= year_lengths[isleap(y)]) { 1531 idays -= year_lengths[isleap(y)]; 1532 if (increment_overflow(&y, 1)) 1533 return NULL; 1534 } 1535 tmp->tm_year = y; 1536 if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE)) 1537 return NULL; 1538 tmp->tm_yday = idays; 1539 /* 1540 ** The "extra" mods below avoid overflow problems. 1541 */ 1542 tmp->tm_wday = EPOCH_WDAY + 1543 ((y - EPOCH_YEAR) % DAYSPERWEEK) * 1544 (DAYSPERNYEAR % DAYSPERWEEK) + 1545 leaps_thru_end_of(y - 1) - 1546 leaps_thru_end_of(EPOCH_YEAR - 1) + 1547 idays; 1548 tmp->tm_wday %= DAYSPERWEEK; 1549 if (tmp->tm_wday < 0) 1550 tmp->tm_wday += DAYSPERWEEK; 1551 tmp->tm_hour = (int) (rem / SECSPERHOUR); 1552 rem %= SECSPERHOUR; 1553 tmp->tm_min = (int) (rem / SECSPERMIN); 1554 /* 1555 ** A positive leap second requires a special 1556 ** representation. This uses "... ??:59:60" et seq. 1557 */ 1558 tmp->tm_sec = (int) (rem % SECSPERMIN) + hit; 1559 ip = mon_lengths[isleap(y)]; 1560 for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon)) 1561 idays -= ip[tmp->tm_mon]; 1562 tmp->tm_mday = (int) (idays + 1); 1563 tmp->tm_isdst = 0; 1564#ifdef TM_GMTOFF 1565 tmp->TM_GMTOFF = offset; 1566#endif /* defined TM_GMTOFF */ 1567 return tmp; 1568} 1569 1570/* 1571** Adapted from code provided by Robert Elz, who writes: 1572** The "best" way to do mktime I think is based on an idea of Bob 1573** Kridle's (so its said...) from a long time ago. 1574** It does a binary search of the time_t space. Since time_t's are 1575** just 32 bits, its a max of 32 iterations (even at 64 bits it 1576** would still be very reasonable). 1577*/ 1578 1579#ifndef WRONG 1580#define WRONG (-1) 1581#endif /* !defined WRONG */ 1582 1583/* 1584** Simplified normalize logic courtesy Paul Eggert. 1585*/ 1586 1587static int 1588increment_overflow(number, delta) 1589int * number; 1590int delta; 1591{ 1592 int number0; 1593 1594 number0 = *number; 1595 *number += delta; 1596 return (*number < number0) != (delta < 0); 1597} 1598 1599static int 1600long_increment_overflow(number, delta) 1601long * number; 1602int delta; 1603{ 1604 long number0; 1605 1606 number0 = *number; 1607 *number += delta; 1608 return (*number < number0) != (delta < 0); 1609} 1610 1611static int 1612normalize_overflow(tensptr, unitsptr, base) 1613int * const tensptr; 1614int * const unitsptr; 1615const int base; 1616{ 1617 register int tensdelta; 1618 1619 tensdelta = (*unitsptr >= 0) ? 1620 (*unitsptr / base) : 1621 (-1 - (-1 - *unitsptr) / base); 1622 *unitsptr -= tensdelta * base; 1623 return increment_overflow(tensptr, tensdelta); 1624} 1625 1626static int 1627long_normalize_overflow(tensptr, unitsptr, base) 1628long * const tensptr; 1629int * const unitsptr; 1630const int base; 1631{ 1632 register int tensdelta; 1633 1634 tensdelta = (*unitsptr >= 0) ? 1635 (*unitsptr / base) : 1636 (-1 - (-1 - *unitsptr) / base); 1637 *unitsptr -= tensdelta * base; 1638 return long_increment_overflow(tensptr, tensdelta); 1639} 1640 1641static int 1642tmcomp(atmp, btmp) 1643register const struct tm * const atmp; 1644register const struct tm * const btmp; 1645{ 1646 register int result; 1647 1648 if ((result = (atmp->tm_year - btmp->tm_year)) == 0 && 1649 (result = (atmp->tm_mon - btmp->tm_mon)) == 0 && 1650 (result = (atmp->tm_mday - btmp->tm_mday)) == 0 && 1651 (result = (atmp->tm_hour - btmp->tm_hour)) == 0 && 1652 (result = (atmp->tm_min - btmp->tm_min)) == 0) 1653 result = atmp->tm_sec - btmp->tm_sec; 1654 return result; 1655} 1656 1657static time_t 1658time2sub(tmp, funcp, offset, okayp, do_norm_secs) 1659struct tm * const tmp; 1660struct tm * (* const funcp) P((const time_t*, long, struct tm*)); 1661const long offset; 1662int * const okayp; 1663const int do_norm_secs; 1664{ 1665 register const struct state * sp; 1666 register int dir; 1667 register int i, j; 1668 register int saved_seconds; 1669 register long li; 1670 register time_t lo; 1671 register time_t hi; 1672 long y; 1673 time_t newt; 1674 time_t t; 1675 struct tm yourtm, mytm; 1676 1677 *okayp = FALSE; 1678 yourtm = *tmp; 1679 if (do_norm_secs) { 1680 if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec, 1681 SECSPERMIN)) 1682 return WRONG; 1683 } 1684 if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR)) 1685 return WRONG; 1686 if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY)) 1687 return WRONG; 1688 y = yourtm.tm_year; 1689 if (long_normalize_overflow(&y, &yourtm.tm_mon, MONSPERYEAR)) 1690 return WRONG; 1691 /* 1692 ** Turn y into an actual year number for now. 1693 ** It is converted back to an offset from TM_YEAR_BASE later. 1694 */ 1695 if (long_increment_overflow(&y, TM_YEAR_BASE)) 1696 return WRONG; 1697 while (yourtm.tm_mday <= 0) { 1698 if (long_increment_overflow(&y, -1)) 1699 return WRONG; 1700 li = y + (1 < yourtm.tm_mon); 1701 yourtm.tm_mday += year_lengths[isleap(li)]; 1702 } 1703 while (yourtm.tm_mday > DAYSPERLYEAR) { 1704 li = y + (1 < yourtm.tm_mon); 1705 yourtm.tm_mday -= year_lengths[isleap(li)]; 1706 if (long_increment_overflow(&y, 1)) 1707 return WRONG; 1708 } 1709 for ( ; ; ) { 1710 i = mon_lengths[isleap(y)][yourtm.tm_mon]; 1711 if (yourtm.tm_mday <= i) 1712 break; 1713 yourtm.tm_mday -= i; 1714 if (++yourtm.tm_mon >= MONSPERYEAR) { 1715 yourtm.tm_mon = 0; 1716 if (long_increment_overflow(&y, 1)) 1717 return WRONG; 1718 } 1719 } 1720 if (long_increment_overflow(&y, -TM_YEAR_BASE)) 1721 return WRONG; 1722 yourtm.tm_year = y; 1723 if (yourtm.tm_year != y) 1724 return WRONG; 1725 if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN) 1726 saved_seconds = 0; 1727 else if (y + TM_YEAR_BASE < EPOCH_YEAR) { 1728 /* 1729 ** We can't set tm_sec to 0, because that might push the 1730 ** time below the minimum representable time. 1731 ** Set tm_sec to 59 instead. 1732 ** This assumes that the minimum representable time is 1733 ** not in the same minute that a leap second was deleted from, 1734 ** which is a safer assumption than using 58 would be. 1735 */ 1736 if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN)) 1737 return WRONG; 1738 saved_seconds = yourtm.tm_sec; 1739 yourtm.tm_sec = SECSPERMIN - 1; 1740 } else { 1741 saved_seconds = yourtm.tm_sec; 1742 yourtm.tm_sec = 0; 1743 } 1744 /* 1745 ** Do a binary search (this works whatever time_t's type is). 1746 */ 1747 if (!TYPE_SIGNED(time_t)) { 1748 lo = 0; 1749 hi = lo - 1; 1750 } else if (!TYPE_INTEGRAL(time_t)) { 1751 if (sizeof(time_t) > sizeof(float)) 1752 hi = (time_t) DBL_MAX; 1753 else hi = (time_t) FLT_MAX; 1754 lo = -hi; 1755 } else { 1756 lo = 1; 1757 for (i = 0; i < (int) TYPE_BIT(time_t) - 1; ++i) 1758 lo *= 2; 1759 hi = -(lo + 1); 1760 } 1761 for ( ; ; ) { 1762 t = lo / 2 + hi / 2; 1763 if (t < lo) 1764 t = lo; 1765 else if (t > hi) 1766 t = hi; 1767 if ((*funcp)(&t, offset, &mytm) == NULL) { 1768 /* 1769 ** Assume that t is too extreme to be represented in 1770 ** a struct tm; arrange things so that it is less 1771 ** extreme on the next pass. 1772 */ 1773 dir = (t > 0) ? 1 : -1; 1774 } else dir = tmcomp(&mytm, &yourtm); 1775 if (dir != 0) { 1776 if (t == lo) { 1777 ++t; 1778 if (t <= lo) 1779 return WRONG; 1780 ++lo; 1781 } else if (t == hi) { 1782 --t; 1783 if (t >= hi) 1784 return WRONG; 1785 --hi; 1786 } 1787 if (lo > hi) 1788 return WRONG; 1789 if (dir > 0) 1790 hi = t; 1791 else lo = t; 1792 continue; 1793 } 1794 if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst) 1795 break; 1796 /* 1797 ** Right time, wrong type. 1798 ** Hunt for right time, right type. 1799 ** It's okay to guess wrong since the guess 1800 ** gets checked. 1801 */ 1802 /* 1803 ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's. 1804 */ 1805 sp = (const struct state *) 1806 (((void *) funcp == (void *) localsub) ? 1807 lclptr : gmtptr); 1808#ifdef ALL_STATE 1809 if (sp == NULL) 1810 return WRONG; 1811#endif /* defined ALL_STATE */ 1812 for (i = sp->typecnt - 1; i >= 0; --i) { 1813 if (sp->ttis[i].tt_isdst != yourtm.tm_isdst) 1814 continue; 1815 for (j = sp->typecnt - 1; j >= 0; --j) { 1816 if (sp->ttis[j].tt_isdst == yourtm.tm_isdst) 1817 continue; 1818 newt = t + sp->ttis[j].tt_gmtoff - 1819 sp->ttis[i].tt_gmtoff; 1820 if ((*funcp)(&newt, offset, &mytm) == NULL) 1821 continue; 1822 if (tmcomp(&mytm, &yourtm) != 0) 1823 continue; 1824 if (mytm.tm_isdst != yourtm.tm_isdst) 1825 continue; 1826 /* 1827 ** We have a match. 1828 */ 1829 t = newt; 1830 goto label; 1831 } 1832 } 1833 return WRONG; 1834 } 1835label: 1836 newt = t + saved_seconds; 1837 if ((newt < t) != (saved_seconds < 0)) 1838 return WRONG; 1839 t = newt; 1840 if ((*funcp)(&t, offset, tmp)) 1841 *okayp = TRUE; 1842 return t; 1843} 1844 1845static time_t 1846time2(tmp, funcp, offset, okayp) 1847struct tm * const tmp; 1848struct tm * (* const funcp) P((const time_t*, long, struct tm*)); 1849const long offset; 1850int * const okayp; 1851{ 1852 time_t t; 1853 1854 /* 1855 ** First try without normalization of seconds 1856 ** (in case tm_sec contains a value associated with a leap second). 1857 ** If that fails, try with normalization of seconds. 1858 */ 1859 t = time2sub(tmp, funcp, offset, okayp, FALSE); 1860 return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE); 1861} 1862 1863static time_t 1864time1(tmp, funcp, offset) 1865struct tm * const tmp; 1866struct tm * (* const funcp) P((const time_t *, long, struct tm *)); 1867const long offset; 1868{ 1869 register time_t t; 1870 register const struct state * sp; 1871 register int samei, otheri; 1872 register int sameind, otherind; 1873 register int i; 1874 register int nseen; 1875 int seen[TZ_MAX_TYPES]; 1876 int types[TZ_MAX_TYPES]; 1877 int okay; 1878 1879 if (tmp->tm_isdst > 1) 1880 tmp->tm_isdst = 1; 1881 t = time2(tmp, funcp, offset, &okay); 1882#ifdef PCTS 1883 /* 1884 ** PCTS code courtesy Grant Sullivan. 1885 */ 1886 if (okay) 1887 return t; 1888 if (tmp->tm_isdst < 0) 1889 tmp->tm_isdst = 0; /* reset to std and try again */ 1890#endif /* defined PCTS */ 1891#ifndef PCTS 1892 if (okay || tmp->tm_isdst < 0) 1893 return t; 1894#endif /* !defined PCTS */ 1895 /* 1896 ** We're supposed to assume that somebody took a time of one type 1897 ** and did some math on it that yielded a "struct tm" that's bad. 1898 ** We try to divine the type they started from and adjust to the 1899 ** type they need. 1900 */ 1901 /* 1902 ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's. 1903 */ 1904 sp = (const struct state *) (((void *) funcp == (void *) localsub) ? 1905 lclptr : gmtptr); 1906#ifdef ALL_STATE 1907 if (sp == NULL) 1908 return WRONG; 1909#endif /* defined ALL_STATE */ 1910 for (i = 0; i < sp->typecnt; ++i) 1911 seen[i] = FALSE; 1912 nseen = 0; 1913 for (i = sp->timecnt - 1; i >= 0; --i) 1914 if (!seen[sp->types[i]]) { 1915 seen[sp->types[i]] = TRUE; 1916 types[nseen++] = sp->types[i]; 1917 } 1918 for (sameind = 0; sameind < nseen; ++sameind) { 1919 samei = types[sameind]; 1920 if (sp->ttis[samei].tt_isdst != tmp->tm_isdst) 1921 continue; 1922 for (otherind = 0; otherind < nseen; ++otherind) { 1923 otheri = types[otherind]; 1924 if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst) 1925 continue; 1926 tmp->tm_sec += sp->ttis[otheri].tt_gmtoff - 1927 sp->ttis[samei].tt_gmtoff; 1928 tmp->tm_isdst = !tmp->tm_isdst; 1929 t = time2(tmp, funcp, offset, &okay); 1930 if (okay) 1931 return t; 1932 tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff - 1933 sp->ttis[samei].tt_gmtoff; 1934 tmp->tm_isdst = !tmp->tm_isdst; 1935 } 1936 } 1937 return WRONG; 1938} 1939 1940#if 0 1941time_t 1942mktime(tmp) 1943struct tm * const tmp; 1944{ 1945 tzset(); 1946 return time1(tmp, localsub, 0L); 1947} 1948#endif 1949 1950#ifndef STD_INSPIRED 1951#pragma weak timelocal=mktime 1952#else 1953 1954time_t 1955timelocal(tmp) 1956struct tm * const tmp; 1957{ 1958 tmp->tm_isdst = -1; /* in case it wasn't initialized */ 1959 return mktime(tmp); 1960} 1961 1962time_t 1963timegm(tmp) 1964struct tm * const tmp; 1965{ 1966 tmp->tm_isdst = 0; 1967 return time1(tmp, gmtsub, 0L); 1968} 1969 1970time_t 1971timeoff(tmp, offset) 1972struct tm * const tmp; 1973const long offset; 1974{ 1975 tmp->tm_isdst = 0; 1976 return time1(tmp, gmtsub, offset); 1977} 1978 1979#endif /* defined STD_INSPIRED */ 1980 1981#ifdef CMUCS 1982 1983/* 1984** The following is supplied for compatibility with 1985** previous versions of the CMUCS runtime library. 1986*/ 1987 1988long 1989gtime(tmp) 1990struct tm * const tmp; 1991{ 1992 const time_t t = mktime(tmp); 1993 1994 if (t == WRONG) 1995 return -1; 1996 return t; 1997} 1998 1999#endif /* defined CMUCS */ 2000 2001/* 2002** XXX--is the below the right way to conditionalize?? 2003*/ 2004 2005#ifdef STD_INSPIRED 2006 2007/* 2008** IEEE Std 1003.1-1988 (POSIX) legislates that 536457599 2009** shall correspond to "Wed Dec 31 23:59:59 UTC 1986", which 2010** is not the case if we are accounting for leap seconds. 2011** So, we provide the following conversion routines for use 2012** when exchanging timestamps with POSIX conforming systems. 2013*/ 2014 2015static long 2016leapcorr(timep) 2017time_t * timep; 2018{ 2019 register struct state * sp; 2020 register struct lsinfo * lp; 2021 register int i; 2022 2023 sp = lclptr; 2024 i = sp->leapcnt; 2025 while (--i >= 0) { 2026 lp = &sp->lsis[i]; 2027 if (*timep >= lp->ls_trans) 2028 return lp->ls_corr; 2029 } 2030 return 0; 2031} 2032 2033time_t 2034time2posix(t) 2035time_t t; 2036{ 2037 tzset(); 2038 return t - leapcorr(&t); 2039} 2040 2041time_t 2042posix2time(t) 2043time_t t; 2044{ 2045 time_t x; 2046 time_t y; 2047 2048 tzset(); 2049 /* 2050 ** For a positive leap second hit, the result 2051 ** is not unique. For a negative leap second 2052 ** hit, the corresponding time doesn't exist, 2053 ** so we return an adjacent second. 2054 */ 2055 x = t + leapcorr(&t); 2056 y = x - leapcorr(&x); 2057 if (y < t) { 2058 do { 2059 x++; 2060 y = x - leapcorr(&x); 2061 } while (y < t); 2062 if (t != y) 2063 return x - 1; 2064 } else if (y > t) { 2065 do { 2066 --x; 2067 y = x - leapcorr(&x); 2068 } while (y > t); 2069 if (t != y) 2070 return x + 1; 2071 } 2072 return x; 2073} 2074 2075#endif /* defined STD_INSPIRED */ 2076