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