usr/src/boot: add .PARALLEL to makefiles
[unleashed.git] / contrib / tzcode / localtime.c
blobafc743854049f527a559dde547638a166a923457
1 /*
2 ** This file is in the public domain, so clarified as of
3 ** 1996-06-05 by Arthur David Olson.
4 */
6 /*
7 ** Leap second handling from Bradley White.
8 ** POSIX-style TZ environment variable handling from Guy Harris.
9 */
11 /*LINTLIBRARY*/
13 #define LOCALTIME_IMPLEMENTATION
14 #include "private.h"
16 #include "tzfile.h"
17 #include <fcntl.h>
19 #if defined THREAD_SAFE && THREAD_SAFE
20 # include <pthread.h>
21 static pthread_mutex_t locallock = PTHREAD_MUTEX_INITIALIZER;
22 static int lock(void) { return pthread_mutex_lock(&locallock); }
23 static void unlock(void) { pthread_mutex_unlock(&locallock); }
24 #else
25 static int lock(void) { return 0; }
26 static void unlock(void) { }
27 #endif
29 /* NETBSD_INSPIRED_EXTERN functions are exported to callers if
30 NETBSD_INSPIRED is defined, and are private otherwise. */
31 #if NETBSD_INSPIRED
32 # define NETBSD_INSPIRED_EXTERN
33 #else
34 # define NETBSD_INSPIRED_EXTERN static
35 #endif
37 #ifndef TZ_ABBR_MAX_LEN
38 #define TZ_ABBR_MAX_LEN 16
39 #endif /* !defined TZ_ABBR_MAX_LEN */
41 #ifndef TZ_ABBR_CHAR_SET
42 #define TZ_ABBR_CHAR_SET \
43 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"
44 #endif /* !defined TZ_ABBR_CHAR_SET */
46 #ifndef TZ_ABBR_ERR_CHAR
47 #define TZ_ABBR_ERR_CHAR '_'
48 #endif /* !defined TZ_ABBR_ERR_CHAR */
51 ** SunOS 4.1.1 headers lack O_BINARY.
54 #ifdef O_BINARY
55 #define OPEN_MODE (O_RDONLY | O_BINARY)
56 #endif /* defined O_BINARY */
57 #ifndef O_BINARY
58 #define OPEN_MODE O_RDONLY
59 #endif /* !defined O_BINARY */
61 #ifndef WILDABBR
63 ** Someone might make incorrect use of a time zone abbreviation:
64 ** 1. They might reference tzname[0] before calling tzset (explicitly
65 ** or implicitly).
66 ** 2. They might reference tzname[1] before calling tzset (explicitly
67 ** or implicitly).
68 ** 3. They might reference tzname[1] after setting to a time zone
69 ** in which Daylight Saving Time is never observed.
70 ** 4. They might reference tzname[0] after setting to a time zone
71 ** in which Standard Time is never observed.
72 ** 5. They might reference tm.TM_ZONE after calling offtime.
73 ** What's best to do in the above cases is open to debate;
74 ** for now, we just set things up so that in any of the five cases
75 ** WILDABBR is used. Another possibility: initialize tzname[0] to the
76 ** string "tzname[0] used before set", and similarly for the other cases.
77 ** And another: initialize tzname[0] to "ERA", with an explanation in the
78 ** manual page of what this "time zone abbreviation" means (doing this so
79 ** that tzname[0] has the "normal" length of three characters).
81 #define WILDABBR " "
82 #endif /* !defined WILDABBR */
84 static const char wildabbr[] = WILDABBR;
86 static const char gmt[] = "GMT";
89 ** The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
90 ** We default to US rules as of 1999-08-17.
91 ** POSIX 1003.1 section 8.1.1 says that the default DST rules are
92 ** implementation dependent; for historical reasons, US rules are a
93 ** common default.
95 #ifndef TZDEFRULESTRING
96 #define TZDEFRULESTRING ",M4.1.0,M10.5.0"
97 #endif /* !defined TZDEFDST */
99 struct ttinfo { /* time type information */
100 int_fast32_t tt_gmtoff; /* UT offset in seconds */
101 bool tt_isdst; /* used to set tm_isdst */
102 int tt_abbrind; /* abbreviation list index */
103 bool tt_ttisstd; /* transition is std time */
104 bool tt_ttisgmt; /* transition is UT */
107 struct lsinfo { /* leap second information */
108 time_t ls_trans; /* transition time */
109 int_fast64_t ls_corr; /* correction to apply */
112 #define SMALLEST(a, b) (((a) < (b)) ? (a) : (b))
113 #define BIGGEST(a, b) (((a) > (b)) ? (a) : (b))
115 #ifdef TZNAME_MAX
116 #define MY_TZNAME_MAX TZNAME_MAX
117 #endif /* defined TZNAME_MAX */
118 #ifndef TZNAME_MAX
119 #define MY_TZNAME_MAX 255
120 #endif /* !defined TZNAME_MAX */
122 struct state {
123 int leapcnt;
124 int timecnt;
125 int typecnt;
126 int charcnt;
127 bool goback;
128 bool goahead;
129 time_t ats[TZ_MAX_TIMES];
130 unsigned char types[TZ_MAX_TIMES];
131 struct ttinfo ttis[TZ_MAX_TYPES];
132 char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt),
133 (2 * (MY_TZNAME_MAX + 1)))];
134 struct lsinfo lsis[TZ_MAX_LEAPS];
135 int defaulttype; /* for early times or if no transitions */
138 enum r_type {
139 JULIAN_DAY, /* Jn = Julian day */
140 DAY_OF_YEAR, /* n = day of year */
141 MONTH_NTH_DAY_OF_WEEK /* Mm.n.d = month, week, day of week */
144 struct rule {
145 enum r_type r_type; /* type of rule */
146 int r_day; /* day number of rule */
147 int r_week; /* week number of rule */
148 int r_mon; /* month number of rule */
149 int_fast32_t r_time; /* transition time of rule */
152 static struct tm *gmtsub(struct state const *, time_t const *, int_fast32_t,
153 struct tm *);
154 static bool increment_overflow(int *, int);
155 static bool increment_overflow_time(time_t *, int_fast32_t);
156 static bool normalize_overflow32(int_fast32_t *, int *, int);
157 static struct tm *timesub(time_t const *, int_fast32_t, struct state const *,
158 struct tm *);
159 static bool typesequiv(struct state const *, int, int);
160 static bool tzparse(char const *, struct state *, bool);
162 #ifdef ALL_STATE
163 static struct state * lclptr;
164 static struct state * gmtptr;
165 #endif /* defined ALL_STATE */
167 #ifndef ALL_STATE
168 static struct state lclmem;
169 static struct state gmtmem;
170 #define lclptr (&lclmem)
171 #define gmtptr (&gmtmem)
172 #endif /* State Farm */
174 #ifndef TZ_STRLEN_MAX
175 #define TZ_STRLEN_MAX 255
176 #endif /* !defined TZ_STRLEN_MAX */
178 static char lcl_TZname[TZ_STRLEN_MAX + 1];
179 static int lcl_is_set;
182 ** Section 4.12.3 of X3.159-1989 requires that
183 ** Except for the strftime function, these functions [asctime,
184 ** ctime, gmtime, localtime] return values in one of two static
185 ** objects: a broken-down time structure and an array of char.
186 ** Thanks to Paul Eggert for noting this.
189 static struct tm tm;
191 #if !HAVE_POSIX_DECLS
192 char * tzname[2] = {
193 (char *) wildabbr,
194 (char *) wildabbr
196 # ifdef USG_COMPAT
197 long timezone;
198 int daylight;
199 # endif
200 #endif
202 #ifdef ALTZONE
203 long altzone;
204 #endif /* defined ALTZONE */
206 /* Initialize *S to a value based on GMTOFF, ISDST, and ABBRIND. */
207 static void
208 init_ttinfo(struct ttinfo *s, int_fast32_t gmtoff, bool isdst, int abbrind)
210 s->tt_gmtoff = gmtoff;
211 s->tt_isdst = isdst;
212 s->tt_abbrind = abbrind;
213 s->tt_ttisstd = false;
214 s->tt_ttisgmt = false;
217 static int_fast32_t
218 detzcode(const char *const codep)
220 register int_fast32_t result;
221 register int i;
222 int_fast32_t one = 1;
223 int_fast32_t halfmaxval = one << (32 - 2);
224 int_fast32_t maxval = halfmaxval - 1 + halfmaxval;
225 int_fast32_t minval = -1 - maxval;
227 result = codep[0] & 0x7f;
228 for (i = 1; i < 4; ++i)
229 result = (result << 8) | (codep[i] & 0xff);
231 if (codep[0] & 0x80) {
232 /* Do two's-complement negation even on non-two's-complement machines.
233 If the result would be minval - 1, return minval. */
234 result -= !TWOS_COMPLEMENT(int_fast32_t) && result != 0;
235 result += minval;
237 return result;
240 static int_fast64_t
241 detzcode64(const char *const codep)
243 register uint_fast64_t result;
244 register int i;
245 int_fast64_t one = 1;
246 int_fast64_t halfmaxval = one << (64 - 2);
247 int_fast64_t maxval = halfmaxval - 1 + halfmaxval;
248 int_fast64_t minval = -TWOS_COMPLEMENT(int_fast64_t) - maxval;
250 result = codep[0] & 0x7f;
251 for (i = 1; i < 8; ++i)
252 result = (result << 8) | (codep[i] & 0xff);
254 if (codep[0] & 0x80) {
255 /* Do two's-complement negation even on non-two's-complement machines.
256 If the result would be minval - 1, return minval. */
257 result -= !TWOS_COMPLEMENT(int_fast64_t) && result != 0;
258 result += minval;
260 return result;
263 static void
264 update_tzname_etc(struct state const *sp, struct ttinfo const *ttisp)
266 tzname[ttisp->tt_isdst] = (char *) &sp->chars[ttisp->tt_abbrind];
267 #ifdef USG_COMPAT
268 if (!ttisp->tt_isdst)
269 timezone = - ttisp->tt_gmtoff;
270 #endif
271 #ifdef ALTZONE
272 if (ttisp->tt_isdst)
273 altzone = - ttisp->tt_gmtoff;
274 #endif
277 static void
278 settzname(void)
280 register struct state * const sp = lclptr;
281 register int i;
283 tzname[0] = tzname[1] = (char *) wildabbr;
284 #ifdef USG_COMPAT
285 daylight = 0;
286 timezone = 0;
287 #endif /* defined USG_COMPAT */
288 #ifdef ALTZONE
289 altzone = 0;
290 #endif /* defined ALTZONE */
291 if (sp == NULL) {
292 tzname[0] = tzname[1] = (char *) gmt;
293 return;
296 ** And to get the latest zone names into tzname. . .
298 for (i = 0; i < sp->typecnt; ++i) {
299 register const struct ttinfo * const ttisp = &sp->ttis[i];
300 update_tzname_etc(sp, ttisp);
302 for (i = 0; i < sp->timecnt; ++i) {
303 register const struct ttinfo * const ttisp =
304 &sp->ttis[
305 sp->types[i]];
306 update_tzname_etc(sp, ttisp);
307 #ifdef USG_COMPAT
308 if (ttisp->tt_isdst)
309 daylight = 1;
310 #endif /* defined USG_COMPAT */
314 static void
315 scrub_abbrs(struct state *sp)
317 int i;
319 ** First, replace bogus characters.
321 for (i = 0; i < sp->charcnt; ++i)
322 if (strchr(TZ_ABBR_CHAR_SET, sp->chars[i]) == NULL)
323 sp->chars[i] = TZ_ABBR_ERR_CHAR;
325 ** Second, truncate long abbreviations.
327 for (i = 0; i < sp->typecnt; ++i) {
328 register const struct ttinfo * const ttisp = &sp->ttis[i];
329 register char * cp = &sp->chars[ttisp->tt_abbrind];
331 if (strlen(cp) > TZ_ABBR_MAX_LEN &&
332 strcmp(cp, GRANDPARENTED) != 0)
333 *(cp + TZ_ABBR_MAX_LEN) = '\0';
337 static bool
338 differ_by_repeat(const time_t t1, const time_t t0)
340 if (TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS)
341 return 0;
342 return t1 - t0 == SECSPERREPEAT;
345 /* Input buffer for data read from a compiled tz file. */
346 union input_buffer {
347 /* The first part of the buffer, interpreted as a header. */
348 struct tzhead tzhead;
350 /* The entire buffer. */
351 char buf[2 * sizeof(struct tzhead) + 2 * sizeof (struct state)
352 + 4 * TZ_MAX_TIMES];
355 /* Local storage needed for 'tzloadbody'. */
356 union local_storage {
357 /* The file name to be opened. */
358 char fullname[FILENAME_MAX + 1];
360 /* The results of analyzing the file's contents after it is opened. */
361 struct {
362 /* The input buffer. */
363 union input_buffer u;
365 /* A temporary state used for parsing a TZ string in the file. */
366 struct state st;
367 } u;
370 /* Load tz data from the file named NAME into *SP. Read extended
371 format if DOEXTEND. Use *LSP for temporary storage. Return 0 on
372 success, an errno value on failure. */
373 static int
374 tzloadbody(char const *name, struct state *sp, bool doextend,
375 union local_storage *lsp)
377 register int i;
378 register int fid;
379 register int stored;
380 register ssize_t nread;
381 register bool doaccess;
382 register char *fullname = lsp->fullname;
383 register union input_buffer *up = &lsp->u.u;
384 register int tzheadsize = sizeof (struct tzhead);
386 sp->goback = sp->goahead = false;
388 if (! name) {
389 name = TZDEFAULT;
390 if (! name)
391 return EINVAL;
394 if (name[0] == ':')
395 ++name;
396 doaccess = name[0] == '/';
397 if (!doaccess) {
398 char const *p = TZDIR;
399 if (! p)
400 return EINVAL;
401 if (sizeof lsp->fullname - 1 <= strlen(p) + strlen(name))
402 return ENAMETOOLONG;
403 strcpy(fullname, p);
404 strcat(fullname, "/");
405 strcat(fullname, name);
406 /* Set doaccess if '.' (as in "../") shows up in name. */
407 if (strchr(name, '.'))
408 doaccess = true;
409 name = fullname;
411 if (doaccess && access(name, R_OK) != 0)
412 return errno;
413 fid = open(name, OPEN_MODE);
414 if (fid < 0)
415 return errno;
417 nread = read(fid, up->buf, sizeof up->buf);
418 if (nread < tzheadsize) {
419 int err = nread < 0 ? errno : EINVAL;
420 close(fid);
421 return err;
423 if (close(fid) < 0)
424 return errno;
425 for (stored = 4; stored <= 8; stored *= 2) {
426 int_fast32_t ttisstdcnt = detzcode(up->tzhead.tzh_ttisstdcnt);
427 int_fast32_t ttisgmtcnt = detzcode(up->tzhead.tzh_ttisgmtcnt);
428 int_fast32_t leapcnt = detzcode(up->tzhead.tzh_leapcnt);
429 int_fast32_t timecnt = detzcode(up->tzhead.tzh_timecnt);
430 int_fast32_t typecnt = detzcode(up->tzhead.tzh_typecnt);
431 int_fast32_t charcnt = detzcode(up->tzhead.tzh_charcnt);
432 char const *p = up->buf + tzheadsize;
433 if (! (0 <= leapcnt && leapcnt < TZ_MAX_LEAPS
434 && 0 < typecnt && typecnt < TZ_MAX_TYPES
435 && 0 <= timecnt && timecnt < TZ_MAX_TIMES
436 && 0 <= charcnt && charcnt < TZ_MAX_CHARS
437 && (ttisstdcnt == typecnt || ttisstdcnt == 0)
438 && (ttisgmtcnt == typecnt || ttisgmtcnt == 0)))
439 return EINVAL;
440 if (nread
441 < (tzheadsize /* struct tzhead */
442 + timecnt * stored /* ats */
443 + timecnt /* types */
444 + typecnt * 6 /* ttinfos */
445 + charcnt /* chars */
446 + leapcnt * (stored + 4) /* lsinfos */
447 + ttisstdcnt /* ttisstds */
448 + ttisgmtcnt)) /* ttisgmts */
449 return EINVAL;
450 sp->leapcnt = leapcnt;
451 sp->timecnt = timecnt;
452 sp->typecnt = typecnt;
453 sp->charcnt = charcnt;
455 /* Read transitions, discarding those out of time_t range.
456 But pretend the last transition before time_t_min
457 occurred at time_t_min. */
458 timecnt = 0;
459 for (i = 0; i < sp->timecnt; ++i) {
460 int_fast64_t at
461 = stored == 4 ? detzcode(p) : detzcode64(p);
462 sp->types[i] = at <= time_t_max;
463 if (sp->types[i]) {
464 time_t attime
465 = ((TYPE_SIGNED(time_t) ? at < time_t_min : at < 0)
466 ? time_t_min : at);
467 if (timecnt && attime <= sp->ats[timecnt - 1]) {
468 if (attime < sp->ats[timecnt - 1])
469 return EINVAL;
470 sp->types[i - 1] = 0;
471 timecnt--;
473 sp->ats[timecnt++] = attime;
475 p += stored;
478 timecnt = 0;
479 for (i = 0; i < sp->timecnt; ++i) {
480 unsigned char typ = *p++;
481 if (sp->typecnt <= typ)
482 return EINVAL;
483 if (sp->types[i])
484 sp->types[timecnt++] = typ;
486 sp->timecnt = timecnt;
487 for (i = 0; i < sp->typecnt; ++i) {
488 register struct ttinfo * ttisp;
489 unsigned char isdst, abbrind;
491 ttisp = &sp->ttis[i];
492 ttisp->tt_gmtoff = detzcode(p);
493 p += 4;
494 isdst = *p++;
495 if (! (isdst < 2))
496 return EINVAL;
497 ttisp->tt_isdst = isdst;
498 abbrind = *p++;
499 if (! (abbrind < sp->charcnt))
500 return EINVAL;
501 ttisp->tt_abbrind = abbrind;
503 for (i = 0; i < sp->charcnt; ++i)
504 sp->chars[i] = *p++;
505 sp->chars[i] = '\0'; /* ensure '\0' at end */
507 /* Read leap seconds, discarding those out of time_t range. */
508 leapcnt = 0;
509 for (i = 0; i < sp->leapcnt; ++i) {
510 int_fast64_t tr = stored == 4 ? detzcode(p) : detzcode64(p);
511 int_fast32_t corr = detzcode(p + stored);
512 p += stored + 4;
513 if (tr <= time_t_max) {
514 time_t trans
515 = ((TYPE_SIGNED(time_t) ? tr < time_t_min : tr < 0)
516 ? time_t_min : tr);
517 if (leapcnt && trans <= sp->lsis[leapcnt - 1].ls_trans) {
518 if (trans < sp->lsis[leapcnt - 1].ls_trans)
519 return EINVAL;
520 leapcnt--;
522 sp->lsis[leapcnt].ls_trans = trans;
523 sp->lsis[leapcnt].ls_corr = corr;
524 leapcnt++;
527 sp->leapcnt = leapcnt;
529 for (i = 0; i < sp->typecnt; ++i) {
530 register struct ttinfo * ttisp;
532 ttisp = &sp->ttis[i];
533 if (ttisstdcnt == 0)
534 ttisp->tt_ttisstd = false;
535 else {
536 if (*p != true && *p != false)
537 return EINVAL;
538 ttisp->tt_ttisstd = *p++;
541 for (i = 0; i < sp->typecnt; ++i) {
542 register struct ttinfo * ttisp;
544 ttisp = &sp->ttis[i];
545 if (ttisgmtcnt == 0)
546 ttisp->tt_ttisgmt = false;
547 else {
548 if (*p != true && *p != false)
549 return EINVAL;
550 ttisp->tt_ttisgmt = *p++;
554 ** If this is an old file, we're done.
556 if (up->tzhead.tzh_version[0] == '\0')
557 break;
558 nread -= p - up->buf;
559 memmove(up->buf, p, nread);
561 if (doextend && nread > 2 &&
562 up->buf[0] == '\n' && up->buf[nread - 1] == '\n' &&
563 sp->typecnt + 2 <= TZ_MAX_TYPES) {
564 struct state *ts = &lsp->u.st;
566 up->buf[nread - 1] = '\0';
567 if (tzparse(&up->buf[1], ts, false)
568 && ts->typecnt == 2) {
570 /* Attempt to reuse existing abbreviations.
571 Without this, America/Anchorage would be right on
572 the edge after 2037 when TZ_MAX_CHARS is 50, as
573 sp->charcnt equals 40 (for LMT AST AWT APT AHST
574 AHDT YST AKDT AKST) and ts->charcnt equals 10
575 (for AKST AKDT). Reusing means sp->charcnt can
576 stay 40 in this example. */
577 int gotabbr = 0;
578 int charcnt = sp->charcnt;
579 for (i = 0; i < 2; i++) {
580 char *tsabbr = ts->chars + ts->ttis[i].tt_abbrind;
581 int j;
582 for (j = 0; j < charcnt; j++)
583 if (strcmp(sp->chars + j, tsabbr) == 0) {
584 ts->ttis[i].tt_abbrind = j;
585 gotabbr++;
586 break;
588 if (! (j < charcnt)) {
589 int tsabbrlen = strlen(tsabbr);
590 if (j + tsabbrlen < TZ_MAX_CHARS) {
591 strcpy(sp->chars + j, tsabbr);
592 charcnt = j + tsabbrlen + 1;
593 ts->ttis[i].tt_abbrind = j;
594 gotabbr++;
598 if (gotabbr == 2) {
599 sp->charcnt = charcnt;
601 /* Ignore any trailing, no-op transitions generated
602 by zic as they don't help here and can run afoul
603 of bugs in zic 2016j or earlier. */
604 while (1 < sp->timecnt
605 && (sp->types[sp->timecnt - 1]
606 == sp->types[sp->timecnt - 2]))
607 sp->timecnt--;
609 for (i = 0; i < ts->timecnt; i++)
610 if (sp->ats[sp->timecnt - 1] < ts->ats[i])
611 break;
612 while (i < ts->timecnt
613 && sp->timecnt < TZ_MAX_TIMES) {
614 sp->ats[sp->timecnt] = ts->ats[i];
615 sp->types[sp->timecnt] = (sp->typecnt
616 + ts->types[i]);
617 sp->timecnt++;
618 i++;
620 sp->ttis[sp->typecnt++] = ts->ttis[0];
621 sp->ttis[sp->typecnt++] = ts->ttis[1];
625 if (sp->timecnt > 1) {
626 for (i = 1; i < sp->timecnt; ++i)
627 if (typesequiv(sp, sp->types[i], sp->types[0]) &&
628 differ_by_repeat(sp->ats[i], sp->ats[0])) {
629 sp->goback = true;
630 break;
632 for (i = sp->timecnt - 2; i >= 0; --i)
633 if (typesequiv(sp, sp->types[sp->timecnt - 1],
634 sp->types[i]) &&
635 differ_by_repeat(sp->ats[sp->timecnt - 1],
636 sp->ats[i])) {
637 sp->goahead = true;
638 break;
642 ** If type 0 is is unused in transitions,
643 ** it's the type to use for early times.
645 for (i = 0; i < sp->timecnt; ++i)
646 if (sp->types[i] == 0)
647 break;
648 i = i < sp->timecnt ? -1 : 0;
650 ** Absent the above,
651 ** if there are transition times
652 ** and the first transition is to a daylight time
653 ** find the standard type less than and closest to
654 ** the type of the first transition.
656 if (i < 0 && sp->timecnt > 0 && sp->ttis[sp->types[0]].tt_isdst) {
657 i = sp->types[0];
658 while (--i >= 0)
659 if (!sp->ttis[i].tt_isdst)
660 break;
663 ** If no result yet, find the first standard type.
664 ** If there is none, punt to type zero.
666 if (i < 0) {
667 i = 0;
668 while (sp->ttis[i].tt_isdst)
669 if (++i >= sp->typecnt) {
670 i = 0;
671 break;
674 sp->defaulttype = i;
675 return 0;
678 /* Load tz data from the file named NAME into *SP. Read extended
679 format if DOEXTEND. Return 0 on success, an errno value on failure. */
680 static int
681 tzload(char const *name, struct state *sp, bool doextend)
683 #ifdef ALL_STATE
684 union local_storage *lsp = malloc(sizeof *lsp);
685 if (!lsp)
686 return errno;
687 else {
688 int err = tzloadbody(name, sp, doextend, lsp);
689 free(lsp);
690 return err;
692 #else
693 union local_storage ls;
694 return tzloadbody(name, sp, doextend, &ls);
695 #endif
698 static bool
699 typesequiv(const struct state *sp, int a, int b)
701 register bool result;
703 if (sp == NULL ||
704 a < 0 || a >= sp->typecnt ||
705 b < 0 || b >= sp->typecnt)
706 result = false;
707 else {
708 register const struct ttinfo * ap = &sp->ttis[a];
709 register const struct ttinfo * bp = &sp->ttis[b];
710 result = ap->tt_gmtoff == bp->tt_gmtoff &&
711 ap->tt_isdst == bp->tt_isdst &&
712 ap->tt_ttisstd == bp->tt_ttisstd &&
713 ap->tt_ttisgmt == bp->tt_ttisgmt &&
714 strcmp(&sp->chars[ap->tt_abbrind],
715 &sp->chars[bp->tt_abbrind]) == 0;
717 return result;
720 static const int mon_lengths[2][MONSPERYEAR] = {
721 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
722 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
725 static const int year_lengths[2] = {
726 DAYSPERNYEAR, DAYSPERLYEAR
730 ** Given a pointer into a time zone string, scan until a character that is not
731 ** a valid character in a zone name is found. Return a pointer to that
732 ** character.
735 static const char * ATTRIBUTE_PURE
736 getzname(register const char *strp)
738 register char c;
740 while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
741 c != '+')
742 ++strp;
743 return strp;
747 ** Given a pointer into an extended time zone string, scan until the ending
748 ** delimiter of the zone name is located. Return a pointer to the delimiter.
750 ** As with getzname above, the legal character set is actually quite
751 ** restricted, with other characters producing undefined results.
752 ** We don't do any checking here; checking is done later in common-case code.
755 static const char * ATTRIBUTE_PURE
756 getqzname(register const char *strp, const int delim)
758 register int c;
760 while ((c = *strp) != '\0' && c != delim)
761 ++strp;
762 return strp;
766 ** Given a pointer into a time zone string, extract a number from that string.
767 ** Check that the number is within a specified range; if it is not, return
768 ** NULL.
769 ** Otherwise, return a pointer to the first character not part of the number.
772 static const char *
773 getnum(register const char *strp, int *const nump, const int min, const int max)
775 register char c;
776 register int num;
778 if (strp == NULL || !is_digit(c = *strp))
779 return NULL;
780 num = 0;
781 do {
782 num = num * 10 + (c - '0');
783 if (num > max)
784 return NULL; /* illegal value */
785 c = *++strp;
786 } while (is_digit(c));
787 if (num < min)
788 return NULL; /* illegal value */
789 *nump = num;
790 return strp;
794 ** Given a pointer into a time zone string, extract a number of seconds,
795 ** in hh[:mm[:ss]] form, from the string.
796 ** If any error occurs, return NULL.
797 ** Otherwise, return a pointer to the first character not part of the number
798 ** of seconds.
801 static const char *
802 getsecs(register const char *strp, int_fast32_t *const secsp)
804 int num;
807 ** 'HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
808 ** "M10.4.6/26", which does not conform to Posix,
809 ** but which specifies the equivalent of
810 ** "02:00 on the first Sunday on or after 23 Oct".
812 strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
813 if (strp == NULL)
814 return NULL;
815 *secsp = num * (int_fast32_t) SECSPERHOUR;
816 if (*strp == ':') {
817 ++strp;
818 strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
819 if (strp == NULL)
820 return NULL;
821 *secsp += num * SECSPERMIN;
822 if (*strp == ':') {
823 ++strp;
824 /* 'SECSPERMIN' allows for leap seconds. */
825 strp = getnum(strp, &num, 0, SECSPERMIN);
826 if (strp == NULL)
827 return NULL;
828 *secsp += num;
831 return strp;
835 ** Given a pointer into a time zone string, extract an offset, in
836 ** [+-]hh[:mm[:ss]] form, from the string.
837 ** If any error occurs, return NULL.
838 ** Otherwise, return a pointer to the first character not part of the time.
841 static const char *
842 getoffset(register const char *strp, int_fast32_t *const offsetp)
844 register bool neg = false;
846 if (*strp == '-') {
847 neg = true;
848 ++strp;
849 } else if (*strp == '+')
850 ++strp;
851 strp = getsecs(strp, offsetp);
852 if (strp == NULL)
853 return NULL; /* illegal time */
854 if (neg)
855 *offsetp = -*offsetp;
856 return strp;
860 ** Given a pointer into a time zone string, extract a rule in the form
861 ** date[/time]. See POSIX section 8 for the format of "date" and "time".
862 ** If a valid rule is not found, return NULL.
863 ** Otherwise, return a pointer to the first character not part of the rule.
866 static const char *
867 getrule(const char *strp, register struct rule *const rulep)
869 if (*strp == 'J') {
871 ** Julian day.
873 rulep->r_type = JULIAN_DAY;
874 ++strp;
875 strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
876 } else if (*strp == 'M') {
878 ** Month, week, day.
880 rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
881 ++strp;
882 strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
883 if (strp == NULL)
884 return NULL;
885 if (*strp++ != '.')
886 return NULL;
887 strp = getnum(strp, &rulep->r_week, 1, 5);
888 if (strp == NULL)
889 return NULL;
890 if (*strp++ != '.')
891 return NULL;
892 strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
893 } else if (is_digit(*strp)) {
895 ** Day of year.
897 rulep->r_type = DAY_OF_YEAR;
898 strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
899 } else return NULL; /* invalid format */
900 if (strp == NULL)
901 return NULL;
902 if (*strp == '/') {
904 ** Time specified.
906 ++strp;
907 strp = getoffset(strp, &rulep->r_time);
908 } else rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */
909 return strp;
913 ** Given a year, a rule, and the offset from UT at the time that rule takes
914 ** effect, calculate the year-relative time that rule takes effect.
917 static int_fast32_t ATTRIBUTE_PURE
918 transtime(const int year, register const struct rule *const rulep,
919 const int_fast32_t offset)
921 register bool leapyear;
922 register int_fast32_t value;
923 register int i;
924 int d, m1, yy0, yy1, yy2, dow;
926 INITIALIZE(value);
927 leapyear = isleap(year);
928 switch (rulep->r_type) {
930 case JULIAN_DAY:
932 ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
933 ** years.
934 ** In non-leap years, or if the day number is 59 or less, just
935 ** add SECSPERDAY times the day number-1 to the time of
936 ** January 1, midnight, to get the day.
938 value = (rulep->r_day - 1) * SECSPERDAY;
939 if (leapyear && rulep->r_day >= 60)
940 value += SECSPERDAY;
941 break;
943 case DAY_OF_YEAR:
945 ** n - day of year.
946 ** Just add SECSPERDAY times the day number to the time of
947 ** January 1, midnight, to get the day.
949 value = rulep->r_day * SECSPERDAY;
950 break;
952 case MONTH_NTH_DAY_OF_WEEK:
954 ** Mm.n.d - nth "dth day" of month m.
958 ** Use Zeller's Congruence to get day-of-week of first day of
959 ** month.
961 m1 = (rulep->r_mon + 9) % 12 + 1;
962 yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
963 yy1 = yy0 / 100;
964 yy2 = yy0 % 100;
965 dow = ((26 * m1 - 2) / 10 +
966 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
967 if (dow < 0)
968 dow += DAYSPERWEEK;
971 ** "dow" is the day-of-week of the first day of the month. Get
972 ** the day-of-month (zero-origin) of the first "dow" day of the
973 ** month.
975 d = rulep->r_day - dow;
976 if (d < 0)
977 d += DAYSPERWEEK;
978 for (i = 1; i < rulep->r_week; ++i) {
979 if (d + DAYSPERWEEK >=
980 mon_lengths[leapyear][rulep->r_mon - 1])
981 break;
982 d += DAYSPERWEEK;
986 ** "d" is the day-of-month (zero-origin) of the day we want.
988 value = d * SECSPERDAY;
989 for (i = 0; i < rulep->r_mon - 1; ++i)
990 value += mon_lengths[leapyear][i] * SECSPERDAY;
991 break;
995 ** "value" is the year-relative time of 00:00:00 UT on the day in
996 ** question. To get the year-relative time of the specified local
997 ** time on that day, add the transition time and the current offset
998 ** from UT.
1000 return value + rulep->r_time + offset;
1004 ** Given a POSIX section 8-style TZ string, fill in the rule tables as
1005 ** appropriate.
1008 static bool
1009 tzparse(const char *name, struct state *sp, bool lastditch)
1011 const char * stdname;
1012 const char * dstname;
1013 size_t stdlen;
1014 size_t dstlen;
1015 size_t charcnt;
1016 int_fast32_t stdoffset;
1017 int_fast32_t dstoffset;
1018 register char * cp;
1019 register bool load_ok;
1021 stdname = name;
1022 if (lastditch) {
1023 stdlen = sizeof gmt - 1;
1024 name += stdlen;
1025 stdoffset = 0;
1026 } else {
1027 if (*name == '<') {
1028 name++;
1029 stdname = name;
1030 name = getqzname(name, '>');
1031 if (*name != '>')
1032 return false;
1033 stdlen = name - stdname;
1034 name++;
1035 } else {
1036 name = getzname(name);
1037 stdlen = name - stdname;
1039 if (!stdlen)
1040 return false;
1041 name = getoffset(name, &stdoffset);
1042 if (name == NULL)
1043 return false;
1045 charcnt = stdlen + 1;
1046 if (sizeof sp->chars < charcnt)
1047 return false;
1048 load_ok = tzload(TZDEFRULES, sp, false) == 0;
1049 if (!load_ok)
1050 sp->leapcnt = 0; /* so, we're off a little */
1051 if (*name != '\0') {
1052 if (*name == '<') {
1053 dstname = ++name;
1054 name = getqzname(name, '>');
1055 if (*name != '>')
1056 return false;
1057 dstlen = name - dstname;
1058 name++;
1059 } else {
1060 dstname = name;
1061 name = getzname(name);
1062 dstlen = name - dstname; /* length of DST zone name */
1064 if (!dstlen)
1065 return false;
1066 charcnt += dstlen + 1;
1067 if (sizeof sp->chars < charcnt)
1068 return false;
1069 if (*name != '\0' && *name != ',' && *name != ';') {
1070 name = getoffset(name, &dstoffset);
1071 if (name == NULL)
1072 return false;
1073 } else dstoffset = stdoffset - SECSPERHOUR;
1074 if (*name == '\0' && !load_ok)
1075 name = TZDEFRULESTRING;
1076 if (*name == ',' || *name == ';') {
1077 struct rule start;
1078 struct rule end;
1079 register int year;
1080 register int yearlim;
1081 register int timecnt;
1082 time_t janfirst;
1083 int_fast32_t janoffset = 0;
1084 int yearbeg;
1086 ++name;
1087 if ((name = getrule(name, &start)) == NULL)
1088 return false;
1089 if (*name++ != ',')
1090 return false;
1091 if ((name = getrule(name, &end)) == NULL)
1092 return false;
1093 if (*name != '\0')
1094 return false;
1095 sp->typecnt = 2; /* standard time and DST */
1097 ** Two transitions per year, from EPOCH_YEAR forward.
1099 init_ttinfo(&sp->ttis[0], -dstoffset, true, stdlen + 1);
1100 init_ttinfo(&sp->ttis[1], -stdoffset, false, 0);
1101 sp->defaulttype = 0;
1102 timecnt = 0;
1103 janfirst = 0;
1104 yearbeg = EPOCH_YEAR;
1106 do {
1107 int_fast32_t yearsecs
1108 = year_lengths[isleap(yearbeg - 1)] * SECSPERDAY;
1109 yearbeg--;
1110 if (increment_overflow_time(&janfirst, -yearsecs)) {
1111 janoffset = -yearsecs;
1112 break;
1114 } while (EPOCH_YEAR - YEARSPERREPEAT / 2 < yearbeg);
1116 yearlim = yearbeg + YEARSPERREPEAT + 1;
1117 for (year = yearbeg; year < yearlim; year++) {
1118 int_fast32_t
1119 starttime = transtime(year, &start, stdoffset),
1120 endtime = transtime(year, &end, dstoffset);
1121 int_fast32_t
1122 yearsecs = (year_lengths[isleap(year)]
1123 * SECSPERDAY);
1124 bool reversed = endtime < starttime;
1125 if (reversed) {
1126 int_fast32_t swap = starttime;
1127 starttime = endtime;
1128 endtime = swap;
1130 if (reversed
1131 || (starttime < endtime
1132 && (endtime - starttime
1133 < (yearsecs
1134 + (stdoffset - dstoffset))))) {
1135 if (TZ_MAX_TIMES - 2 < timecnt)
1136 break;
1137 sp->ats[timecnt] = janfirst;
1138 if (! increment_overflow_time
1139 (&sp->ats[timecnt],
1140 janoffset + starttime))
1141 sp->types[timecnt++] = reversed;
1142 else if (janoffset)
1143 sp->defaulttype = reversed;
1144 sp->ats[timecnt] = janfirst;
1145 if (! increment_overflow_time
1146 (&sp->ats[timecnt],
1147 janoffset + endtime)) {
1148 sp->types[timecnt++] = !reversed;
1149 yearlim = year + YEARSPERREPEAT + 1;
1150 } else if (janoffset)
1151 sp->defaulttype = !reversed;
1153 if (increment_overflow_time
1154 (&janfirst, janoffset + yearsecs))
1155 break;
1156 janoffset = 0;
1158 sp->timecnt = timecnt;
1159 if (! timecnt)
1160 sp->typecnt = 1; /* Perpetual DST. */
1161 else if (YEARSPERREPEAT < year - yearbeg)
1162 sp->goback = sp->goahead = true;
1163 } else {
1164 register int_fast32_t theirstdoffset;
1165 register int_fast32_t theirdstoffset;
1166 register int_fast32_t theiroffset;
1167 register bool isdst;
1168 register int i;
1169 register int j;
1171 if (*name != '\0')
1172 return false;
1174 ** Initial values of theirstdoffset and theirdstoffset.
1176 theirstdoffset = 0;
1177 for (i = 0; i < sp->timecnt; ++i) {
1178 j = sp->types[i];
1179 if (!sp->ttis[j].tt_isdst) {
1180 theirstdoffset =
1181 -sp->ttis[j].tt_gmtoff;
1182 break;
1185 theirdstoffset = 0;
1186 for (i = 0; i < sp->timecnt; ++i) {
1187 j = sp->types[i];
1188 if (sp->ttis[j].tt_isdst) {
1189 theirdstoffset =
1190 -sp->ttis[j].tt_gmtoff;
1191 break;
1195 ** Initially we're assumed to be in standard time.
1197 isdst = false;
1198 theiroffset = theirstdoffset;
1200 ** Now juggle transition times and types
1201 ** tracking offsets as you do.
1203 for (i = 0; i < sp->timecnt; ++i) {
1204 j = sp->types[i];
1205 sp->types[i] = sp->ttis[j].tt_isdst;
1206 if (sp->ttis[j].tt_ttisgmt) {
1207 /* No adjustment to transition time */
1208 } else {
1210 ** If summer time is in effect, and the
1211 ** transition time was not specified as
1212 ** standard time, add the summer time
1213 ** offset to the transition time;
1214 ** otherwise, add the standard time
1215 ** offset to the transition time.
1218 ** Transitions from DST to DDST
1219 ** will effectively disappear since
1220 ** POSIX provides for only one DST
1221 ** offset.
1223 if (isdst && !sp->ttis[j].tt_ttisstd) {
1224 sp->ats[i] += dstoffset -
1225 theirdstoffset;
1226 } else {
1227 sp->ats[i] += stdoffset -
1228 theirstdoffset;
1231 theiroffset = -sp->ttis[j].tt_gmtoff;
1232 if (sp->ttis[j].tt_isdst)
1233 theirdstoffset = theiroffset;
1234 else theirstdoffset = theiroffset;
1237 ** Finally, fill in ttis.
1239 init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
1240 init_ttinfo(&sp->ttis[1], -dstoffset, true, stdlen + 1);
1241 sp->typecnt = 2;
1242 sp->defaulttype = 0;
1244 } else {
1245 dstlen = 0;
1246 sp->typecnt = 1; /* only standard time */
1247 sp->timecnt = 0;
1248 init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
1249 sp->defaulttype = 0;
1251 sp->charcnt = charcnt;
1252 cp = sp->chars;
1253 memcpy(cp, stdname, stdlen);
1254 cp += stdlen;
1255 *cp++ = '\0';
1256 if (dstlen != 0) {
1257 memcpy(cp, dstname, dstlen);
1258 *(cp + dstlen) = '\0';
1260 return true;
1263 static void
1264 gmtload(struct state *const sp)
1266 if (tzload(gmt, sp, true) != 0)
1267 tzparse(gmt, sp, true);
1270 /* Initialize *SP to a value appropriate for the TZ setting NAME.
1271 Return 0 on success, an errno value on failure. */
1272 static int
1273 zoneinit(struct state *sp, char const *name)
1275 if (name && ! name[0]) {
1277 ** User wants it fast rather than right.
1279 sp->leapcnt = 0; /* so, we're off a little */
1280 sp->timecnt = 0;
1281 sp->typecnt = 0;
1282 sp->charcnt = 0;
1283 sp->goback = sp->goahead = false;
1284 init_ttinfo(&sp->ttis[0], 0, false, 0);
1285 strcpy(sp->chars, gmt);
1286 sp->defaulttype = 0;
1287 return 0;
1288 } else {
1289 int err = tzload(name, sp, true);
1290 if (err != 0 && name && name[0] != ':' && tzparse(name, sp, false))
1291 err = 0;
1292 if (err == 0)
1293 scrub_abbrs(sp);
1294 return err;
1298 static void
1299 tzsetlcl(char const *name)
1301 struct state *sp = lclptr;
1302 int lcl = name ? strlen(name) < sizeof lcl_TZname : -1;
1303 if (lcl < 0
1304 ? lcl_is_set < 0
1305 : 0 < lcl_is_set && strcmp(lcl_TZname, name) == 0)
1306 return;
1307 #ifdef ALL_STATE
1308 if (! sp)
1309 lclptr = sp = malloc(sizeof *lclptr);
1310 #endif /* defined ALL_STATE */
1311 if (sp) {
1312 if (zoneinit(sp, name) != 0)
1313 zoneinit(sp, "");
1314 if (0 < lcl)
1315 strcpy(lcl_TZname, name);
1317 settzname();
1318 lcl_is_set = lcl;
1321 #ifdef STD_INSPIRED
1322 void
1323 tzsetwall(void)
1325 if (lock() != 0)
1326 return;
1327 tzsetlcl(NULL);
1328 unlock();
1330 #endif
1332 static void
1333 tzset_unlocked(void)
1335 tzsetlcl(getenv("TZ"));
1338 void
1339 tzset(void)
1341 if (lock() != 0)
1342 return;
1343 tzset_unlocked();
1344 unlock();
1347 static void
1348 gmtcheck(void)
1350 static bool gmt_is_set;
1351 if (lock() != 0)
1352 return;
1353 if (! gmt_is_set) {
1354 #ifdef ALL_STATE
1355 gmtptr = malloc(sizeof *gmtptr);
1356 #endif
1357 if (gmtptr)
1358 gmtload(gmtptr);
1359 gmt_is_set = true;
1361 unlock();
1364 #if NETBSD_INSPIRED
1366 timezone_t
1367 tzalloc(char const *name)
1369 timezone_t sp = malloc(sizeof *sp);
1370 if (sp) {
1371 int err = zoneinit(sp, name);
1372 if (err != 0) {
1373 free(sp);
1374 errno = err;
1375 return NULL;
1378 return sp;
1381 void
1382 tzfree(timezone_t sp)
1384 free(sp);
1388 ** NetBSD 6.1.4 has ctime_rz, but omit it because POSIX says ctime and
1389 ** ctime_r are obsolescent and have potential security problems that
1390 ** ctime_rz would share. Callers can instead use localtime_rz + strftime.
1392 ** NetBSD 6.1.4 has tzgetname, but omit it because it doesn't work
1393 ** in zones with three or more time zone abbreviations.
1394 ** Callers can instead use localtime_rz + strftime.
1397 #endif
1400 ** The easy way to behave "as if no library function calls" localtime
1401 ** is to not call it, so we drop its guts into "localsub", which can be
1402 ** freely called. (And no, the PANS doesn't require the above behavior,
1403 ** but it *is* desirable.)
1405 ** If successful and SETNAME is nonzero,
1406 ** set the applicable parts of tzname, timezone and altzone;
1407 ** however, it's OK to omit this step if the time zone is POSIX-compatible,
1408 ** since in that case tzset should have already done this step correctly.
1409 ** SETNAME's type is intfast32_t for compatibility with gmtsub,
1410 ** but it is actually a boolean and its value should be 0 or 1.
1413 /*ARGSUSED*/
1414 static struct tm *
1415 localsub(struct state const *sp, time_t const *timep, int_fast32_t setname,
1416 struct tm *const tmp)
1418 register const struct ttinfo * ttisp;
1419 register int i;
1420 register struct tm * result;
1421 const time_t t = *timep;
1423 if (sp == NULL) {
1424 /* Don't bother to set tzname etc.; tzset has already done it. */
1425 return gmtsub(gmtptr, timep, 0, tmp);
1427 if ((sp->goback && t < sp->ats[0]) ||
1428 (sp->goahead && t > sp->ats[sp->timecnt - 1])) {
1429 time_t newt = t;
1430 register time_t seconds;
1431 register time_t years;
1433 if (t < sp->ats[0])
1434 seconds = sp->ats[0] - t;
1435 else seconds = t - sp->ats[sp->timecnt - 1];
1436 --seconds;
1437 years = (seconds / SECSPERREPEAT + 1) * YEARSPERREPEAT;
1438 seconds = years * AVGSECSPERYEAR;
1439 if (t < sp->ats[0])
1440 newt += seconds;
1441 else newt -= seconds;
1442 if (newt < sp->ats[0] ||
1443 newt > sp->ats[sp->timecnt - 1])
1444 return NULL; /* "cannot happen" */
1445 result = localsub(sp, &newt, setname, tmp);
1446 if (result) {
1447 register int_fast64_t newy;
1449 newy = result->tm_year;
1450 if (t < sp->ats[0])
1451 newy -= years;
1452 else newy += years;
1453 if (! (INT_MIN <= newy && newy <= INT_MAX))
1454 return NULL;
1455 result->tm_year = newy;
1457 return result;
1459 if (sp->timecnt == 0 || t < sp->ats[0]) {
1460 i = sp->defaulttype;
1461 } else {
1462 register int lo = 1;
1463 register int hi = sp->timecnt;
1465 while (lo < hi) {
1466 register int mid = (lo + hi) >> 1;
1468 if (t < sp->ats[mid])
1469 hi = mid;
1470 else lo = mid + 1;
1472 i = (int) sp->types[lo - 1];
1474 ttisp = &sp->ttis[i];
1476 ** To get (wrong) behavior that's compatible with System V Release 2.0
1477 ** you'd replace the statement below with
1478 ** t += ttisp->tt_gmtoff;
1479 ** timesub(&t, 0L, sp, tmp);
1481 result = timesub(&t, ttisp->tt_gmtoff, sp, tmp);
1482 if (result) {
1483 result->tm_isdst = ttisp->tt_isdst;
1484 #ifdef TM_ZONE
1485 result->TM_ZONE = (char *) &sp->chars[ttisp->tt_abbrind];
1486 #endif /* defined TM_ZONE */
1487 if (setname)
1488 update_tzname_etc(sp, ttisp);
1490 return result;
1493 #if NETBSD_INSPIRED
1495 struct tm *
1496 localtime_rz(struct state *sp, time_t const *timep, struct tm *tmp)
1498 return localsub(sp, timep, 0, tmp);
1501 #endif
1503 static struct tm *
1504 localtime_tzset(time_t const *timep, struct tm *tmp, bool setname)
1506 int err = lock();
1507 if (err) {
1508 errno = err;
1509 return NULL;
1511 if (setname || !lcl_is_set)
1512 tzset_unlocked();
1513 tmp = localsub(lclptr, timep, setname, tmp);
1514 unlock();
1515 return tmp;
1518 struct tm *
1519 localtime(const time_t *timep)
1521 return localtime_tzset(timep, &tm, true);
1524 struct tm *
1525 localtime_r(const time_t *timep, struct tm *tmp)
1527 return localtime_tzset(timep, tmp, false);
1531 ** gmtsub is to gmtime as localsub is to localtime.
1534 static struct tm *
1535 gmtsub(struct state const *sp, time_t const *timep, int_fast32_t offset,
1536 struct tm *tmp)
1538 register struct tm * result;
1540 result = timesub(timep, offset, gmtptr, tmp);
1541 #ifdef TM_ZONE
1543 ** Could get fancy here and deliver something such as
1544 ** "+xx" or "-xx" if offset is non-zero,
1545 ** but this is no time for a treasure hunt.
1547 tmp->TM_ZONE = ((char *)
1548 (offset ? wildabbr : gmtptr ? gmtptr->chars : gmt));
1549 #endif /* defined TM_ZONE */
1550 return result;
1554 * Re-entrant version of gmtime.
1557 struct tm *
1558 gmtime_r(const time_t *timep, struct tm *tmp)
1560 gmtcheck();
1561 return gmtsub(gmtptr, timep, 0, tmp);
1564 struct tm *
1565 gmtime(const time_t *timep)
1567 return gmtime_r(timep, &tm);
1570 #ifdef STD_INSPIRED
1572 struct tm *
1573 offtime(const time_t *timep, long offset)
1575 gmtcheck();
1576 return gmtsub(gmtptr, timep, offset, &tm);
1579 #endif /* defined STD_INSPIRED */
1582 ** Return the number of leap years through the end of the given year
1583 ** where, to make the math easy, the answer for year zero is defined as zero.
1586 static int ATTRIBUTE_PURE
1587 leaps_thru_end_of(register const int y)
1589 return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
1590 -(leaps_thru_end_of(-(y + 1)) + 1);
1593 static struct tm *
1594 timesub(const time_t *timep, int_fast32_t offset,
1595 const struct state *sp, struct tm *tmp)
1597 register const struct lsinfo * lp;
1598 register time_t tdays;
1599 register int idays; /* unsigned would be so 2003 */
1600 register int_fast64_t rem;
1601 int y;
1602 register const int * ip;
1603 register int_fast64_t corr;
1604 register bool hit;
1605 register int i;
1607 corr = 0;
1608 hit = false;
1609 i = (sp == NULL) ? 0 : sp->leapcnt;
1610 while (--i >= 0) {
1611 lp = &sp->lsis[i];
1612 if (*timep >= lp->ls_trans) {
1613 if (*timep == lp->ls_trans) {
1614 hit = ((i == 0 && lp->ls_corr > 0) ||
1615 lp->ls_corr > sp->lsis[i - 1].ls_corr);
1616 if (hit)
1617 while (i > 0 &&
1618 sp->lsis[i].ls_trans ==
1619 sp->lsis[i - 1].ls_trans + 1 &&
1620 sp->lsis[i].ls_corr ==
1621 sp->lsis[i - 1].ls_corr + 1) {
1622 ++hit;
1623 --i;
1626 corr = lp->ls_corr;
1627 break;
1630 y = EPOCH_YEAR;
1631 tdays = *timep / SECSPERDAY;
1632 rem = *timep % SECSPERDAY;
1633 while (tdays < 0 || tdays >= year_lengths[isleap(y)]) {
1634 int newy;
1635 register time_t tdelta;
1636 register int idelta;
1637 register int leapdays;
1639 tdelta = tdays / DAYSPERLYEAR;
1640 if (! ((! TYPE_SIGNED(time_t) || INT_MIN <= tdelta)
1641 && tdelta <= INT_MAX))
1642 goto out_of_range;
1643 idelta = tdelta;
1644 if (idelta == 0)
1645 idelta = (tdays < 0) ? -1 : 1;
1646 newy = y;
1647 if (increment_overflow(&newy, idelta))
1648 goto out_of_range;
1649 leapdays = leaps_thru_end_of(newy - 1) -
1650 leaps_thru_end_of(y - 1);
1651 tdays -= ((time_t) newy - y) * DAYSPERNYEAR;
1652 tdays -= leapdays;
1653 y = newy;
1656 ** Given the range, we can now fearlessly cast...
1658 idays = tdays;
1659 rem += offset - corr;
1660 while (rem < 0) {
1661 rem += SECSPERDAY;
1662 --idays;
1664 while (rem >= SECSPERDAY) {
1665 rem -= SECSPERDAY;
1666 ++idays;
1668 while (idays < 0) {
1669 if (increment_overflow(&y, -1))
1670 goto out_of_range;
1671 idays += year_lengths[isleap(y)];
1673 while (idays >= year_lengths[isleap(y)]) {
1674 idays -= year_lengths[isleap(y)];
1675 if (increment_overflow(&y, 1))
1676 goto out_of_range;
1678 tmp->tm_year = y;
1679 if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE))
1680 goto out_of_range;
1681 tmp->tm_yday = idays;
1683 ** The "extra" mods below avoid overflow problems.
1685 tmp->tm_wday = EPOCH_WDAY +
1686 ((y - EPOCH_YEAR) % DAYSPERWEEK) *
1687 (DAYSPERNYEAR % DAYSPERWEEK) +
1688 leaps_thru_end_of(y - 1) -
1689 leaps_thru_end_of(EPOCH_YEAR - 1) +
1690 idays;
1691 tmp->tm_wday %= DAYSPERWEEK;
1692 if (tmp->tm_wday < 0)
1693 tmp->tm_wday += DAYSPERWEEK;
1694 tmp->tm_hour = (int) (rem / SECSPERHOUR);
1695 rem %= SECSPERHOUR;
1696 tmp->tm_min = (int) (rem / SECSPERMIN);
1698 ** A positive leap second requires a special
1699 ** representation. This uses "... ??:59:60" et seq.
1701 tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
1702 ip = mon_lengths[isleap(y)];
1703 for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
1704 idays -= ip[tmp->tm_mon];
1705 tmp->tm_mday = (int) (idays + 1);
1706 tmp->tm_isdst = 0;
1707 #ifdef TM_GMTOFF
1708 tmp->TM_GMTOFF = offset;
1709 #endif /* defined TM_GMTOFF */
1710 return tmp;
1712 out_of_range:
1713 errno = EOVERFLOW;
1714 return NULL;
1717 char *
1718 ctime(const time_t *timep)
1721 ** Section 4.12.3.2 of X3.159-1989 requires that
1722 ** The ctime function converts the calendar time pointed to by timer
1723 ** to local time in the form of a string. It is equivalent to
1724 ** asctime(localtime(timer))
1726 struct tm *tmp = localtime(timep);
1727 return tmp ? asctime(tmp) : NULL;
1730 char *
1731 ctime_r(const time_t *timep, char *buf)
1733 struct tm mytm;
1734 struct tm *tmp = localtime_r(timep, &mytm);
1735 return tmp ? asctime_r(tmp, buf) : NULL;
1739 ** Adapted from code provided by Robert Elz, who writes:
1740 ** The "best" way to do mktime I think is based on an idea of Bob
1741 ** Kridle's (so its said...) from a long time ago.
1742 ** It does a binary search of the time_t space. Since time_t's are
1743 ** just 32 bits, its a max of 32 iterations (even at 64 bits it
1744 ** would still be very reasonable).
1747 #ifndef WRONG
1748 #define WRONG (-1)
1749 #endif /* !defined WRONG */
1752 ** Normalize logic courtesy Paul Eggert.
1755 static bool
1756 increment_overflow(int *ip, int j)
1758 register int const i = *ip;
1761 ** If i >= 0 there can only be overflow if i + j > INT_MAX
1762 ** or if j > INT_MAX - i; given i >= 0, INT_MAX - i cannot overflow.
1763 ** If i < 0 there can only be overflow if i + j < INT_MIN
1764 ** or if j < INT_MIN - i; given i < 0, INT_MIN - i cannot overflow.
1766 if ((i >= 0) ? (j > INT_MAX - i) : (j < INT_MIN - i))
1767 return true;
1768 *ip += j;
1769 return false;
1772 static bool
1773 increment_overflow32(int_fast32_t *const lp, int const m)
1775 register int_fast32_t const l = *lp;
1777 if ((l >= 0) ? (m > INT_FAST32_MAX - l) : (m < INT_FAST32_MIN - l))
1778 return true;
1779 *lp += m;
1780 return false;
1783 static bool
1784 increment_overflow_time(time_t *tp, int_fast32_t j)
1787 ** This is like
1788 ** 'if (! (time_t_min <= *tp + j && *tp + j <= time_t_max)) ...',
1789 ** except that it does the right thing even if *tp + j would overflow.
1791 if (! (j < 0
1792 ? (TYPE_SIGNED(time_t) ? time_t_min - j <= *tp : -1 - j < *tp)
1793 : *tp <= time_t_max - j))
1794 return true;
1795 *tp += j;
1796 return false;
1799 static bool
1800 normalize_overflow(int *const tensptr, int *const unitsptr, const int base)
1802 register int tensdelta;
1804 tensdelta = (*unitsptr >= 0) ?
1805 (*unitsptr / base) :
1806 (-1 - (-1 - *unitsptr) / base);
1807 *unitsptr -= tensdelta * base;
1808 return increment_overflow(tensptr, tensdelta);
1811 static bool
1812 normalize_overflow32(int_fast32_t *tensptr, int *unitsptr, int base)
1814 register int tensdelta;
1816 tensdelta = (*unitsptr >= 0) ?
1817 (*unitsptr / base) :
1818 (-1 - (-1 - *unitsptr) / base);
1819 *unitsptr -= tensdelta * base;
1820 return increment_overflow32(tensptr, tensdelta);
1823 static int
1824 tmcomp(register const struct tm *const atmp,
1825 register const struct tm *const btmp)
1827 register int result;
1829 if (atmp->tm_year != btmp->tm_year)
1830 return atmp->tm_year < btmp->tm_year ? -1 : 1;
1831 if ((result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
1832 (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
1833 (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
1834 (result = (atmp->tm_min - btmp->tm_min)) == 0)
1835 result = atmp->tm_sec - btmp->tm_sec;
1836 return result;
1839 static time_t
1840 time2sub(struct tm *const tmp,
1841 struct tm *(*funcp)(struct state const *, time_t const *,
1842 int_fast32_t, struct tm *),
1843 struct state const *sp,
1844 const int_fast32_t offset,
1845 bool *okayp,
1846 bool do_norm_secs)
1848 register int dir;
1849 register int i, j;
1850 register int saved_seconds;
1851 register int_fast32_t li;
1852 register time_t lo;
1853 register time_t hi;
1854 int_fast32_t y;
1855 time_t newt;
1856 time_t t;
1857 struct tm yourtm, mytm;
1859 *okayp = false;
1860 yourtm = *tmp;
1861 if (do_norm_secs) {
1862 if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec,
1863 SECSPERMIN))
1864 return WRONG;
1866 if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))
1867 return WRONG;
1868 if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
1869 return WRONG;
1870 y = yourtm.tm_year;
1871 if (normalize_overflow32(&y, &yourtm.tm_mon, MONSPERYEAR))
1872 return WRONG;
1874 ** Turn y into an actual year number for now.
1875 ** It is converted back to an offset from TM_YEAR_BASE later.
1877 if (increment_overflow32(&y, TM_YEAR_BASE))
1878 return WRONG;
1879 while (yourtm.tm_mday <= 0) {
1880 if (increment_overflow32(&y, -1))
1881 return WRONG;
1882 li = y + (1 < yourtm.tm_mon);
1883 yourtm.tm_mday += year_lengths[isleap(li)];
1885 while (yourtm.tm_mday > DAYSPERLYEAR) {
1886 li = y + (1 < yourtm.tm_mon);
1887 yourtm.tm_mday -= year_lengths[isleap(li)];
1888 if (increment_overflow32(&y, 1))
1889 return WRONG;
1891 for ( ; ; ) {
1892 i = mon_lengths[isleap(y)][yourtm.tm_mon];
1893 if (yourtm.tm_mday <= i)
1894 break;
1895 yourtm.tm_mday -= i;
1896 if (++yourtm.tm_mon >= MONSPERYEAR) {
1897 yourtm.tm_mon = 0;
1898 if (increment_overflow32(&y, 1))
1899 return WRONG;
1902 if (increment_overflow32(&y, -TM_YEAR_BASE))
1903 return WRONG;
1904 if (! (INT_MIN <= y && y <= INT_MAX))
1905 return WRONG;
1906 yourtm.tm_year = y;
1907 if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN)
1908 saved_seconds = 0;
1909 else if (y + TM_YEAR_BASE < EPOCH_YEAR) {
1911 ** We can't set tm_sec to 0, because that might push the
1912 ** time below the minimum representable time.
1913 ** Set tm_sec to 59 instead.
1914 ** This assumes that the minimum representable time is
1915 ** not in the same minute that a leap second was deleted from,
1916 ** which is a safer assumption than using 58 would be.
1918 if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN))
1919 return WRONG;
1920 saved_seconds = yourtm.tm_sec;
1921 yourtm.tm_sec = SECSPERMIN - 1;
1922 } else {
1923 saved_seconds = yourtm.tm_sec;
1924 yourtm.tm_sec = 0;
1927 ** Do a binary search (this works whatever time_t's type is).
1929 lo = time_t_min;
1930 hi = time_t_max;
1931 for ( ; ; ) {
1932 t = lo / 2 + hi / 2;
1933 if (t < lo)
1934 t = lo;
1935 else if (t > hi)
1936 t = hi;
1937 if (! funcp(sp, &t, offset, &mytm)) {
1939 ** Assume that t is too extreme to be represented in
1940 ** a struct tm; arrange things so that it is less
1941 ** extreme on the next pass.
1943 dir = (t > 0) ? 1 : -1;
1944 } else dir = tmcomp(&mytm, &yourtm);
1945 if (dir != 0) {
1946 if (t == lo) {
1947 if (t == time_t_max)
1948 return WRONG;
1949 ++t;
1950 ++lo;
1951 } else if (t == hi) {
1952 if (t == time_t_min)
1953 return WRONG;
1954 --t;
1955 --hi;
1957 if (lo > hi)
1958 return WRONG;
1959 if (dir > 0)
1960 hi = t;
1961 else lo = t;
1962 continue;
1964 #if defined TM_GMTOFF && ! UNINIT_TRAP
1965 if (mytm.TM_GMTOFF != yourtm.TM_GMTOFF
1966 && (yourtm.TM_GMTOFF < 0
1967 ? (-SECSPERDAY <= yourtm.TM_GMTOFF
1968 && (mytm.TM_GMTOFF <=
1969 (SMALLEST (INT_FAST32_MAX, LONG_MAX)
1970 + yourtm.TM_GMTOFF)))
1971 : (yourtm.TM_GMTOFF <= SECSPERDAY
1972 && ((BIGGEST (INT_FAST32_MIN, LONG_MIN)
1973 + yourtm.TM_GMTOFF)
1974 <= mytm.TM_GMTOFF)))) {
1975 /* MYTM matches YOURTM except with the wrong UTC offset.
1976 YOURTM.TM_GMTOFF is plausible, so try it instead.
1977 It's OK if YOURTM.TM_GMTOFF contains uninitialized data,
1978 since the guess gets checked. */
1979 time_t altt = t;
1980 int_fast32_t diff = mytm.TM_GMTOFF - yourtm.TM_GMTOFF;
1981 if (!increment_overflow_time(&altt, diff)) {
1982 struct tm alttm;
1983 if (funcp(sp, &altt, offset, &alttm)
1984 && alttm.tm_isdst == mytm.tm_isdst
1985 && alttm.TM_GMTOFF == yourtm.TM_GMTOFF
1986 && tmcomp(&alttm, &yourtm) == 0) {
1987 t = altt;
1988 mytm = alttm;
1992 #endif
1993 if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
1994 break;
1996 ** Right time, wrong type.
1997 ** Hunt for right time, right type.
1998 ** It's okay to guess wrong since the guess
1999 ** gets checked.
2001 if (sp == NULL)
2002 return WRONG;
2003 for (i = sp->typecnt - 1; i >= 0; --i) {
2004 if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
2005 continue;
2006 for (j = sp->typecnt - 1; j >= 0; --j) {
2007 if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
2008 continue;
2009 newt = t + sp->ttis[j].tt_gmtoff -
2010 sp->ttis[i].tt_gmtoff;
2011 if (! funcp(sp, &newt, offset, &mytm))
2012 continue;
2013 if (tmcomp(&mytm, &yourtm) != 0)
2014 continue;
2015 if (mytm.tm_isdst != yourtm.tm_isdst)
2016 continue;
2018 ** We have a match.
2020 t = newt;
2021 goto label;
2024 return WRONG;
2026 label:
2027 newt = t + saved_seconds;
2028 if ((newt < t) != (saved_seconds < 0))
2029 return WRONG;
2030 t = newt;
2031 if (funcp(sp, &t, offset, tmp))
2032 *okayp = true;
2033 return t;
2036 static time_t
2037 time2(struct tm * const tmp,
2038 struct tm *(*funcp)(struct state const *, time_t const *,
2039 int_fast32_t, struct tm *),
2040 struct state const *sp,
2041 const int_fast32_t offset,
2042 bool *okayp)
2044 time_t t;
2047 ** First try without normalization of seconds
2048 ** (in case tm_sec contains a value associated with a leap second).
2049 ** If that fails, try with normalization of seconds.
2051 t = time2sub(tmp, funcp, sp, offset, okayp, false);
2052 return *okayp ? t : time2sub(tmp, funcp, sp, offset, okayp, true);
2055 static time_t
2056 time1(struct tm *const tmp,
2057 struct tm *(*funcp) (struct state const *, time_t const *,
2058 int_fast32_t, struct tm *),
2059 struct state const *sp,
2060 const int_fast32_t offset)
2062 register time_t t;
2063 register int samei, otheri;
2064 register int sameind, otherind;
2065 register int i;
2066 register int nseen;
2067 char seen[TZ_MAX_TYPES];
2068 unsigned char types[TZ_MAX_TYPES];
2069 bool okay;
2071 if (tmp == NULL) {
2072 errno = EINVAL;
2073 return WRONG;
2075 if (tmp->tm_isdst > 1)
2076 tmp->tm_isdst = 1;
2077 t = time2(tmp, funcp, sp, offset, &okay);
2078 if (okay)
2079 return t;
2080 if (tmp->tm_isdst < 0)
2081 #ifdef PCTS
2083 ** POSIX Conformance Test Suite code courtesy Grant Sullivan.
2085 tmp->tm_isdst = 0; /* reset to std and try again */
2086 #else
2087 return t;
2088 #endif /* !defined PCTS */
2090 ** We're supposed to assume that somebody took a time of one type
2091 ** and did some math on it that yielded a "struct tm" that's bad.
2092 ** We try to divine the type they started from and adjust to the
2093 ** type they need.
2095 if (sp == NULL)
2096 return WRONG;
2097 for (i = 0; i < sp->typecnt; ++i)
2098 seen[i] = false;
2099 nseen = 0;
2100 for (i = sp->timecnt - 1; i >= 0; --i)
2101 if (!seen[sp->types[i]]) {
2102 seen[sp->types[i]] = true;
2103 types[nseen++] = sp->types[i];
2105 for (sameind = 0; sameind < nseen; ++sameind) {
2106 samei = types[sameind];
2107 if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
2108 continue;
2109 for (otherind = 0; otherind < nseen; ++otherind) {
2110 otheri = types[otherind];
2111 if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
2112 continue;
2113 tmp->tm_sec += sp->ttis[otheri].tt_gmtoff -
2114 sp->ttis[samei].tt_gmtoff;
2115 tmp->tm_isdst = !tmp->tm_isdst;
2116 t = time2(tmp, funcp, sp, offset, &okay);
2117 if (okay)
2118 return t;
2119 tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff -
2120 sp->ttis[samei].tt_gmtoff;
2121 tmp->tm_isdst = !tmp->tm_isdst;
2124 return WRONG;
2127 static time_t
2128 mktime_tzname(struct state *sp, struct tm *tmp, bool setname)
2130 if (sp)
2131 return time1(tmp, localsub, sp, setname);
2132 else {
2133 gmtcheck();
2134 return time1(tmp, gmtsub, gmtptr, 0);
2138 #if NETBSD_INSPIRED
2140 time_t
2141 mktime_z(struct state *sp, struct tm *tmp)
2143 return mktime_tzname(sp, tmp, false);
2146 #endif
2148 time_t
2149 mktime(struct tm *tmp)
2151 time_t t;
2152 int err = lock();
2153 if (err) {
2154 errno = err;
2155 return -1;
2157 tzset_unlocked();
2158 t = mktime_tzname(lclptr, tmp, true);
2159 unlock();
2160 return t;
2163 #ifdef STD_INSPIRED
2165 time_t
2166 timelocal(struct tm *tmp)
2168 if (tmp != NULL)
2169 tmp->tm_isdst = -1; /* in case it wasn't initialized */
2170 return mktime(tmp);
2173 time_t
2174 timegm(struct tm *tmp)
2176 return timeoff(tmp, 0);
2179 time_t
2180 timeoff(struct tm *tmp, long offset)
2182 if (tmp)
2183 tmp->tm_isdst = 0;
2184 gmtcheck();
2185 return time1(tmp, gmtsub, gmtptr, offset);
2188 #endif /* defined STD_INSPIRED */
2191 ** XXX--is the below the right way to conditionalize??
2194 #ifdef STD_INSPIRED
2197 ** IEEE Std 1003.1-1988 (POSIX) legislates that 536457599
2198 ** shall correspond to "Wed Dec 31 23:59:59 UTC 1986", which
2199 ** is not the case if we are accounting for leap seconds.
2200 ** So, we provide the following conversion routines for use
2201 ** when exchanging timestamps with POSIX conforming systems.
2204 static int_fast64_t
2205 leapcorr(struct state const *sp, time_t t)
2207 register struct lsinfo const * lp;
2208 register int i;
2210 i = sp->leapcnt;
2211 while (--i >= 0) {
2212 lp = &sp->lsis[i];
2213 if (t >= lp->ls_trans)
2214 return lp->ls_corr;
2216 return 0;
2219 NETBSD_INSPIRED_EXTERN time_t ATTRIBUTE_PURE
2220 time2posix_z(struct state *sp, time_t t)
2222 return t - leapcorr(sp, t);
2225 time_t
2226 time2posix(time_t t)
2228 int err = lock();
2229 if (err) {
2230 errno = err;
2231 return -1;
2233 if (!lcl_is_set)
2234 tzset_unlocked();
2235 if (lclptr)
2236 t = time2posix_z(lclptr, t);
2237 unlock();
2238 return t;
2241 NETBSD_INSPIRED_EXTERN time_t ATTRIBUTE_PURE
2242 posix2time_z(struct state *sp, time_t t)
2244 time_t x;
2245 time_t y;
2247 ** For a positive leap second hit, the result
2248 ** is not unique. For a negative leap second
2249 ** hit, the corresponding time doesn't exist,
2250 ** so we return an adjacent second.
2252 x = t + leapcorr(sp, t);
2253 y = x - leapcorr(sp, x);
2254 if (y < t) {
2255 do {
2256 x++;
2257 y = x - leapcorr(sp, x);
2258 } while (y < t);
2259 x -= y != t;
2260 } else if (y > t) {
2261 do {
2262 --x;
2263 y = x - leapcorr(sp, x);
2264 } while (y > t);
2265 x += y != t;
2267 return x;
2270 time_t
2271 posix2time(time_t t)
2273 int err = lock();
2274 if (err) {
2275 errno = err;
2276 return -1;
2278 if (!lcl_is_set)
2279 tzset_unlocked();
2280 if (lclptr)
2281 t = posix2time_z(lclptr, t);
2282 unlock();
2283 return t;
2286 #endif /* defined STD_INSPIRED */
2288 #if defined time_tz || EPOCH_LOCAL || EPOCH_OFFSET != 0
2290 # ifndef USG_COMPAT
2291 # define daylight 0
2292 # define timezone 0
2293 # endif
2294 # ifndef ALTZONE
2295 # define altzone 0
2296 # endif
2298 /* Convert from the underlying system's time_t to the ersatz time_tz,
2299 which is called 'time_t' in this file. Typically, this merely
2300 converts the time's integer width. On some platforms, the system
2301 time is local time not UT, or uses some epoch other than the POSIX
2302 epoch.
2304 Although this code appears to define a function named 'time' that
2305 returns time_t, the macros in private.h cause this code to actually
2306 define a function named 'tz_time' that returns tz_time_t. The call
2307 to sys_time invokes the underlying system's 'time' function. */
2309 time_t
2310 time(time_t *p)
2312 time_t r = sys_time(0);
2313 if (r != (time_t) -1) {
2314 int_fast32_t offset = EPOCH_LOCAL ? (daylight ? timezone : altzone) : 0;
2315 if (increment_overflow32(&offset, -EPOCH_OFFSET)
2316 || increment_overflow_time (&r, offset)) {
2317 errno = EOVERFLOW;
2318 r = -1;
2321 if (p)
2322 *p = r;
2323 return r;
2326 #endif