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