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