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