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