1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/intl/icu/source/tools/tzcode/localtime.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,2080 @@ 1.4 +/* 1.5 +** This file is in the public domain, so clarified as of 1.6 +** 1996-06-05 by Arthur David Olson. 1.7 +*/ 1.8 + 1.9 +#ifndef lint 1.10 +#ifndef NOID 1.11 +static char elsieid[] = "@(#)localtime.c 8.9"; 1.12 +#endif /* !defined NOID */ 1.13 +#endif /* !defined lint */ 1.14 + 1.15 +/* 1.16 +** Leap second handling from Bradley White. 1.17 +** POSIX-style TZ environment variable handling from Guy Harris. 1.18 +*/ 1.19 + 1.20 +/*LINTLIBRARY*/ 1.21 + 1.22 +#include "private.h" 1.23 +#include "tzfile.h" 1.24 +#include "fcntl.h" 1.25 +#include "float.h" /* for FLT_MAX and DBL_MAX */ 1.26 + 1.27 +#ifndef TZ_ABBR_MAX_LEN 1.28 +#define TZ_ABBR_MAX_LEN 16 1.29 +#endif /* !defined TZ_ABBR_MAX_LEN */ 1.30 + 1.31 +#ifndef TZ_ABBR_CHAR_SET 1.32 +#define TZ_ABBR_CHAR_SET \ 1.33 + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._" 1.34 +#endif /* !defined TZ_ABBR_CHAR_SET */ 1.35 + 1.36 +#ifndef TZ_ABBR_ERR_CHAR 1.37 +#define TZ_ABBR_ERR_CHAR '_' 1.38 +#endif /* !defined TZ_ABBR_ERR_CHAR */ 1.39 + 1.40 +/* 1.41 +** SunOS 4.1.1 headers lack O_BINARY. 1.42 +*/ 1.43 + 1.44 +#ifdef O_BINARY 1.45 +#define OPEN_MODE (O_RDONLY | O_BINARY) 1.46 +#endif /* defined O_BINARY */ 1.47 +#ifndef O_BINARY 1.48 +#define OPEN_MODE O_RDONLY 1.49 +#endif /* !defined O_BINARY */ 1.50 + 1.51 +#ifndef WILDABBR 1.52 +/* 1.53 +** Someone might make incorrect use of a time zone abbreviation: 1.54 +** 1. They might reference tzname[0] before calling tzset (explicitly 1.55 +** or implicitly). 1.56 +** 2. They might reference tzname[1] before calling tzset (explicitly 1.57 +** or implicitly). 1.58 +** 3. They might reference tzname[1] after setting to a time zone 1.59 +** in which Daylight Saving Time is never observed. 1.60 +** 4. They might reference tzname[0] after setting to a time zone 1.61 +** in which Standard Time is never observed. 1.62 +** 5. They might reference tm.TM_ZONE after calling offtime. 1.63 +** What's best to do in the above cases is open to debate; 1.64 +** for now, we just set things up so that in any of the five cases 1.65 +** WILDABBR is used. Another possibility: initialize tzname[0] to the 1.66 +** string "tzname[0] used before set", and similarly for the other cases. 1.67 +** And another: initialize tzname[0] to "ERA", with an explanation in the 1.68 +** manual page of what this "time zone abbreviation" means (doing this so 1.69 +** that tzname[0] has the "normal" length of three characters). 1.70 +*/ 1.71 +#define WILDABBR " " 1.72 +#endif /* !defined WILDABBR */ 1.73 + 1.74 +static char wildabbr[] = WILDABBR; 1.75 + 1.76 +static const char gmt[] = "GMT"; 1.77 + 1.78 +/* 1.79 +** The DST rules to use if TZ has no rules and we can't load TZDEFRULES. 1.80 +** We default to US rules as of 1999-08-17. 1.81 +** POSIX 1003.1 section 8.1.1 says that the default DST rules are 1.82 +** implementation dependent; for historical reasons, US rules are a 1.83 +** common default. 1.84 +*/ 1.85 +#ifndef TZDEFRULESTRING 1.86 +#define TZDEFRULESTRING ",M4.1.0,M10.5.0" 1.87 +#endif /* !defined TZDEFDST */ 1.88 + 1.89 +struct ttinfo { /* time type information */ 1.90 + long tt_gmtoff; /* UTC offset in seconds */ 1.91 + int tt_isdst; /* used to set tm_isdst */ 1.92 + int tt_abbrind; /* abbreviation list index */ 1.93 + int tt_ttisstd; /* TRUE if transition is std time */ 1.94 + int tt_ttisgmt; /* TRUE if transition is UTC */ 1.95 +}; 1.96 + 1.97 +struct lsinfo { /* leap second information */ 1.98 + time_t ls_trans; /* transition time */ 1.99 + long ls_corr; /* correction to apply */ 1.100 +}; 1.101 + 1.102 +#define BIGGEST(a, b) (((a) > (b)) ? (a) : (b)) 1.103 + 1.104 +#ifdef TZNAME_MAX 1.105 +#define MY_TZNAME_MAX TZNAME_MAX 1.106 +#endif /* defined TZNAME_MAX */ 1.107 +#ifndef TZNAME_MAX 1.108 +#define MY_TZNAME_MAX 255 1.109 +#endif /* !defined TZNAME_MAX */ 1.110 + 1.111 +struct state { 1.112 + int leapcnt; 1.113 + int timecnt; 1.114 + int typecnt; 1.115 + int charcnt; 1.116 + int goback; 1.117 + int goahead; 1.118 + time_t ats[TZ_MAX_TIMES]; 1.119 + unsigned char types[TZ_MAX_TIMES]; 1.120 + struct ttinfo ttis[TZ_MAX_TYPES]; 1.121 + char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt), 1.122 + (2 * (MY_TZNAME_MAX + 1)))]; 1.123 + struct lsinfo lsis[TZ_MAX_LEAPS]; 1.124 +}; 1.125 + 1.126 +struct rule { 1.127 + int r_type; /* type of rule--see below */ 1.128 + int r_day; /* day number of rule */ 1.129 + int r_week; /* week number of rule */ 1.130 + int r_mon; /* month number of rule */ 1.131 + long r_time; /* transition time of rule */ 1.132 +}; 1.133 + 1.134 +#define JULIAN_DAY 0 /* Jn - Julian day */ 1.135 +#define DAY_OF_YEAR 1 /* n - day of year */ 1.136 +#define MONTH_NTH_DAY_OF_WEEK 2 /* Mm.n.d - month, week, day of week */ 1.137 + 1.138 +/* 1.139 +** Prototypes for static functions. 1.140 +*/ 1.141 + 1.142 +static long detzcode(const char * codep); 1.143 +static time_t detzcode64(const char * codep); 1.144 +static int differ_by_repeat(time_t t1, time_t t0); 1.145 +static const char * getzname(const char * strp); 1.146 +static const char * getqzname(const char * strp, const int delim); 1.147 +static const char * getnum(const char * strp, int * nump, int min, 1.148 + int max); 1.149 +static const char * getsecs(const char * strp, long * secsp); 1.150 +static const char * getoffset(const char * strp, long * offsetp); 1.151 +static const char * getrule(const char * strp, struct rule * rulep); 1.152 +static void gmtload(struct state * sp); 1.153 +static struct tm * gmtsub(const time_t * timep, long offset, 1.154 + struct tm * tmp); 1.155 +static struct tm * localsub(const time_t * timep, long offset, 1.156 + struct tm * tmp); 1.157 +static int increment_overflow(int * number, int delta); 1.158 +static int leaps_thru_end_of(int y); 1.159 +static int long_increment_overflow(long * number, int delta); 1.160 +static int long_normalize_overflow(long * tensptr, 1.161 + int * unitsptr, int base); 1.162 +static int normalize_overflow(int * tensptr, int * unitsptr, 1.163 + int base); 1.164 +static void settzname(void); 1.165 +static time_t time1(struct tm * tmp, 1.166 + struct tm * (*funcp)(const time_t *, 1.167 + long, struct tm *), 1.168 + long offset); 1.169 +static time_t time2(struct tm *tmp, 1.170 + struct tm * (*funcp)(const time_t *, 1.171 + long, struct tm*), 1.172 + long offset, int * okayp); 1.173 +static time_t time2sub(struct tm *tmp, 1.174 + struct tm * (*funcp)(const time_t *, 1.175 + long, struct tm*), 1.176 + long offset, int * okayp, int do_norm_secs); 1.177 +static struct tm * timesub(const time_t * timep, long offset, 1.178 + const struct state * sp, struct tm * tmp); 1.179 +static int tmcomp(const struct tm * atmp, 1.180 + const struct tm * btmp); 1.181 +static time_t transtime(time_t janfirst, int year, 1.182 + const struct rule * rulep, long offset); 1.183 +static int typesequiv(const struct state * sp, int a, int b); 1.184 +static int tzload(const char * name, struct state * sp, 1.185 + int doextend); 1.186 +static int tzparse(const char * name, struct state * sp, 1.187 + int lastditch); 1.188 + 1.189 +#ifdef ALL_STATE 1.190 +static struct state * lclptr; 1.191 +static struct state * gmtptr; 1.192 +#endif /* defined ALL_STATE */ 1.193 + 1.194 +#ifndef ALL_STATE 1.195 +static struct state lclmem; 1.196 +static struct state gmtmem; 1.197 +#define lclptr (&lclmem) 1.198 +#define gmtptr (&gmtmem) 1.199 +#endif /* State Farm */ 1.200 + 1.201 +#ifndef TZ_STRLEN_MAX 1.202 +#define TZ_STRLEN_MAX 255 1.203 +#endif /* !defined TZ_STRLEN_MAX */ 1.204 + 1.205 +static char lcl_TZname[TZ_STRLEN_MAX + 1]; 1.206 +static int lcl_is_set; 1.207 +static int gmt_is_set; 1.208 + 1.209 +char * tzname[2] = { 1.210 + wildabbr, 1.211 + wildabbr 1.212 +}; 1.213 + 1.214 +/* 1.215 +** Section 4.12.3 of X3.159-1989 requires that 1.216 +** Except for the strftime function, these functions [asctime, 1.217 +** ctime, gmtime, localtime] return values in one of two static 1.218 +** objects: a broken-down time structure and an array of char. 1.219 +** Thanks to Paul Eggert for noting this. 1.220 +*/ 1.221 + 1.222 +static struct tm tm; 1.223 + 1.224 +#ifdef USG_COMPAT 1.225 +time_t timezone = 0; 1.226 +int daylight = 0; 1.227 +#endif /* defined USG_COMPAT */ 1.228 + 1.229 +#ifdef ALTZONE 1.230 +time_t altzone = 0; 1.231 +#endif /* defined ALTZONE */ 1.232 + 1.233 +static long 1.234 +detzcode(codep) 1.235 +const char * const codep; 1.236 +{ 1.237 + register long result; 1.238 + register int i; 1.239 + 1.240 + result = (codep[0] & 0x80) ? ~0L : 0; 1.241 + for (i = 0; i < 4; ++i) 1.242 + result = (result << 8) | (codep[i] & 0xff); 1.243 + return result; 1.244 +} 1.245 + 1.246 +static time_t 1.247 +detzcode64(codep) 1.248 +const char * const codep; 1.249 +{ 1.250 + register time_t result; 1.251 + register int i; 1.252 + 1.253 + result = (codep[0] & 0x80) ? (~(int_fast64_t) 0) : 0; 1.254 + for (i = 0; i < 8; ++i) 1.255 + result = result * 256 + (codep[i] & 0xff); 1.256 + return result; 1.257 +} 1.258 + 1.259 +static void 1.260 +settzname(void) 1.261 +{ 1.262 + register struct state * const sp = lclptr; 1.263 + register int i; 1.264 + 1.265 + tzname[0] = wildabbr; 1.266 + tzname[1] = wildabbr; 1.267 +#ifdef USG_COMPAT 1.268 + daylight = 0; 1.269 + timezone = 0; 1.270 +#endif /* defined USG_COMPAT */ 1.271 +#ifdef ALTZONE 1.272 + altzone = 0; 1.273 +#endif /* defined ALTZONE */ 1.274 +#ifdef ALL_STATE 1.275 + if (sp == NULL) { 1.276 + tzname[0] = tzname[1] = gmt; 1.277 + return; 1.278 + } 1.279 +#endif /* defined ALL_STATE */ 1.280 + for (i = 0; i < sp->typecnt; ++i) { 1.281 + register const struct ttinfo * const ttisp = &sp->ttis[i]; 1.282 + 1.283 + tzname[ttisp->tt_isdst] = 1.284 + &sp->chars[ttisp->tt_abbrind]; 1.285 +#ifdef USG_COMPAT 1.286 + if (ttisp->tt_isdst) 1.287 + daylight = 1; 1.288 + if (i == 0 || !ttisp->tt_isdst) 1.289 + timezone = -(ttisp->tt_gmtoff); 1.290 +#endif /* defined USG_COMPAT */ 1.291 +#ifdef ALTZONE 1.292 + if (i == 0 || ttisp->tt_isdst) 1.293 + altzone = -(ttisp->tt_gmtoff); 1.294 +#endif /* defined ALTZONE */ 1.295 + } 1.296 + /* 1.297 + ** And to get the latest zone names into tzname. . . 1.298 + */ 1.299 + for (i = 0; i < sp->timecnt; ++i) { 1.300 + register const struct ttinfo * const ttisp = 1.301 + &sp->ttis[ 1.302 + sp->types[i]]; 1.303 + 1.304 + tzname[ttisp->tt_isdst] = 1.305 + &sp->chars[ttisp->tt_abbrind]; 1.306 + } 1.307 + /* 1.308 + ** Finally, scrub the abbreviations. 1.309 + ** First, replace bogus characters. 1.310 + */ 1.311 + for (i = 0; i < sp->charcnt; ++i) 1.312 + if (strchr(TZ_ABBR_CHAR_SET, sp->chars[i]) == NULL) 1.313 + sp->chars[i] = TZ_ABBR_ERR_CHAR; 1.314 + /* 1.315 + ** Second, truncate long abbreviations. 1.316 + */ 1.317 + for (i = 0; i < sp->typecnt; ++i) { 1.318 + register const struct ttinfo * const ttisp = &sp->ttis[i]; 1.319 + register char * cp = &sp->chars[ttisp->tt_abbrind]; 1.320 + 1.321 + if (strlen(cp) > TZ_ABBR_MAX_LEN && 1.322 + strcmp(cp, GRANDPARENTED) != 0) 1.323 + *(cp + TZ_ABBR_MAX_LEN) = '\0'; 1.324 + } 1.325 +} 1.326 + 1.327 +static int 1.328 +differ_by_repeat(t1, t0) 1.329 +const time_t t1; 1.330 +const time_t t0; 1.331 +{ 1.332 + if (TYPE_INTEGRAL(time_t) && 1.333 + TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS) 1.334 + return 0; 1.335 + return t1 - t0 == SECSPERREPEAT; 1.336 +} 1.337 + 1.338 +static int 1.339 +tzload(name, sp, doextend) 1.340 +register const char * name; 1.341 +register struct state * const sp; 1.342 +register const int doextend; 1.343 +{ 1.344 + register const char * p; 1.345 + register int i; 1.346 + register int fid; 1.347 + register int stored; 1.348 + register int nread; 1.349 + union { 1.350 + struct tzhead tzhead; 1.351 + char buf[2 * sizeof(struct tzhead) + 1.352 + 2 * sizeof *sp + 1.353 + 4 * TZ_MAX_TIMES]; 1.354 + } u; 1.355 + 1.356 + if (name == NULL && (name = TZDEFAULT) == NULL) 1.357 + return -1; 1.358 + { 1.359 + register int doaccess; 1.360 + /* 1.361 + ** Section 4.9.1 of the C standard says that 1.362 + ** "FILENAME_MAX expands to an integral constant expression 1.363 + ** that is the size needed for an array of char large enough 1.364 + ** to hold the longest file name string that the implementation 1.365 + ** guarantees can be opened." 1.366 + */ 1.367 + char fullname[FILENAME_MAX + 1]; 1.368 + 1.369 + if (name[0] == ':') 1.370 + ++name; 1.371 + doaccess = name[0] == '/'; 1.372 + if (!doaccess) { 1.373 + if ((p = TZDIR) == NULL) 1.374 + return -1; 1.375 + if ((strlen(p) + strlen(name) + 1) >= sizeof fullname) 1.376 + return -1; 1.377 + (void) strcpy(fullname, p); 1.378 + (void) strcat(fullname, "/"); 1.379 + (void) strcat(fullname, name); 1.380 + /* 1.381 + ** Set doaccess if '.' (as in "../") shows up in name. 1.382 + */ 1.383 + if (strchr(name, '.') != NULL) 1.384 + doaccess = TRUE; 1.385 + name = fullname; 1.386 + } 1.387 + if (doaccess && access(name, R_OK) != 0) 1.388 + return -1; 1.389 + if ((fid = open(name, OPEN_MODE)) == -1) 1.390 + return -1; 1.391 + } 1.392 + nread = read(fid, u.buf, sizeof u.buf); 1.393 + if (close(fid) < 0 || nread <= 0) 1.394 + return -1; 1.395 + for (stored = 4; stored <= 8; stored *= 2) { 1.396 + int ttisstdcnt; 1.397 + int ttisgmtcnt; 1.398 + 1.399 + ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt); 1.400 + ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt); 1.401 + sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt); 1.402 + sp->timecnt = (int) detzcode(u.tzhead.tzh_timecnt); 1.403 + sp->typecnt = (int) detzcode(u.tzhead.tzh_typecnt); 1.404 + sp->charcnt = (int) detzcode(u.tzhead.tzh_charcnt); 1.405 + p = u.tzhead.tzh_charcnt + sizeof u.tzhead.tzh_charcnt; 1.406 + if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS || 1.407 + sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES || 1.408 + sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES || 1.409 + sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS || 1.410 + (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) || 1.411 + (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0)) 1.412 + return -1; 1.413 + if (nread - (p - u.buf) < 1.414 + sp->timecnt * stored + /* ats */ 1.415 + sp->timecnt + /* types */ 1.416 + sp->typecnt * 6 + /* ttinfos */ 1.417 + sp->charcnt + /* chars */ 1.418 + sp->leapcnt * (stored + 4) + /* lsinfos */ 1.419 + ttisstdcnt + /* ttisstds */ 1.420 + ttisgmtcnt) /* ttisgmts */ 1.421 + return -1; 1.422 + for (i = 0; i < sp->timecnt; ++i) { 1.423 + sp->ats[i] = (stored == 4) ? 1.424 + detzcode(p) : detzcode64(p); 1.425 + p += stored; 1.426 + } 1.427 + for (i = 0; i < sp->timecnt; ++i) { 1.428 + sp->types[i] = (unsigned char) *p++; 1.429 + if (sp->types[i] >= sp->typecnt) 1.430 + return -1; 1.431 + } 1.432 + for (i = 0; i < sp->typecnt; ++i) { 1.433 + register struct ttinfo * ttisp; 1.434 + 1.435 + ttisp = &sp->ttis[i]; 1.436 + ttisp->tt_gmtoff = detzcode(p); 1.437 + p += 4; 1.438 + ttisp->tt_isdst = (unsigned char) *p++; 1.439 + if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1) 1.440 + return -1; 1.441 + ttisp->tt_abbrind = (unsigned char) *p++; 1.442 + if (ttisp->tt_abbrind < 0 || 1.443 + ttisp->tt_abbrind > sp->charcnt) 1.444 + return -1; 1.445 + } 1.446 + for (i = 0; i < sp->charcnt; ++i) 1.447 + sp->chars[i] = *p++; 1.448 + sp->chars[i] = '\0'; /* ensure '\0' at end */ 1.449 + for (i = 0; i < sp->leapcnt; ++i) { 1.450 + register struct lsinfo * lsisp; 1.451 + 1.452 + lsisp = &sp->lsis[i]; 1.453 + lsisp->ls_trans = (stored == 4) ? 1.454 + detzcode(p) : detzcode64(p); 1.455 + p += stored; 1.456 + lsisp->ls_corr = detzcode(p); 1.457 + p += 4; 1.458 + } 1.459 + for (i = 0; i < sp->typecnt; ++i) { 1.460 + register struct ttinfo * ttisp; 1.461 + 1.462 + ttisp = &sp->ttis[i]; 1.463 + if (ttisstdcnt == 0) 1.464 + ttisp->tt_ttisstd = FALSE; 1.465 + else { 1.466 + ttisp->tt_ttisstd = *p++; 1.467 + if (ttisp->tt_ttisstd != TRUE && 1.468 + ttisp->tt_ttisstd != FALSE) 1.469 + return -1; 1.470 + } 1.471 + } 1.472 + for (i = 0; i < sp->typecnt; ++i) { 1.473 + register struct ttinfo * ttisp; 1.474 + 1.475 + ttisp = &sp->ttis[i]; 1.476 + if (ttisgmtcnt == 0) 1.477 + ttisp->tt_ttisgmt = FALSE; 1.478 + else { 1.479 + ttisp->tt_ttisgmt = *p++; 1.480 + if (ttisp->tt_ttisgmt != TRUE && 1.481 + ttisp->tt_ttisgmt != FALSE) 1.482 + return -1; 1.483 + } 1.484 + } 1.485 + /* 1.486 + ** Out-of-sort ats should mean we're running on a 1.487 + ** signed time_t system but using a data file with 1.488 + ** unsigned values (or vice versa). 1.489 + */ 1.490 + for (i = 0; i < sp->timecnt - 2; ++i) 1.491 + if (sp->ats[i] > sp->ats[i + 1]) { 1.492 + ++i; 1.493 + if (TYPE_SIGNED(time_t)) { 1.494 + /* 1.495 + ** Ignore the end (easy). 1.496 + */ 1.497 + sp->timecnt = i; 1.498 + } else { 1.499 + /* 1.500 + ** Ignore the beginning (harder). 1.501 + */ 1.502 + register int j; 1.503 + 1.504 + for (j = 0; j + i < sp->timecnt; ++j) { 1.505 + sp->ats[j] = sp->ats[j + i]; 1.506 + sp->types[j] = sp->types[j + i]; 1.507 + } 1.508 + sp->timecnt = j; 1.509 + } 1.510 + break; 1.511 + } 1.512 + /* 1.513 + ** If this is an old file, we're done. 1.514 + */ 1.515 + if (u.tzhead.tzh_version[0] == '\0') 1.516 + break; 1.517 + nread -= p - u.buf; 1.518 + for (i = 0; i < nread; ++i) 1.519 + u.buf[i] = p[i]; 1.520 + /* 1.521 + ** If this is a narrow integer time_t system, we're done. 1.522 + */ 1.523 + if (stored >= (int) sizeof(time_t) && TYPE_INTEGRAL(time_t)) 1.524 + break; 1.525 + } 1.526 + if (doextend && nread > 2 && 1.527 + u.buf[0] == '\n' && u.buf[nread - 1] == '\n' && 1.528 + sp->typecnt + 2 <= TZ_MAX_TYPES) { 1.529 + struct state ts; 1.530 + register int result; 1.531 + 1.532 + u.buf[nread - 1] = '\0'; 1.533 + result = tzparse(&u.buf[1], &ts, FALSE); 1.534 + if (result == 0 && ts.typecnt == 2 && 1.535 + sp->charcnt + ts.charcnt <= TZ_MAX_CHARS) { 1.536 + for (i = 0; i < 2; ++i) 1.537 + ts.ttis[i].tt_abbrind += 1.538 + sp->charcnt; 1.539 + for (i = 0; i < ts.charcnt; ++i) 1.540 + sp->chars[sp->charcnt++] = 1.541 + ts.chars[i]; 1.542 + i = 0; 1.543 + while (i < ts.timecnt && 1.544 + ts.ats[i] <= 1.545 + sp->ats[sp->timecnt - 1]) 1.546 + ++i; 1.547 + while (i < ts.timecnt && 1.548 + sp->timecnt < TZ_MAX_TIMES) { 1.549 + sp->ats[sp->timecnt] = 1.550 + ts.ats[i]; 1.551 + sp->types[sp->timecnt] = 1.552 + sp->typecnt + 1.553 + ts.types[i]; 1.554 + ++sp->timecnt; 1.555 + ++i; 1.556 + } 1.557 + sp->ttis[sp->typecnt++] = ts.ttis[0]; 1.558 + sp->ttis[sp->typecnt++] = ts.ttis[1]; 1.559 + } 1.560 + } 1.561 + sp->goback = sp->goahead = FALSE; 1.562 + if (sp->timecnt > 1) { 1.563 + for (i = 1; i < sp->timecnt; ++i) 1.564 + if (typesequiv(sp, sp->types[i], sp->types[0]) && 1.565 + differ_by_repeat(sp->ats[i], sp->ats[0])) { 1.566 + sp->goback = TRUE; 1.567 + break; 1.568 + } 1.569 + for (i = sp->timecnt - 2; i >= 0; --i) 1.570 + if (typesequiv(sp, sp->types[sp->timecnt - 1], 1.571 + sp->types[i]) && 1.572 + differ_by_repeat(sp->ats[sp->timecnt - 1], 1.573 + sp->ats[i])) { 1.574 + sp->goahead = TRUE; 1.575 + break; 1.576 + } 1.577 + } 1.578 + return 0; 1.579 +} 1.580 + 1.581 +static int 1.582 +typesequiv(sp, a, b) 1.583 +const struct state * const sp; 1.584 +const int a; 1.585 +const int b; 1.586 +{ 1.587 + register int result; 1.588 + 1.589 + if (sp == NULL || 1.590 + a < 0 || a >= sp->typecnt || 1.591 + b < 0 || b >= sp->typecnt) 1.592 + result = FALSE; 1.593 + else { 1.594 + register const struct ttinfo * ap = &sp->ttis[a]; 1.595 + register const struct ttinfo * bp = &sp->ttis[b]; 1.596 + result = ap->tt_gmtoff == bp->tt_gmtoff && 1.597 + ap->tt_isdst == bp->tt_isdst && 1.598 + ap->tt_ttisstd == bp->tt_ttisstd && 1.599 + ap->tt_ttisgmt == bp->tt_ttisgmt && 1.600 + strcmp(&sp->chars[ap->tt_abbrind], 1.601 + &sp->chars[bp->tt_abbrind]) == 0; 1.602 + } 1.603 + return result; 1.604 +} 1.605 + 1.606 +static const int mon_lengths[2][MONSPERYEAR] = { 1.607 + { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, 1.608 + { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } 1.609 +}; 1.610 + 1.611 +static const int year_lengths[2] = { 1.612 + DAYSPERNYEAR, DAYSPERLYEAR 1.613 +}; 1.614 + 1.615 +/* 1.616 +** Given a pointer into a time zone string, scan until a character that is not 1.617 +** a valid character in a zone name is found. Return a pointer to that 1.618 +** character. 1.619 +*/ 1.620 + 1.621 +static const char * 1.622 +getzname(strp) 1.623 +register const char * strp; 1.624 +{ 1.625 + register char c; 1.626 + 1.627 + while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' && 1.628 + c != '+') 1.629 + ++strp; 1.630 + return strp; 1.631 +} 1.632 + 1.633 +/* 1.634 +** Given a pointer into an extended time zone string, scan until the ending 1.635 +** delimiter of the zone name is located. Return a pointer to the delimiter. 1.636 +** 1.637 +** As with getzname above, the legal character set is actually quite 1.638 +** restricted, with other characters producing undefined results. 1.639 +** We don't do any checking here; checking is done later in common-case code. 1.640 +*/ 1.641 + 1.642 +static const char * 1.643 +getqzname(register const char *strp, const int delim) 1.644 +{ 1.645 + register int c; 1.646 + 1.647 + while ((c = *strp) != '\0' && c != delim) 1.648 + ++strp; 1.649 + return strp; 1.650 +} 1.651 + 1.652 +/* 1.653 +** Given a pointer into a time zone string, extract a number from that string. 1.654 +** Check that the number is within a specified range; if it is not, return 1.655 +** NULL. 1.656 +** Otherwise, return a pointer to the first character not part of the number. 1.657 +*/ 1.658 + 1.659 +static const char * 1.660 +getnum(strp, nump, min, max) 1.661 +register const char * strp; 1.662 +int * const nump; 1.663 +const int min; 1.664 +const int max; 1.665 +{ 1.666 + register char c; 1.667 + register int num; 1.668 + 1.669 + if (strp == NULL || !is_digit(c = *strp)) 1.670 + return NULL; 1.671 + num = 0; 1.672 + do { 1.673 + num = num * 10 + (c - '0'); 1.674 + if (num > max) 1.675 + return NULL; /* illegal value */ 1.676 + c = *++strp; 1.677 + } while (is_digit(c)); 1.678 + if (num < min) 1.679 + return NULL; /* illegal value */ 1.680 + *nump = num; 1.681 + return strp; 1.682 +} 1.683 + 1.684 +/* 1.685 +** Given a pointer into a time zone string, extract a number of seconds, 1.686 +** in hh[:mm[:ss]] form, from the string. 1.687 +** If any error occurs, return NULL. 1.688 +** Otherwise, return a pointer to the first character not part of the number 1.689 +** of seconds. 1.690 +*/ 1.691 + 1.692 +static const char * 1.693 +getsecs(strp, secsp) 1.694 +register const char * strp; 1.695 +long * const secsp; 1.696 +{ 1.697 + int num; 1.698 + 1.699 + /* 1.700 + ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like 1.701 + ** "M10.4.6/26", which does not conform to Posix, 1.702 + ** but which specifies the equivalent of 1.703 + ** ``02:00 on the first Sunday on or after 23 Oct''. 1.704 + */ 1.705 + strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1); 1.706 + if (strp == NULL) 1.707 + return NULL; 1.708 + *secsp = num * (long) SECSPERHOUR; 1.709 + if (*strp == ':') { 1.710 + ++strp; 1.711 + strp = getnum(strp, &num, 0, MINSPERHOUR - 1); 1.712 + if (strp == NULL) 1.713 + return NULL; 1.714 + *secsp += num * SECSPERMIN; 1.715 + if (*strp == ':') { 1.716 + ++strp; 1.717 + /* `SECSPERMIN' allows for leap seconds. */ 1.718 + strp = getnum(strp, &num, 0, SECSPERMIN); 1.719 + if (strp == NULL) 1.720 + return NULL; 1.721 + *secsp += num; 1.722 + } 1.723 + } 1.724 + return strp; 1.725 +} 1.726 + 1.727 +/* 1.728 +** Given a pointer into a time zone string, extract an offset, in 1.729 +** [+-]hh[:mm[:ss]] form, from the string. 1.730 +** If any error occurs, return NULL. 1.731 +** Otherwise, return a pointer to the first character not part of the time. 1.732 +*/ 1.733 + 1.734 +static const char * 1.735 +getoffset(strp, offsetp) 1.736 +register const char * strp; 1.737 +long * const offsetp; 1.738 +{ 1.739 + register int neg = 0; 1.740 + 1.741 + if (*strp == '-') { 1.742 + neg = 1; 1.743 + ++strp; 1.744 + } else if (*strp == '+') 1.745 + ++strp; 1.746 + strp = getsecs(strp, offsetp); 1.747 + if (strp == NULL) 1.748 + return NULL; /* illegal time */ 1.749 + if (neg) 1.750 + *offsetp = -*offsetp; 1.751 + return strp; 1.752 +} 1.753 + 1.754 +/* 1.755 +** Given a pointer into a time zone string, extract a rule in the form 1.756 +** date[/time]. See POSIX section 8 for the format of "date" and "time". 1.757 +** If a valid rule is not found, return NULL. 1.758 +** Otherwise, return a pointer to the first character not part of the rule. 1.759 +*/ 1.760 + 1.761 +static const char * 1.762 +getrule(strp, rulep) 1.763 +const char * strp; 1.764 +register struct rule * const rulep; 1.765 +{ 1.766 + if (*strp == 'J') { 1.767 + /* 1.768 + ** Julian day. 1.769 + */ 1.770 + rulep->r_type = JULIAN_DAY; 1.771 + ++strp; 1.772 + strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR); 1.773 + } else if (*strp == 'M') { 1.774 + /* 1.775 + ** Month, week, day. 1.776 + */ 1.777 + rulep->r_type = MONTH_NTH_DAY_OF_WEEK; 1.778 + ++strp; 1.779 + strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR); 1.780 + if (strp == NULL) 1.781 + return NULL; 1.782 + if (*strp++ != '.') 1.783 + return NULL; 1.784 + strp = getnum(strp, &rulep->r_week, 1, 5); 1.785 + if (strp == NULL) 1.786 + return NULL; 1.787 + if (*strp++ != '.') 1.788 + return NULL; 1.789 + strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1); 1.790 + } else if (is_digit(*strp)) { 1.791 + /* 1.792 + ** Day of year. 1.793 + */ 1.794 + rulep->r_type = DAY_OF_YEAR; 1.795 + strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1); 1.796 + } else return NULL; /* invalid format */ 1.797 + if (strp == NULL) 1.798 + return NULL; 1.799 + if (*strp == '/') { 1.800 + /* 1.801 + ** Time specified. 1.802 + */ 1.803 + ++strp; 1.804 + strp = getsecs(strp, &rulep->r_time); 1.805 + } else rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */ 1.806 + return strp; 1.807 +} 1.808 + 1.809 +/* 1.810 +** Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the 1.811 +** year, a rule, and the offset from UTC at the time that rule takes effect, 1.812 +** calculate the Epoch-relative time that rule takes effect. 1.813 +*/ 1.814 + 1.815 +static time_t 1.816 +transtime(janfirst, year, rulep, offset) 1.817 +const time_t janfirst; 1.818 +const int year; 1.819 +register const struct rule * const rulep; 1.820 +const long offset; 1.821 +{ 1.822 + register int leapyear; 1.823 + register time_t value; 1.824 + register int i; 1.825 + int d, m1, yy0, yy1, yy2, dow; 1.826 + 1.827 + INITIALIZE(value); 1.828 + leapyear = isleap(year); 1.829 + switch (rulep->r_type) { 1.830 + 1.831 + case JULIAN_DAY: 1.832 + /* 1.833 + ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap 1.834 + ** years. 1.835 + ** In non-leap years, or if the day number is 59 or less, just 1.836 + ** add SECSPERDAY times the day number-1 to the time of 1.837 + ** January 1, midnight, to get the day. 1.838 + */ 1.839 + value = janfirst + (rulep->r_day - 1) * SECSPERDAY; 1.840 + if (leapyear && rulep->r_day >= 60) 1.841 + value += SECSPERDAY; 1.842 + break; 1.843 + 1.844 + case DAY_OF_YEAR: 1.845 + /* 1.846 + ** n - day of year. 1.847 + ** Just add SECSPERDAY times the day number to the time of 1.848 + ** January 1, midnight, to get the day. 1.849 + */ 1.850 + value = janfirst + rulep->r_day * SECSPERDAY; 1.851 + break; 1.852 + 1.853 + case MONTH_NTH_DAY_OF_WEEK: 1.854 + /* 1.855 + ** Mm.n.d - nth "dth day" of month m. 1.856 + */ 1.857 + value = janfirst; 1.858 + for (i = 0; i < rulep->r_mon - 1; ++i) 1.859 + value += mon_lengths[leapyear][i] * SECSPERDAY; 1.860 + 1.861 + /* 1.862 + ** Use Zeller's Congruence to get day-of-week of first day of 1.863 + ** month. 1.864 + */ 1.865 + m1 = (rulep->r_mon + 9) % 12 + 1; 1.866 + yy0 = (rulep->r_mon <= 2) ? (year - 1) : year; 1.867 + yy1 = yy0 / 100; 1.868 + yy2 = yy0 % 100; 1.869 + dow = ((26 * m1 - 2) / 10 + 1.870 + 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7; 1.871 + if (dow < 0) 1.872 + dow += DAYSPERWEEK; 1.873 + 1.874 + /* 1.875 + ** "dow" is the day-of-week of the first day of the month. Get 1.876 + ** the day-of-month (zero-origin) of the first "dow" day of the 1.877 + ** month. 1.878 + */ 1.879 + d = rulep->r_day - dow; 1.880 + if (d < 0) 1.881 + d += DAYSPERWEEK; 1.882 + for (i = 1; i < rulep->r_week; ++i) { 1.883 + if (d + DAYSPERWEEK >= 1.884 + mon_lengths[leapyear][rulep->r_mon - 1]) 1.885 + break; 1.886 + d += DAYSPERWEEK; 1.887 + } 1.888 + 1.889 + /* 1.890 + ** "d" is the day-of-month (zero-origin) of the day we want. 1.891 + */ 1.892 + value += d * SECSPERDAY; 1.893 + break; 1.894 + } 1.895 + 1.896 + /* 1.897 + ** "value" is the Epoch-relative time of 00:00:00 UTC on the day in 1.898 + ** question. To get the Epoch-relative time of the specified local 1.899 + ** time on that day, add the transition time and the current offset 1.900 + ** from UTC. 1.901 + */ 1.902 + return value + rulep->r_time + offset; 1.903 +} 1.904 + 1.905 +/* 1.906 +** Given a POSIX section 8-style TZ string, fill in the rule tables as 1.907 +** appropriate. 1.908 +*/ 1.909 + 1.910 +static int 1.911 +tzparse(name, sp, lastditch) 1.912 +const char * name; 1.913 +register struct state * const sp; 1.914 +const int lastditch; 1.915 +{ 1.916 + const char * stdname; 1.917 + const char * dstname; 1.918 + size_t stdlen; 1.919 + size_t dstlen; 1.920 + long stdoffset; 1.921 + long dstoffset; 1.922 + register time_t * atp; 1.923 + register unsigned char * typep; 1.924 + register char * cp; 1.925 + register int load_result; 1.926 + 1.927 + INITIALIZE(dstname); 1.928 + stdname = name; 1.929 + if (lastditch) { 1.930 + stdlen = strlen(name); /* length of standard zone name */ 1.931 + name += stdlen; 1.932 + if (stdlen >= sizeof sp->chars) 1.933 + stdlen = (sizeof sp->chars) - 1; 1.934 + stdoffset = 0; 1.935 + } else { 1.936 + if (*name == '<') { 1.937 + name++; 1.938 + stdname = name; 1.939 + name = getqzname(name, '>'); 1.940 + if (*name != '>') 1.941 + return (-1); 1.942 + stdlen = name - stdname; 1.943 + name++; 1.944 + } else { 1.945 + name = getzname(name); 1.946 + stdlen = name - stdname; 1.947 + } 1.948 + if (*name == '\0') 1.949 + return -1; 1.950 + name = getoffset(name, &stdoffset); 1.951 + if (name == NULL) 1.952 + return -1; 1.953 + } 1.954 + load_result = tzload(TZDEFRULES, sp, FALSE); 1.955 + if (load_result != 0) 1.956 + sp->leapcnt = 0; /* so, we're off a little */ 1.957 + if (*name != '\0') { 1.958 + if (*name == '<') { 1.959 + dstname = ++name; 1.960 + name = getqzname(name, '>'); 1.961 + if (*name != '>') 1.962 + return -1; 1.963 + dstlen = name - dstname; 1.964 + name++; 1.965 + } else { 1.966 + dstname = name; 1.967 + name = getzname(name); 1.968 + dstlen = name - dstname; /* length of DST zone name */ 1.969 + } 1.970 + if (*name != '\0' && *name != ',' && *name != ';') { 1.971 + name = getoffset(name, &dstoffset); 1.972 + if (name == NULL) 1.973 + return -1; 1.974 + } else dstoffset = stdoffset - SECSPERHOUR; 1.975 + if (*name == '\0' && load_result != 0) 1.976 + name = TZDEFRULESTRING; 1.977 + if (*name == ',' || *name == ';') { 1.978 + struct rule start; 1.979 + struct rule end; 1.980 + register int year; 1.981 + register time_t janfirst; 1.982 + time_t starttime; 1.983 + time_t endtime; 1.984 + 1.985 + ++name; 1.986 + if ((name = getrule(name, &start)) == NULL) 1.987 + return -1; 1.988 + if (*name++ != ',') 1.989 + return -1; 1.990 + if ((name = getrule(name, &end)) == NULL) 1.991 + return -1; 1.992 + if (*name != '\0') 1.993 + return -1; 1.994 + sp->typecnt = 2; /* standard time and DST */ 1.995 + /* 1.996 + ** Two transitions per year, from EPOCH_YEAR forward. 1.997 + */ 1.998 + sp->ttis[0].tt_gmtoff = -dstoffset; 1.999 + sp->ttis[0].tt_isdst = 1; 1.1000 + sp->ttis[0].tt_abbrind = stdlen + 1; 1.1001 + sp->ttis[1].tt_gmtoff = -stdoffset; 1.1002 + sp->ttis[1].tt_isdst = 0; 1.1003 + sp->ttis[1].tt_abbrind = 0; 1.1004 + atp = sp->ats; 1.1005 + typep = sp->types; 1.1006 + janfirst = 0; 1.1007 + sp->timecnt = 0; 1.1008 + for (year = EPOCH_YEAR; 1.1009 + sp->timecnt + 2 <= TZ_MAX_TIMES; 1.1010 + ++year) { 1.1011 + time_t newfirst; 1.1012 + 1.1013 + starttime = transtime(janfirst, year, &start, 1.1014 + stdoffset); 1.1015 + endtime = transtime(janfirst, year, &end, 1.1016 + dstoffset); 1.1017 + if (starttime > endtime) { 1.1018 + *atp++ = endtime; 1.1019 + *typep++ = 1; /* DST ends */ 1.1020 + *atp++ = starttime; 1.1021 + *typep++ = 0; /* DST begins */ 1.1022 + } else { 1.1023 + *atp++ = starttime; 1.1024 + *typep++ = 0; /* DST begins */ 1.1025 + *atp++ = endtime; 1.1026 + *typep++ = 1; /* DST ends */ 1.1027 + } 1.1028 + sp->timecnt += 2; 1.1029 + newfirst = janfirst; 1.1030 + newfirst += year_lengths[isleap(year)] * 1.1031 + SECSPERDAY; 1.1032 + if (newfirst <= janfirst) 1.1033 + break; 1.1034 + janfirst = newfirst; 1.1035 + } 1.1036 + } else { 1.1037 + register long theirstdoffset; 1.1038 + register long theirdstoffset; 1.1039 + register long theiroffset; 1.1040 + register int isdst; 1.1041 + register int i; 1.1042 + register int j; 1.1043 + 1.1044 + if (*name != '\0') 1.1045 + return -1; 1.1046 + /* 1.1047 + ** Initial values of theirstdoffset and theirdstoffset. 1.1048 + */ 1.1049 + theirstdoffset = 0; 1.1050 + for (i = 0; i < sp->timecnt; ++i) { 1.1051 + j = sp->types[i]; 1.1052 + if (!sp->ttis[j].tt_isdst) { 1.1053 + theirstdoffset = 1.1054 + -sp->ttis[j].tt_gmtoff; 1.1055 + break; 1.1056 + } 1.1057 + } 1.1058 + theirdstoffset = 0; 1.1059 + for (i = 0; i < sp->timecnt; ++i) { 1.1060 + j = sp->types[i]; 1.1061 + if (sp->ttis[j].tt_isdst) { 1.1062 + theirdstoffset = 1.1063 + -sp->ttis[j].tt_gmtoff; 1.1064 + break; 1.1065 + } 1.1066 + } 1.1067 + /* 1.1068 + ** Initially we're assumed to be in standard time. 1.1069 + */ 1.1070 + isdst = FALSE; 1.1071 + theiroffset = theirstdoffset; 1.1072 + /* 1.1073 + ** Now juggle transition times and types 1.1074 + ** tracking offsets as you do. 1.1075 + */ 1.1076 + for (i = 0; i < sp->timecnt; ++i) { 1.1077 + j = sp->types[i]; 1.1078 + sp->types[i] = sp->ttis[j].tt_isdst; 1.1079 + if (sp->ttis[j].tt_ttisgmt) { 1.1080 + /* No adjustment to transition time */ 1.1081 + } else { 1.1082 + /* 1.1083 + ** If summer time is in effect, and the 1.1084 + ** transition time was not specified as 1.1085 + ** standard time, add the summer time 1.1086 + ** offset to the transition time; 1.1087 + ** otherwise, add the standard time 1.1088 + ** offset to the transition time. 1.1089 + */ 1.1090 + /* 1.1091 + ** Transitions from DST to DDST 1.1092 + ** will effectively disappear since 1.1093 + ** POSIX provides for only one DST 1.1094 + ** offset. 1.1095 + */ 1.1096 + if (isdst && !sp->ttis[j].tt_ttisstd) { 1.1097 + sp->ats[i] += dstoffset - 1.1098 + theirdstoffset; 1.1099 + } else { 1.1100 + sp->ats[i] += stdoffset - 1.1101 + theirstdoffset; 1.1102 + } 1.1103 + } 1.1104 + theiroffset = -sp->ttis[j].tt_gmtoff; 1.1105 + if (sp->ttis[j].tt_isdst) 1.1106 + theirdstoffset = theiroffset; 1.1107 + else theirstdoffset = theiroffset; 1.1108 + } 1.1109 + /* 1.1110 + ** Finally, fill in ttis. 1.1111 + ** ttisstd and ttisgmt need not be handled. 1.1112 + */ 1.1113 + sp->ttis[0].tt_gmtoff = -stdoffset; 1.1114 + sp->ttis[0].tt_isdst = FALSE; 1.1115 + sp->ttis[0].tt_abbrind = 0; 1.1116 + sp->ttis[1].tt_gmtoff = -dstoffset; 1.1117 + sp->ttis[1].tt_isdst = TRUE; 1.1118 + sp->ttis[1].tt_abbrind = stdlen + 1; 1.1119 + sp->typecnt = 2; 1.1120 + } 1.1121 + } else { 1.1122 + dstlen = 0; 1.1123 + sp->typecnt = 1; /* only standard time */ 1.1124 + sp->timecnt = 0; 1.1125 + sp->ttis[0].tt_gmtoff = -stdoffset; 1.1126 + sp->ttis[0].tt_isdst = 0; 1.1127 + sp->ttis[0].tt_abbrind = 0; 1.1128 + } 1.1129 + sp->charcnt = stdlen + 1; 1.1130 + if (dstlen != 0) 1.1131 + sp->charcnt += dstlen + 1; 1.1132 + if ((size_t) sp->charcnt > sizeof sp->chars) 1.1133 + return -1; 1.1134 + cp = sp->chars; 1.1135 + (void) strncpy(cp, stdname, stdlen); 1.1136 + cp += stdlen; 1.1137 + *cp++ = '\0'; 1.1138 + if (dstlen != 0) { 1.1139 + (void) strncpy(cp, dstname, dstlen); 1.1140 + *(cp + dstlen) = '\0'; 1.1141 + } 1.1142 + return 0; 1.1143 +} 1.1144 + 1.1145 +static void 1.1146 +gmtload(sp) 1.1147 +struct state * const sp; 1.1148 +{ 1.1149 + if (tzload(gmt, sp, TRUE) != 0) 1.1150 + (void) tzparse(gmt, sp, TRUE); 1.1151 +} 1.1152 + 1.1153 +#ifndef STD_INSPIRED 1.1154 +/* 1.1155 +** A non-static declaration of tzsetwall in a system header file 1.1156 +** may cause a warning about this upcoming static declaration... 1.1157 +*/ 1.1158 +static 1.1159 +#endif /* !defined STD_INSPIRED */ 1.1160 +void 1.1161 +tzsetwall(void) 1.1162 +{ 1.1163 + if (lcl_is_set < 0) 1.1164 + return; 1.1165 + lcl_is_set = -1; 1.1166 + 1.1167 +#ifdef ALL_STATE 1.1168 + if (lclptr == NULL) { 1.1169 + lclptr = (struct state *) malloc(sizeof *lclptr); 1.1170 + if (lclptr == NULL) { 1.1171 + settzname(); /* all we can do */ 1.1172 + return; 1.1173 + } 1.1174 + } 1.1175 +#endif /* defined ALL_STATE */ 1.1176 + if (tzload((char *) NULL, lclptr, TRUE) != 0) 1.1177 + gmtload(lclptr); 1.1178 + settzname(); 1.1179 +} 1.1180 + 1.1181 +void 1.1182 +tzset(void) 1.1183 +{ 1.1184 + register const char * name; 1.1185 + 1.1186 + name = getenv("TZ"); 1.1187 + if (name == NULL) { 1.1188 + tzsetwall(); 1.1189 + return; 1.1190 + } 1.1191 + 1.1192 + if (lcl_is_set > 0 && strcmp(lcl_TZname, name) == 0) 1.1193 + return; 1.1194 + lcl_is_set = strlen(name) < sizeof lcl_TZname; 1.1195 + if (lcl_is_set) 1.1196 + (void) strcpy(lcl_TZname, name); 1.1197 + 1.1198 +#ifdef ALL_STATE 1.1199 + if (lclptr == NULL) { 1.1200 + lclptr = (struct state *) malloc(sizeof *lclptr); 1.1201 + if (lclptr == NULL) { 1.1202 + settzname(); /* all we can do */ 1.1203 + return; 1.1204 + } 1.1205 + } 1.1206 +#endif /* defined ALL_STATE */ 1.1207 + if (*name == '\0') { 1.1208 + /* 1.1209 + ** User wants it fast rather than right. 1.1210 + */ 1.1211 + lclptr->leapcnt = 0; /* so, we're off a little */ 1.1212 + lclptr->timecnt = 0; 1.1213 + lclptr->typecnt = 0; 1.1214 + lclptr->ttis[0].tt_isdst = 0; 1.1215 + lclptr->ttis[0].tt_gmtoff = 0; 1.1216 + lclptr->ttis[0].tt_abbrind = 0; 1.1217 + (void) strcpy(lclptr->chars, gmt); 1.1218 + } else if (tzload(name, lclptr, TRUE) != 0) 1.1219 + if (name[0] == ':' || tzparse(name, lclptr, FALSE) != 0) 1.1220 + (void) gmtload(lclptr); 1.1221 + settzname(); 1.1222 +} 1.1223 + 1.1224 +/* 1.1225 +** The easy way to behave "as if no library function calls" localtime 1.1226 +** is to not call it--so we drop its guts into "localsub", which can be 1.1227 +** freely called. (And no, the PANS doesn't require the above behavior-- 1.1228 +** but it *is* desirable.) 1.1229 +** 1.1230 +** The unused offset argument is for the benefit of mktime variants. 1.1231 +*/ 1.1232 + 1.1233 +/*ARGSUSED*/ 1.1234 +static struct tm * 1.1235 +localsub(timep, offset, tmp) 1.1236 +const time_t * const timep; 1.1237 +const long offset; 1.1238 +struct tm * const tmp; 1.1239 +{ 1.1240 + register struct state * sp; 1.1241 + register const struct ttinfo * ttisp; 1.1242 + register int i; 1.1243 + register struct tm * result; 1.1244 + const time_t t = *timep; 1.1245 + 1.1246 + sp = lclptr; 1.1247 +#ifdef ALL_STATE 1.1248 + if (sp == NULL) 1.1249 + return gmtsub(timep, offset, tmp); 1.1250 +#endif /* defined ALL_STATE */ 1.1251 + if ((sp->goback && t < sp->ats[0]) || 1.1252 + (sp->goahead && t > sp->ats[sp->timecnt - 1])) { 1.1253 + time_t newt = t; 1.1254 + register time_t seconds; 1.1255 + register time_t tcycles; 1.1256 + register int_fast64_t icycles; 1.1257 + 1.1258 + if (t < sp->ats[0]) 1.1259 + seconds = sp->ats[0] - t; 1.1260 + else seconds = t - sp->ats[sp->timecnt - 1]; 1.1261 + --seconds; 1.1262 + tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR; 1.1263 + ++tcycles; 1.1264 + icycles = tcycles; 1.1265 + if (tcycles - icycles >= 1 || icycles - tcycles >= 1) 1.1266 + return NULL; 1.1267 + seconds = icycles; 1.1268 + seconds *= YEARSPERREPEAT; 1.1269 + seconds *= AVGSECSPERYEAR; 1.1270 + if (t < sp->ats[0]) 1.1271 + newt += seconds; 1.1272 + else newt -= seconds; 1.1273 + if (newt < sp->ats[0] || 1.1274 + newt > sp->ats[sp->timecnt - 1]) 1.1275 + return NULL; /* "cannot happen" */ 1.1276 + result = localsub(&newt, offset, tmp); 1.1277 + if (result == tmp) { 1.1278 + register time_t newy; 1.1279 + 1.1280 + newy = tmp->tm_year; 1.1281 + if (t < sp->ats[0]) 1.1282 + newy -= icycles * YEARSPERREPEAT; 1.1283 + else newy += icycles * YEARSPERREPEAT; 1.1284 + tmp->tm_year = newy; 1.1285 + if (tmp->tm_year != newy) 1.1286 + return NULL; 1.1287 + } 1.1288 + return result; 1.1289 + } 1.1290 + if (sp->timecnt == 0 || t < sp->ats[0]) { 1.1291 + i = 0; 1.1292 + while (sp->ttis[i].tt_isdst) 1.1293 + if (++i >= sp->typecnt) { 1.1294 + i = 0; 1.1295 + break; 1.1296 + } 1.1297 + } else { 1.1298 + register int lo = 1; 1.1299 + register int hi = sp->timecnt; 1.1300 + 1.1301 + while (lo < hi) { 1.1302 + register int mid = (lo + hi) >> 1; 1.1303 + 1.1304 + if (t < sp->ats[mid]) 1.1305 + hi = mid; 1.1306 + else lo = mid + 1; 1.1307 + } 1.1308 + i = (int) sp->types[lo - 1]; 1.1309 + } 1.1310 + ttisp = &sp->ttis[i]; 1.1311 + /* 1.1312 + ** To get (wrong) behavior that's compatible with System V Release 2.0 1.1313 + ** you'd replace the statement below with 1.1314 + ** t += ttisp->tt_gmtoff; 1.1315 + ** timesub(&t, 0L, sp, tmp); 1.1316 + */ 1.1317 + result = timesub(&t, ttisp->tt_gmtoff, sp, tmp); 1.1318 + tmp->tm_isdst = ttisp->tt_isdst; 1.1319 + tzname[tmp->tm_isdst] = &sp->chars[ttisp->tt_abbrind]; 1.1320 +#ifdef TM_ZONE 1.1321 + tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind]; 1.1322 +#endif /* defined TM_ZONE */ 1.1323 + return result; 1.1324 +} 1.1325 + 1.1326 +struct tm * 1.1327 +localtime(timep) 1.1328 +const time_t * const timep; 1.1329 +{ 1.1330 + tzset(); 1.1331 + return localsub(timep, 0L, &tm); 1.1332 +} 1.1333 + 1.1334 +/* 1.1335 +** Re-entrant version of localtime. 1.1336 +*/ 1.1337 + 1.1338 +struct tm * 1.1339 +localtime_r(timep, tmp) 1.1340 +const time_t * const timep; 1.1341 +struct tm * tmp; 1.1342 +{ 1.1343 + return localsub(timep, 0L, tmp); 1.1344 +} 1.1345 + 1.1346 +/* 1.1347 +** gmtsub is to gmtime as localsub is to localtime. 1.1348 +*/ 1.1349 + 1.1350 +static struct tm * 1.1351 +gmtsub(timep, offset, tmp) 1.1352 +const time_t * const timep; 1.1353 +const long offset; 1.1354 +struct tm * const tmp; 1.1355 +{ 1.1356 + register struct tm * result; 1.1357 + 1.1358 + if (!gmt_is_set) { 1.1359 + gmt_is_set = TRUE; 1.1360 +#ifdef ALL_STATE 1.1361 + gmtptr = (struct state *) malloc(sizeof *gmtptr); 1.1362 + if (gmtptr != NULL) 1.1363 +#endif /* defined ALL_STATE */ 1.1364 + gmtload(gmtptr); 1.1365 + } 1.1366 + result = timesub(timep, offset, gmtptr, tmp); 1.1367 +#ifdef TM_ZONE 1.1368 + /* 1.1369 + ** Could get fancy here and deliver something such as 1.1370 + ** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero, 1.1371 + ** but this is no time for a treasure hunt. 1.1372 + */ 1.1373 + if (offset != 0) 1.1374 + tmp->TM_ZONE = wildabbr; 1.1375 + else { 1.1376 +#ifdef ALL_STATE 1.1377 + if (gmtptr == NULL) 1.1378 + tmp->TM_ZONE = gmt; 1.1379 + else tmp->TM_ZONE = gmtptr->chars; 1.1380 +#endif /* defined ALL_STATE */ 1.1381 +#ifndef ALL_STATE 1.1382 + tmp->TM_ZONE = gmtptr->chars; 1.1383 +#endif /* State Farm */ 1.1384 + } 1.1385 +#endif /* defined TM_ZONE */ 1.1386 + return result; 1.1387 +} 1.1388 + 1.1389 +struct tm * 1.1390 +gmtime(timep) 1.1391 +const time_t * const timep; 1.1392 +{ 1.1393 + return gmtsub(timep, 0L, &tm); 1.1394 +} 1.1395 + 1.1396 +/* 1.1397 +* Re-entrant version of gmtime. 1.1398 +*/ 1.1399 + 1.1400 +struct tm * 1.1401 +gmtime_r(timep, tmp) 1.1402 +const time_t * const timep; 1.1403 +struct tm * tmp; 1.1404 +{ 1.1405 + return gmtsub(timep, 0L, tmp); 1.1406 +} 1.1407 + 1.1408 +#ifdef STD_INSPIRED 1.1409 + 1.1410 +struct tm * 1.1411 +offtime(timep, offset) 1.1412 +const time_t * const timep; 1.1413 +const long offset; 1.1414 +{ 1.1415 + return gmtsub(timep, offset, &tm); 1.1416 +} 1.1417 + 1.1418 +#endif /* defined STD_INSPIRED */ 1.1419 + 1.1420 +/* 1.1421 +** Return the number of leap years through the end of the given year 1.1422 +** where, to make the math easy, the answer for year zero is defined as zero. 1.1423 +*/ 1.1424 + 1.1425 +static int 1.1426 +leaps_thru_end_of(y) 1.1427 +register const int y; 1.1428 +{ 1.1429 + return (y >= 0) ? (y / 4 - y / 100 + y / 400) : 1.1430 + -(leaps_thru_end_of(-(y + 1)) + 1); 1.1431 +} 1.1432 + 1.1433 +static struct tm * 1.1434 +timesub(timep, offset, sp, tmp) 1.1435 +const time_t * const timep; 1.1436 +const long offset; 1.1437 +register const struct state * const sp; 1.1438 +register struct tm * const tmp; 1.1439 +{ 1.1440 + register const struct lsinfo * lp; 1.1441 + register time_t tdays; 1.1442 + register int idays; /* unsigned would be so 2003 */ 1.1443 + register long rem; 1.1444 + int y; 1.1445 + register const int * ip; 1.1446 + register long corr; 1.1447 + register int hit; 1.1448 + register int i; 1.1449 + 1.1450 + corr = 0; 1.1451 + hit = 0; 1.1452 +#ifdef ALL_STATE 1.1453 + i = (sp == NULL) ? 0 : sp->leapcnt; 1.1454 +#endif /* defined ALL_STATE */ 1.1455 +#ifndef ALL_STATE 1.1456 + i = sp->leapcnt; 1.1457 +#endif /* State Farm */ 1.1458 + while (--i >= 0) { 1.1459 + lp = &sp->lsis[i]; 1.1460 + if (*timep >= lp->ls_trans) { 1.1461 + if (*timep == lp->ls_trans) { 1.1462 + hit = ((i == 0 && lp->ls_corr > 0) || 1.1463 + lp->ls_corr > sp->lsis[i - 1].ls_corr); 1.1464 + if (hit) 1.1465 + while (i > 0 && 1.1466 + sp->lsis[i].ls_trans == 1.1467 + sp->lsis[i - 1].ls_trans + 1 && 1.1468 + sp->lsis[i].ls_corr == 1.1469 + sp->lsis[i - 1].ls_corr + 1) { 1.1470 + ++hit; 1.1471 + --i; 1.1472 + } 1.1473 + } 1.1474 + corr = lp->ls_corr; 1.1475 + break; 1.1476 + } 1.1477 + } 1.1478 + y = EPOCH_YEAR; 1.1479 + tdays = *timep / SECSPERDAY; 1.1480 + rem = *timep - tdays * SECSPERDAY; 1.1481 + while (tdays < 0 || tdays >= year_lengths[isleap(y)]) { 1.1482 + int newy; 1.1483 + register time_t tdelta; 1.1484 + register int idelta; 1.1485 + register int leapdays; 1.1486 + 1.1487 + tdelta = tdays / DAYSPERLYEAR; 1.1488 + idelta = tdelta; 1.1489 + if (tdelta - idelta >= 1 || idelta - tdelta >= 1) 1.1490 + return NULL; 1.1491 + if (idelta == 0) 1.1492 + idelta = (tdays < 0) ? -1 : 1; 1.1493 + newy = y; 1.1494 + if (increment_overflow(&newy, idelta)) 1.1495 + return NULL; 1.1496 + leapdays = leaps_thru_end_of(newy - 1) - 1.1497 + leaps_thru_end_of(y - 1); 1.1498 + tdays -= ((time_t) newy - y) * DAYSPERNYEAR; 1.1499 + tdays -= leapdays; 1.1500 + y = newy; 1.1501 + } 1.1502 + { 1.1503 + register long seconds; 1.1504 + 1.1505 + seconds = tdays * SECSPERDAY + 0.5; 1.1506 + tdays = seconds / SECSPERDAY; 1.1507 + rem += seconds - tdays * SECSPERDAY; 1.1508 + } 1.1509 + /* 1.1510 + ** Given the range, we can now fearlessly cast... 1.1511 + */ 1.1512 + idays = tdays; 1.1513 + rem += offset - corr; 1.1514 + while (rem < 0) { 1.1515 + rem += SECSPERDAY; 1.1516 + --idays; 1.1517 + } 1.1518 + while (rem >= SECSPERDAY) { 1.1519 + rem -= SECSPERDAY; 1.1520 + ++idays; 1.1521 + } 1.1522 + while (idays < 0) { 1.1523 + if (increment_overflow(&y, -1)) 1.1524 + return NULL; 1.1525 + idays += year_lengths[isleap(y)]; 1.1526 + } 1.1527 + while (idays >= year_lengths[isleap(y)]) { 1.1528 + idays -= year_lengths[isleap(y)]; 1.1529 + if (increment_overflow(&y, 1)) 1.1530 + return NULL; 1.1531 + } 1.1532 + tmp->tm_year = y; 1.1533 + if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE)) 1.1534 + return NULL; 1.1535 + tmp->tm_yday = idays; 1.1536 + /* 1.1537 + ** The "extra" mods below avoid overflow problems. 1.1538 + */ 1.1539 + tmp->tm_wday = EPOCH_WDAY + 1.1540 + ((y - EPOCH_YEAR) % DAYSPERWEEK) * 1.1541 + (DAYSPERNYEAR % DAYSPERWEEK) + 1.1542 + leaps_thru_end_of(y - 1) - 1.1543 + leaps_thru_end_of(EPOCH_YEAR - 1) + 1.1544 + idays; 1.1545 + tmp->tm_wday %= DAYSPERWEEK; 1.1546 + if (tmp->tm_wday < 0) 1.1547 + tmp->tm_wday += DAYSPERWEEK; 1.1548 + tmp->tm_hour = (int) (rem / SECSPERHOUR); 1.1549 + rem %= SECSPERHOUR; 1.1550 + tmp->tm_min = (int) (rem / SECSPERMIN); 1.1551 + /* 1.1552 + ** A positive leap second requires a special 1.1553 + ** representation. This uses "... ??:59:60" et seq. 1.1554 + */ 1.1555 + tmp->tm_sec = (int) (rem % SECSPERMIN) + hit; 1.1556 + ip = mon_lengths[isleap(y)]; 1.1557 + for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon)) 1.1558 + idays -= ip[tmp->tm_mon]; 1.1559 + tmp->tm_mday = (int) (idays + 1); 1.1560 + tmp->tm_isdst = 0; 1.1561 +#ifdef TM_GMTOFF 1.1562 + tmp->TM_GMTOFF = offset; 1.1563 +#endif /* defined TM_GMTOFF */ 1.1564 + return tmp; 1.1565 +} 1.1566 + 1.1567 +char * 1.1568 +ctime(timep) 1.1569 +const time_t * const timep; 1.1570 +{ 1.1571 +/* 1.1572 +** Section 4.12.3.2 of X3.159-1989 requires that 1.1573 +** The ctime function converts the calendar time pointed to by timer 1.1574 +** to local time in the form of a string. It is equivalent to 1.1575 +** asctime(localtime(timer)) 1.1576 +*/ 1.1577 + return asctime(localtime(timep)); 1.1578 +} 1.1579 + 1.1580 +char * 1.1581 +ctime_r(timep, buf) 1.1582 +const time_t * const timep; 1.1583 +char * buf; 1.1584 +{ 1.1585 + struct tm mytm; 1.1586 + 1.1587 + return asctime_r(localtime_r(timep, &mytm), buf); 1.1588 +} 1.1589 + 1.1590 +/* 1.1591 +** Adapted from code provided by Robert Elz, who writes: 1.1592 +** The "best" way to do mktime I think is based on an idea of Bob 1.1593 +** Kridle's (so its said...) from a long time ago. 1.1594 +** It does a binary search of the time_t space. Since time_t's are 1.1595 +** just 32 bits, its a max of 32 iterations (even at 64 bits it 1.1596 +** would still be very reasonable). 1.1597 +*/ 1.1598 + 1.1599 +#ifndef WRONG 1.1600 +#define WRONG (-1) 1.1601 +#endif /* !defined WRONG */ 1.1602 + 1.1603 +/* 1.1604 +** Simplified normalize logic courtesy Paul Eggert. 1.1605 +*/ 1.1606 + 1.1607 +static int 1.1608 +increment_overflow(number, delta) 1.1609 +int * number; 1.1610 +int delta; 1.1611 +{ 1.1612 + int number0; 1.1613 + 1.1614 + number0 = *number; 1.1615 + *number += delta; 1.1616 + return (*number < number0) != (delta < 0); 1.1617 +} 1.1618 + 1.1619 +static int 1.1620 +long_increment_overflow(number, delta) 1.1621 +long * number; 1.1622 +int delta; 1.1623 +{ 1.1624 + long number0; 1.1625 + 1.1626 + number0 = *number; 1.1627 + *number += delta; 1.1628 + return (*number < number0) != (delta < 0); 1.1629 +} 1.1630 + 1.1631 +static int 1.1632 +normalize_overflow(tensptr, unitsptr, base) 1.1633 +int * const tensptr; 1.1634 +int * const unitsptr; 1.1635 +const int base; 1.1636 +{ 1.1637 + register int tensdelta; 1.1638 + 1.1639 + tensdelta = (*unitsptr >= 0) ? 1.1640 + (*unitsptr / base) : 1.1641 + (-1 - (-1 - *unitsptr) / base); 1.1642 + *unitsptr -= tensdelta * base; 1.1643 + return increment_overflow(tensptr, tensdelta); 1.1644 +} 1.1645 + 1.1646 +static int 1.1647 +long_normalize_overflow(tensptr, unitsptr, base) 1.1648 +long * const tensptr; 1.1649 +int * const unitsptr; 1.1650 +const int base; 1.1651 +{ 1.1652 + register int tensdelta; 1.1653 + 1.1654 + tensdelta = (*unitsptr >= 0) ? 1.1655 + (*unitsptr / base) : 1.1656 + (-1 - (-1 - *unitsptr) / base); 1.1657 + *unitsptr -= tensdelta * base; 1.1658 + return long_increment_overflow(tensptr, tensdelta); 1.1659 +} 1.1660 + 1.1661 +static int 1.1662 +tmcomp(atmp, btmp) 1.1663 +register const struct tm * const atmp; 1.1664 +register const struct tm * const btmp; 1.1665 +{ 1.1666 + register int result; 1.1667 + 1.1668 + if ((result = (atmp->tm_year - btmp->tm_year)) == 0 && 1.1669 + (result = (atmp->tm_mon - btmp->tm_mon)) == 0 && 1.1670 + (result = (atmp->tm_mday - btmp->tm_mday)) == 0 && 1.1671 + (result = (atmp->tm_hour - btmp->tm_hour)) == 0 && 1.1672 + (result = (atmp->tm_min - btmp->tm_min)) == 0) 1.1673 + result = atmp->tm_sec - btmp->tm_sec; 1.1674 + return result; 1.1675 +} 1.1676 + 1.1677 +static time_t 1.1678 +time2sub(tmp, funcp, offset, okayp, do_norm_secs) 1.1679 +struct tm * const tmp; 1.1680 +struct tm * (* const funcp)(const time_t*, long, struct tm*); 1.1681 +const long offset; 1.1682 +int * const okayp; 1.1683 +const int do_norm_secs; 1.1684 +{ 1.1685 + register const struct state * sp; 1.1686 + register int dir; 1.1687 + register int i, j; 1.1688 + register int saved_seconds; 1.1689 + register long li; 1.1690 + register time_t lo; 1.1691 + register time_t hi; 1.1692 + long y; 1.1693 + time_t newt; 1.1694 + time_t t; 1.1695 + struct tm yourtm, mytm; 1.1696 + 1.1697 + *okayp = FALSE; 1.1698 + yourtm = *tmp; 1.1699 + if (do_norm_secs) { 1.1700 + if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec, 1.1701 + SECSPERMIN)) 1.1702 + return WRONG; 1.1703 + } 1.1704 + if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR)) 1.1705 + return WRONG; 1.1706 + if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY)) 1.1707 + return WRONG; 1.1708 + y = yourtm.tm_year; 1.1709 + if (long_normalize_overflow(&y, &yourtm.tm_mon, MONSPERYEAR)) 1.1710 + return WRONG; 1.1711 + /* 1.1712 + ** Turn y into an actual year number for now. 1.1713 + ** It is converted back to an offset from TM_YEAR_BASE later. 1.1714 + */ 1.1715 + if (long_increment_overflow(&y, TM_YEAR_BASE)) 1.1716 + return WRONG; 1.1717 + while (yourtm.tm_mday <= 0) { 1.1718 + if (long_increment_overflow(&y, -1)) 1.1719 + return WRONG; 1.1720 + li = y + (1 < yourtm.tm_mon); 1.1721 + yourtm.tm_mday += year_lengths[isleap(li)]; 1.1722 + } 1.1723 + while (yourtm.tm_mday > DAYSPERLYEAR) { 1.1724 + li = y + (1 < yourtm.tm_mon); 1.1725 + yourtm.tm_mday -= year_lengths[isleap(li)]; 1.1726 + if (long_increment_overflow(&y, 1)) 1.1727 + return WRONG; 1.1728 + } 1.1729 + for ( ; ; ) { 1.1730 + i = mon_lengths[isleap(y)][yourtm.tm_mon]; 1.1731 + if (yourtm.tm_mday <= i) 1.1732 + break; 1.1733 + yourtm.tm_mday -= i; 1.1734 + if (++yourtm.tm_mon >= MONSPERYEAR) { 1.1735 + yourtm.tm_mon = 0; 1.1736 + if (long_increment_overflow(&y, 1)) 1.1737 + return WRONG; 1.1738 + } 1.1739 + } 1.1740 + if (long_increment_overflow(&y, -TM_YEAR_BASE)) 1.1741 + return WRONG; 1.1742 + yourtm.tm_year = y; 1.1743 + if (yourtm.tm_year != y) 1.1744 + return WRONG; 1.1745 + if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN) 1.1746 + saved_seconds = 0; 1.1747 + else if (y + TM_YEAR_BASE < EPOCH_YEAR) { 1.1748 + /* 1.1749 + ** We can't set tm_sec to 0, because that might push the 1.1750 + ** time below the minimum representable time. 1.1751 + ** Set tm_sec to 59 instead. 1.1752 + ** This assumes that the minimum representable time is 1.1753 + ** not in the same minute that a leap second was deleted from, 1.1754 + ** which is a safer assumption than using 58 would be. 1.1755 + */ 1.1756 + if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN)) 1.1757 + return WRONG; 1.1758 + saved_seconds = yourtm.tm_sec; 1.1759 + yourtm.tm_sec = SECSPERMIN - 1; 1.1760 + } else { 1.1761 + saved_seconds = yourtm.tm_sec; 1.1762 + yourtm.tm_sec = 0; 1.1763 + } 1.1764 + /* 1.1765 + ** Do a binary search (this works whatever time_t's type is). 1.1766 + */ 1.1767 + if (!TYPE_SIGNED(time_t)) { 1.1768 + lo = 0; 1.1769 + hi = lo - 1; 1.1770 + } else if (!TYPE_INTEGRAL(time_t)) { 1.1771 + if (sizeof(time_t) > sizeof(float)) 1.1772 + hi = (time_t) DBL_MAX; 1.1773 + else hi = (time_t) FLT_MAX; 1.1774 + lo = -hi; 1.1775 + } else { 1.1776 + lo = 1; 1.1777 + for (i = 0; i < (int) TYPE_BIT(time_t) - 1; ++i) 1.1778 + lo *= 2; 1.1779 + hi = -(lo + 1); 1.1780 + } 1.1781 + for ( ; ; ) { 1.1782 + t = lo / 2 + hi / 2; 1.1783 + if (t < lo) 1.1784 + t = lo; 1.1785 + else if (t > hi) 1.1786 + t = hi; 1.1787 + if ((*funcp)(&t, offset, &mytm) == NULL) { 1.1788 + /* 1.1789 + ** Assume that t is too extreme to be represented in 1.1790 + ** a struct tm; arrange things so that it is less 1.1791 + ** extreme on the next pass. 1.1792 + */ 1.1793 + dir = (t > 0) ? 1 : -1; 1.1794 + } else dir = tmcomp(&mytm, &yourtm); 1.1795 + if (dir != 0) { 1.1796 + if (t == lo) { 1.1797 + ++t; 1.1798 + if (t <= lo) 1.1799 + return WRONG; 1.1800 + ++lo; 1.1801 + } else if (t == hi) { 1.1802 + --t; 1.1803 + if (t >= hi) 1.1804 + return WRONG; 1.1805 + --hi; 1.1806 + } 1.1807 + if (lo > hi) 1.1808 + return WRONG; 1.1809 + if (dir > 0) 1.1810 + hi = t; 1.1811 + else lo = t; 1.1812 + continue; 1.1813 + } 1.1814 + if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst) 1.1815 + break; 1.1816 + /* 1.1817 + ** Right time, wrong type. 1.1818 + ** Hunt for right time, right type. 1.1819 + ** It's okay to guess wrong since the guess 1.1820 + ** gets checked. 1.1821 + */ 1.1822 + sp = (const struct state *) 1.1823 + ((funcp == localsub) ? lclptr : gmtptr); 1.1824 +#ifdef ALL_STATE 1.1825 + if (sp == NULL) 1.1826 + return WRONG; 1.1827 +#endif /* defined ALL_STATE */ 1.1828 + for (i = sp->typecnt - 1; i >= 0; --i) { 1.1829 + if (sp->ttis[i].tt_isdst != yourtm.tm_isdst) 1.1830 + continue; 1.1831 + for (j = sp->typecnt - 1; j >= 0; --j) { 1.1832 + if (sp->ttis[j].tt_isdst == yourtm.tm_isdst) 1.1833 + continue; 1.1834 + newt = t + sp->ttis[j].tt_gmtoff - 1.1835 + sp->ttis[i].tt_gmtoff; 1.1836 + if ((*funcp)(&newt, offset, &mytm) == NULL) 1.1837 + continue; 1.1838 + if (tmcomp(&mytm, &yourtm) != 0) 1.1839 + continue; 1.1840 + if (mytm.tm_isdst != yourtm.tm_isdst) 1.1841 + continue; 1.1842 + /* 1.1843 + ** We have a match. 1.1844 + */ 1.1845 + t = newt; 1.1846 + goto label; 1.1847 + } 1.1848 + } 1.1849 + return WRONG; 1.1850 + } 1.1851 +label: 1.1852 + newt = t + saved_seconds; 1.1853 + if ((newt < t) != (saved_seconds < 0)) 1.1854 + return WRONG; 1.1855 + t = newt; 1.1856 + if ((*funcp)(&t, offset, tmp)) 1.1857 + *okayp = TRUE; 1.1858 + return t; 1.1859 +} 1.1860 + 1.1861 +static time_t 1.1862 +time2(tmp, funcp, offset, okayp) 1.1863 +struct tm * const tmp; 1.1864 +struct tm * (* const funcp)(const time_t*, long, struct tm*); 1.1865 +const long offset; 1.1866 +int * const okayp; 1.1867 +{ 1.1868 + time_t t; 1.1869 + 1.1870 + /* 1.1871 + ** First try without normalization of seconds 1.1872 + ** (in case tm_sec contains a value associated with a leap second). 1.1873 + ** If that fails, try with normalization of seconds. 1.1874 + */ 1.1875 + t = time2sub(tmp, funcp, offset, okayp, FALSE); 1.1876 + return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE); 1.1877 +} 1.1878 + 1.1879 +static time_t 1.1880 +time1(tmp, funcp, offset) 1.1881 +struct tm * const tmp; 1.1882 +struct tm * (* const funcp)(const time_t *, long, struct tm *); 1.1883 +const long offset; 1.1884 +{ 1.1885 + register time_t t; 1.1886 + register const struct state * sp; 1.1887 + register int samei, otheri; 1.1888 + register int sameind, otherind; 1.1889 + register int i; 1.1890 + register int nseen; 1.1891 + int seen[TZ_MAX_TYPES]; 1.1892 + int types[TZ_MAX_TYPES]; 1.1893 + int okay; 1.1894 + 1.1895 + if (tmp->tm_isdst > 1) 1.1896 + tmp->tm_isdst = 1; 1.1897 + t = time2(tmp, funcp, offset, &okay); 1.1898 +#ifdef PCTS 1.1899 + /* 1.1900 + ** PCTS code courtesy Grant Sullivan. 1.1901 + */ 1.1902 + if (okay) 1.1903 + return t; 1.1904 + if (tmp->tm_isdst < 0) 1.1905 + tmp->tm_isdst = 0; /* reset to std and try again */ 1.1906 +#endif /* defined PCTS */ 1.1907 +#ifndef PCTS 1.1908 + if (okay || tmp->tm_isdst < 0) 1.1909 + return t; 1.1910 +#endif /* !defined PCTS */ 1.1911 + /* 1.1912 + ** We're supposed to assume that somebody took a time of one type 1.1913 + ** and did some math on it that yielded a "struct tm" that's bad. 1.1914 + ** We try to divine the type they started from and adjust to the 1.1915 + ** type they need. 1.1916 + */ 1.1917 + sp = (const struct state *) ((funcp == localsub) ? lclptr : gmtptr); 1.1918 +#ifdef ALL_STATE 1.1919 + if (sp == NULL) 1.1920 + return WRONG; 1.1921 +#endif /* defined ALL_STATE */ 1.1922 + for (i = 0; i < sp->typecnt; ++i) 1.1923 + seen[i] = FALSE; 1.1924 + nseen = 0; 1.1925 + for (i = sp->timecnt - 1; i >= 0; --i) 1.1926 + if (!seen[sp->types[i]]) { 1.1927 + seen[sp->types[i]] = TRUE; 1.1928 + types[nseen++] = sp->types[i]; 1.1929 + } 1.1930 + for (sameind = 0; sameind < nseen; ++sameind) { 1.1931 + samei = types[sameind]; 1.1932 + if (sp->ttis[samei].tt_isdst != tmp->tm_isdst) 1.1933 + continue; 1.1934 + for (otherind = 0; otherind < nseen; ++otherind) { 1.1935 + otheri = types[otherind]; 1.1936 + if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst) 1.1937 + continue; 1.1938 + tmp->tm_sec += sp->ttis[otheri].tt_gmtoff - 1.1939 + sp->ttis[samei].tt_gmtoff; 1.1940 + tmp->tm_isdst = !tmp->tm_isdst; 1.1941 + t = time2(tmp, funcp, offset, &okay); 1.1942 + if (okay) 1.1943 + return t; 1.1944 + tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff - 1.1945 + sp->ttis[samei].tt_gmtoff; 1.1946 + tmp->tm_isdst = !tmp->tm_isdst; 1.1947 + } 1.1948 + } 1.1949 + return WRONG; 1.1950 +} 1.1951 + 1.1952 +time_t 1.1953 +mktime(tmp) 1.1954 +struct tm * const tmp; 1.1955 +{ 1.1956 + tzset(); 1.1957 + return time1(tmp, localsub, 0L); 1.1958 +} 1.1959 + 1.1960 +#ifdef STD_INSPIRED 1.1961 + 1.1962 +time_t 1.1963 +timelocal(tmp) 1.1964 +struct tm * const tmp; 1.1965 +{ 1.1966 + tmp->tm_isdst = -1; /* in case it wasn't initialized */ 1.1967 + return mktime(tmp); 1.1968 +} 1.1969 + 1.1970 +time_t 1.1971 +timegm(tmp) 1.1972 +struct tm * const tmp; 1.1973 +{ 1.1974 + tmp->tm_isdst = 0; 1.1975 + return time1(tmp, gmtsub, 0L); 1.1976 +} 1.1977 + 1.1978 +time_t 1.1979 +timeoff(tmp, offset) 1.1980 +struct tm * const tmp; 1.1981 +const long offset; 1.1982 +{ 1.1983 + tmp->tm_isdst = 0; 1.1984 + return time1(tmp, gmtsub, offset); 1.1985 +} 1.1986 + 1.1987 +#endif /* defined STD_INSPIRED */ 1.1988 + 1.1989 +#ifdef CMUCS 1.1990 + 1.1991 +/* 1.1992 +** The following is supplied for compatibility with 1.1993 +** previous versions of the CMUCS runtime library. 1.1994 +*/ 1.1995 + 1.1996 +long 1.1997 +gtime(tmp) 1.1998 +struct tm * const tmp; 1.1999 +{ 1.2000 + const time_t t = mktime(tmp); 1.2001 + 1.2002 + if (t == WRONG) 1.2003 + return -1; 1.2004 + return t; 1.2005 +} 1.2006 + 1.2007 +#endif /* defined CMUCS */ 1.2008 + 1.2009 +/* 1.2010 +** XXX--is the below the right way to conditionalize?? 1.2011 +*/ 1.2012 + 1.2013 +#ifdef STD_INSPIRED 1.2014 + 1.2015 +/* 1.2016 +** IEEE Std 1003.1-1988 (POSIX) legislates that 536457599 1.2017 +** shall correspond to "Wed Dec 31 23:59:59 UTC 1986", which 1.2018 +** is not the case if we are accounting for leap seconds. 1.2019 +** So, we provide the following conversion routines for use 1.2020 +** when exchanging timestamps with POSIX conforming systems. 1.2021 +*/ 1.2022 + 1.2023 +static long 1.2024 +leapcorr(timep) 1.2025 +time_t * timep; 1.2026 +{ 1.2027 + register struct state * sp; 1.2028 + register struct lsinfo * lp; 1.2029 + register int i; 1.2030 + 1.2031 + sp = lclptr; 1.2032 + i = sp->leapcnt; 1.2033 + while (--i >= 0) { 1.2034 + lp = &sp->lsis[i]; 1.2035 + if (*timep >= lp->ls_trans) 1.2036 + return lp->ls_corr; 1.2037 + } 1.2038 + return 0; 1.2039 +} 1.2040 + 1.2041 +time_t 1.2042 +time2posix(t) 1.2043 +time_t t; 1.2044 +{ 1.2045 + tzset(); 1.2046 + return t - leapcorr(&t); 1.2047 +} 1.2048 + 1.2049 +time_t 1.2050 +posix2time(t) 1.2051 +time_t t; 1.2052 +{ 1.2053 + time_t x; 1.2054 + time_t y; 1.2055 + 1.2056 + tzset(); 1.2057 + /* 1.2058 + ** For a positive leap second hit, the result 1.2059 + ** is not unique. For a negative leap second 1.2060 + ** hit, the corresponding time doesn't exist, 1.2061 + ** so we return an adjacent second. 1.2062 + */ 1.2063 + x = t + leapcorr(&t); 1.2064 + y = x - leapcorr(&x); 1.2065 + if (y < t) { 1.2066 + do { 1.2067 + x++; 1.2068 + y = x - leapcorr(&x); 1.2069 + } while (y < t); 1.2070 + if (t != y) 1.2071 + return x - 1; 1.2072 + } else if (y > t) { 1.2073 + do { 1.2074 + --x; 1.2075 + y = x - leapcorr(&x); 1.2076 + } while (y > t); 1.2077 + if (t != y) 1.2078 + return x + 1; 1.2079 + } 1.2080 + return x; 1.2081 +} 1.2082 + 1.2083 +#endif /* defined STD_INSPIRED */