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