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