1b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
2b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru** This file is in the public domain, so clarified as of
3b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru** 2006-07-17 by Arthur David Olson.
4b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
5b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
6b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic char	elsieid[] = "@(#)zic.c	8.18";
7b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
8b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "private.h"
9b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "locale.h"
10b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "tzfile.h"
11b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
12b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define	ZIC_VERSION	'2'
13b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
14b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querutypedef int_fast64_t	zic_t;
15b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
16b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifndef ZIC_MAX_ABBR_LEN_WO_WARN
17b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define ZIC_MAX_ABBR_LEN_WO_WARN	6
18b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif /* !defined ZIC_MAX_ABBR_LEN_WO_WARN */
19b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
20b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if HAVE_SYS_STAT_H
21b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "sys/stat.h"
22b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
23b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef S_IRUSR
24b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define MKDIR_UMASK (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
25b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#else
26b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define MKDIR_UMASK 0755
27b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
28b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
29b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* Enable extensions and modifications for ICU. */
30b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define ICU
31b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
32b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* Continue executing after link failure. Even if ICU is undefined
33b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * (for vanilla zic behavior), ICU_LINKS should be defined, since zic
34b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * appears to fail on the 2003 data the first time through during the
35b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * linking phase. Running zic twice, with ICU_LINKS defined, causes
36b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * links to be handled correctly. */
37b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define ICU_LINKS
38b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
39b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef ICU
40b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "tz2icu.h"
41b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
42b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
43b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
44b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru** On some ancient hosts, predicates like `isspace(C)' are defined
45b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru** only if isascii(C) || C == EOF. Modern hosts obey the C Standard,
46b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru** which says they are defined only if C == ((unsigned char) C) || C == EOF.
47b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru** Neither the C Standard nor Posix require that `isascii' exist.
48b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru** For portability, we check both ancient and modern requirements.
49b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru** If isascii is not defined, the isascii check succeeds trivially.
50b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
51b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "ctype.h"
52b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifndef isascii
53b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define isascii(x) 1
54b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
55b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
56b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define OFFSET_STRLEN_MAXIMUM	(7 + INT_STRLEN_MAXIMUM(long))
57b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define RULE_STRLEN_MAXIMUM	8	/* "Mdd.dd.d" */
58b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
59b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define end(cp)	(strchr((cp), '\0'))
60b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
61b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustruct rule {
62b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	const char *	r_filename;
63b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	int		r_linenum;
64b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	const char *	r_name;
65b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
66b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	int		r_loyear;	/* for example, 1986 */
67b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	int		r_hiyear;	/* for example, 1986 */
68b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	const char *	r_yrtype;
69b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	int		r_lowasnum;
70b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	int		r_hiwasnum;
71b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
72b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	int		r_month;	/* 0..11 */
73b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
74b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	int		r_dycode;	/* see below */
75b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	int		r_dayofmonth;
76b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	int		r_wday;
77b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
78b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	long		r_tod;		/* time from midnight */
79b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	int		r_todisstd;	/* above is standard time if TRUE */
80b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					/* or wall clock time if FALSE */
81b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	int		r_todisgmt;	/* above is GMT if TRUE */
82b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					/* or local time if FALSE */
83b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	long		r_stdoff;	/* offset from standard time */
84b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	const char *	r_abbrvar;	/* variable part of abbreviation */
85b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
86b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	int		r_todo;		/* a rule to do (used in outzone) */
87b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	zic_t		r_temp;		/* used in outzone */
88b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
89b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
90b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
91b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru**	r_dycode		r_dayofmonth	r_wday
92b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
93b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
94b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define DC_DOM		0	/* 1..31 */	/* unused */
95b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define DC_DOWGEQ	1	/* 1..31 */	/* 0..6 (Sun..Sat) */
96b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define DC_DOWLEQ	2	/* 1..31 */	/* 0..6 (Sun..Sat) */
97b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
98b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustruct zone {
99b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	const char *	z_filename;
100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	int		z_linenum;
101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	const char *	z_name;
103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	long		z_gmtoff;
104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	const char *	z_rule;
105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	const char *	z_format;
106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	long		z_stdoff;
108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	struct rule *	z_rules;
110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	int		z_nrules;
111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	struct rule	z_untilrule;
113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	zic_t		z_untiltime;
114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
116b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruextern int	getopt(int argc, char * const argv[],
117b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru			const char * options);
118b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruextern int	link(const char * fromname, const char * toname);
119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruextern char *	optarg;
120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruextern int	optind;
121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
122b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void	addtt(zic_t starttime, int type);
123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef ICU
124b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int	addtype(long gmtoff, long rawoff, long dstoff,
125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				const char * abbr, int isdst,
126b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru				int ttisstd, int ttisgmt);
127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#else
128b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int	addtype(long gmtoff, const char * abbr, int isdst,
129b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru				int ttisstd, int ttisgmt);
130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
131b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void	leapadd(zic_t t, int positive, int rolling, int count);
132b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void	adjleap(void);
133b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void	associate(void);
134b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int	ciequal(const char * ap, const char * bp);
135b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void	convert(long val, char * buf);
136b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void	convert64(zic_t val, char * buf);
137b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void	dolink(const char * fromfield, const char * tofield);
138b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void	doabbr(char * abbr, const char * format,
139b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru			const char * letters, int isdst, int doquotes);
140b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void	eat(const char * name, int num);
141b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void	eats(const char * name, int num,
142b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru			const char * rname, int rnum);
143b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic long	eitol(int i);
144b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void	error(const char * message);
145b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic char **	getfields(char * buf);
146b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic long	gethms(const char * string, const char * errstrng,
147b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru			int signable);
148b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void	infile(const char * filename);
149b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void	inleap(char ** fields, int nfields);
150b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void	inlink(char ** fields, int nfields);
151b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void	inrule(char ** fields, int nfields);
152b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int	inzcont(char ** fields, int nfields);
153b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int	inzone(char ** fields, int nfields);
154b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int	inzsub(char ** fields, int nfields, int iscont);
155b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int	is32(zic_t x);
156b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int	itsabbr(const char * abbr, const char * word);
157b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int	itsdir(const char * name);
158b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int	lowerit(int c);
159b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic char *	memcheck(char * tocheck);
160b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int	mkdirs(char * filename);
161b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void	newabbr(const char * abbr);
162b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic long	oadd(long t1, long t2);
163b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void	outzone(const struct zone * zp, int ntzones);
164b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void	puttzcode(long code, FILE * fp);
165b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void	puttzcode64(zic_t code, FILE * fp);
166b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int	rcomp(const void * leftp, const void * rightp);
167b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic zic_t	rpytime(const struct rule * rp, int wantedy);
168b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void	rulesub(struct rule * rp,
169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			const char * loyearp, const char * hiyearp,
170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			const char * typep, const char * monthp,
171b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru			const char * dayp, const char * timep);
172b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int 	stringoffset(char * result, long offset);
173b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int	stringrule(char * result, const struct rule * rp,
174b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru			long dstoff, long gmtoff);
175b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void 	stringzone(char * result,
176b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru			const struct zone * zp, int ntzones);
177b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void	setboundaries(void);
178b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic zic_t	tadd(zic_t t1, long t2);
179b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void	usage(FILE *stream, int status);
180b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void	writezone(const char * name, const char * string);
181b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int	yearistype(int year, const char * type);
182b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#ifdef ICU
183b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void	emit_icu_zone(FILE* f, const char* zoneName, int zoneOffset,
184b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru					const struct rule* rule,
185b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru					int ruleIndex, int startYear);
186b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void	emit_icu_link(FILE* f, const char* from, const char* to);
187b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void	emit_icu_rule(FILE* f, const struct rule* r, int ruleIndex);
188b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int	add_icu_final_rules(const struct rule* r1, const struct rule* r2);
189b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif
190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int		charcnt;
192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int		errors;
193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char *	filename;
194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int		leapcnt;
195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int		leapseen;
196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int		leapminyear;
197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int		leapmaxyear;
198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int		linenum;
199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int		max_abbrvar_len;
200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int		max_format_len;
201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic zic_t		max_time;
202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int		max_year;
203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic zic_t		min_time;
204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int		min_year;
205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int		noise;
206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char *	rfilename;
207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int		rlinenum;
208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char *	progname;
209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int		timecnt;
210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int		typecnt;
211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru** Line codes.
214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define LC_RULE		0
217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define LC_ZONE		1
218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define LC_LINK		2
219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define LC_LEAP		3
220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru** Which fields are which on a Zone line.
223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define ZF_NAME		1
226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define ZF_GMTOFF	2
227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define ZF_RULE		3
228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define ZF_FORMAT	4
229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define ZF_TILYEAR	5
230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define ZF_TILMONTH	6
231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define ZF_TILDAY	7
232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define ZF_TILTIME	8
233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define ZONE_MINFIELDS	5
234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define ZONE_MAXFIELDS	9
235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru** Which fields are which on a Zone continuation line.
238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define ZFC_GMTOFF	0
241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define ZFC_RULE	1
242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define ZFC_FORMAT	2
243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define ZFC_TILYEAR	3
244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define ZFC_TILMONTH	4
245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define ZFC_TILDAY	5
246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define ZFC_TILTIME	6
247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define ZONEC_MINFIELDS	3
248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define ZONEC_MAXFIELDS	7
249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru** Which files are which on a Rule line.
252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define RF_NAME		1
255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define RF_LOYEAR	2
256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define RF_HIYEAR	3
257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define RF_COMMAND	4
258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define RF_MONTH	5
259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define RF_DAY		6
260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define RF_TOD		7
261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define RF_STDOFF	8
262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define RF_ABBRVAR	9
263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define RULE_FIELDS	10
264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru** Which fields are which on a Link line.
267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
269b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define LF_FROM		1
270b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define LF_TO		2
271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define LINK_FIELDS	3
272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru** Which fields are which on a Leap line.
275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define LP_YEAR		1
278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define LP_MONTH	2
279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define LP_DAY		3
280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define LP_TIME		4
281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define LP_CORR		5
282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define LP_ROLL		6
283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define LEAP_FIELDS	7
284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
285b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru** Year synonyms.
287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define YR_MINIMUM	0
290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define YR_MAXIMUM	1
291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define YR_ONLY		2
292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic struct rule *	rules;
294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int		nrules;	/* number of rules */
295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic struct zone *	zones;
297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int		nzones;	/* number of zones */
298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustruct link {
300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	const char *	l_filename;
301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	int		l_linenum;
302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	const char *	l_from;
303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	const char *	l_to;
304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic struct link *	links;
307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int		nlinks;
308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustruct lookup {
310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	const char *	l_word;
311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	const int	l_value;
312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef ICU
315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* Indices into rules[] for final rules.  They will occur in pairs,
316b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * with finalRules[i] occurring before finalRules[i+1] in the year.
317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Each zone need only store a start year, a standard offset, and an
318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * index into finalRules[].  FinalRules[] are aliases into rules[]. */
319b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const struct rule **	finalRules;
320b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int					finalRulesCount;
321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
323b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic struct lookup const *	byword(const char * string,
324b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru					const struct lookup * lp);
325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic struct lookup const	line_codes[] = {
327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{ "Rule",	LC_RULE },
328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{ "Zone",	LC_ZONE },
329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{ "Link",	LC_LINK },
330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{ "Leap",	LC_LEAP },
331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{ NULL,		0}
332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic struct lookup const	mon_names[] = {
335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{ "January",	TM_JANUARY },
336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{ "February",	TM_FEBRUARY },
337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{ "March",	TM_MARCH },
338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{ "April",	TM_APRIL },
339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{ "May",	TM_MAY },
340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{ "June",	TM_JUNE },
341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{ "July",	TM_JULY },
342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{ "August",	TM_AUGUST },
343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{ "September",	TM_SEPTEMBER },
344b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{ "October",	TM_OCTOBER },
345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{ "November",	TM_NOVEMBER },
346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{ "December",	TM_DECEMBER },
347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{ NULL,		0 }
348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic struct lookup const	wday_names[] = {
351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{ "Sunday",	TM_SUNDAY },
352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{ "Monday",	TM_MONDAY },
353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{ "Tuesday",	TM_TUESDAY },
354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{ "Wednesday",	TM_WEDNESDAY },
355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{ "Thursday",	TM_THURSDAY },
356b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{ "Friday",	TM_FRIDAY },
357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{ "Saturday",	TM_SATURDAY },
358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{ NULL,		0 }
359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic struct lookup const	lasts[] = {
362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{ "last-Sunday",	TM_SUNDAY },
363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{ "last-Monday",	TM_MONDAY },
364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{ "last-Tuesday",	TM_TUESDAY },
365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{ "last-Wednesday",	TM_WEDNESDAY },
366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{ "last-Thursday",	TM_THURSDAY },
367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{ "last-Friday",	TM_FRIDAY },
368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{ "last-Saturday",	TM_SATURDAY },
369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{ NULL,			0 }
370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic struct lookup const	begin_years[] = {
373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{ "minimum",	YR_MINIMUM },
374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{ "maximum",	YR_MAXIMUM },
375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{ NULL,		0 }
376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic struct lookup const	end_years[] = {
379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{ "minimum",	YR_MINIMUM },
380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{ "maximum",	YR_MAXIMUM },
381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{ "only",	YR_ONLY },
382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{ NULL,		0 }
383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic struct lookup const	leap_types[] = {
386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{ "Rolling",	TRUE },
387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{ "Stationary",	FALSE },
388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{ NULL,		0 }
389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const int	len_months[2][MONSPERYEAR] = {
392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const int	len_years[2] = {
397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	DAYSPERNYEAR, DAYSPERLYEAR
398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic struct attype {
401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	zic_t		at;
402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	unsigned char	type;
403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}			attypes[TZ_MAX_TIMES];
404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic long		gmtoffs[TZ_MAX_TYPES];
405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef ICU
406b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* gmtoffs[i] = rawoffs[i] + dstoffs[i] */
407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic long		rawoffs[TZ_MAX_TYPES];
408b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic long		dstoffs[TZ_MAX_TYPES];
409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
410b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic char		isdsts[TZ_MAX_TYPES];
411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic unsigned char	abbrinds[TZ_MAX_TYPES];
412b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic char		ttisstds[TZ_MAX_TYPES];
413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic char		ttisgmts[TZ_MAX_TYPES];
414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic char		chars[TZ_MAX_CHARS];
415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic zic_t		trans[TZ_MAX_LEAPS];
416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic long		corr[TZ_MAX_LEAPS];
417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic char		roll[TZ_MAX_LEAPS];
418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru** Memory allocation.
421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic char *
424b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querumemcheck(ptr)
425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruchar * const	ptr;
426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (ptr == NULL) {
428b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		const char *e = strerror(errno);
429b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
430b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		(void) fprintf(stderr, _("%s: Memory exhausted: %s\n"),
431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			progname, e);
432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		exit(EXIT_FAILURE);
433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	return ptr;
435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define emalloc(size)		memcheck(imalloc(size))
438b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define erealloc(ptr, size)	memcheck(irealloc((ptr), (size)))
439b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define ecpyalloc(ptr)		memcheck(icpyalloc(ptr))
440b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define ecatalloc(oldp, newp)	memcheck(icatalloc((oldp), (newp)))
441b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
442b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
443b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru** Error handling.
444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void
447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querueats(name, num, rname, rnum)
448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst char * const	name;
449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst int		num;
450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst char * const	rname;
451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst int		rnum;
452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
453b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	filename = name;
454b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	linenum = num;
455b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	rfilename = rname;
456b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	rlinenum = rnum;
457b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void
460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querueat(name, num)
461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst char * const	name;
462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst int		num;
463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	eats(name, num, (char *) NULL, -1);
465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void
468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruerror(string)
469b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst char * const	string;
470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	/*
472b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	** Match the format of "cc" to allow sh users to
473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	**	zic ... 2>&1 | error -t "*" -v
474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	** on BSD systems.
475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	*/
476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	(void) fprintf(stderr, _("\"%s\", line %d: %s"),
477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		filename, linenum, string);
478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (rfilename != NULL)
479b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		(void) fprintf(stderr, _(" (rule from \"%s\", line %d)"),
480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			rfilename, rlinenum);
481b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	(void) fprintf(stderr, "\n");
482b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	++errors;
483b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
484b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
485b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void
486b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruwarning(string)
487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst char * const	string;
488b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	char *	cp;
490b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	cp = ecpyalloc(_("warning: "));
492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	cp = ecatalloc(cp, string);
493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	error(cp);
494b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	ifree(cp);
495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	--errors;
496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
497b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void
499b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruusage(FILE *stream, int status)
500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
501b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	(void) fprintf(stream, _("%s: usage is %s \
502b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru[ --version ] [ --help ] [ -v ] [ -l localtime ] [ -p posixrules ] \\\n\
503b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru\t[ -d directory ] [ -L leapseconds ] [ -y yearistype ] [ filename ... ]\n\
504b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru\n\
505b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruReport bugs to tz@elsie.nci.nih.gov.\n"),
506b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru		       progname, progname);
507b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	exit(status);
508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef ICU
511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* File into which we will write supplemental ICU data. */
512b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic FILE *	icuFile;
513b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
514b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void
515b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruemit_icu_zone(FILE* f, const char* zoneName, int zoneOffset,
516b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru					const struct rule* rule,
517b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru					int ruleIndex, int startYear) {
518b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	/* machine-readable section */
519b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	fprintf(f, "zone %s %d %d %s", zoneName, zoneOffset, startYear, rule->r_name);
520b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
521b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	/* human-readable section */
522b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	fprintf(f, " # zone %s, offset %d, year >= %d, rule %s (%d)\n",
523b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru			zoneName, zoneOffset, startYear,
524b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru			rule->r_name, ruleIndex);
525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
527b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void
528b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruemit_icu_link(FILE* f, const char* from, const char* to) {
529b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	/* machine-readable section */
530b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	fprintf(f, "link %s %s\n", from, to);
531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
533b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char* DYCODE[] = {"DOM", "DOWGEQ", "DOWLEQ"};
534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
535b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void
536b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruemit_icu_rule(FILE* f, const struct rule* r, int ruleIndex) {
537b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	if (r->r_yrtype != NULL) {
538b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru		warning("year types not supported by ICU");
539b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru		fprintf(stderr, "rule %s, file %s, line %d\n",
540b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru				r->r_name, r->r_filename, r->r_linenum);
541b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
542b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
543b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	/* machine-readable section */
544b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	fprintf(f, "rule %s %s %d %d %d %ld %d %d %ld",
545b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru			r->r_name, DYCODE[r->r_dycode],
546b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru			r->r_month, r->r_dayofmonth,
547b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru			(r->r_dycode == DC_DOM ? -1 : r->r_wday),
548b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru			r->r_tod, r->r_todisstd, r->r_todisgmt, r->r_stdoff
549b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru			);
550b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
551b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	/* human-readable section */
552b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	fprintf(f, " # %d: %s, file %s, line %d",
553b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru			ruleIndex, r->r_name, r->r_filename, r->r_linenum);
554b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	fprintf(f, ", mode %s", DYCODE[r->r_dycode]);
555b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	fprintf(f, ", %s, dom %d", mon_names[r->r_month].l_word, r->r_dayofmonth);
556b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	if (r->r_dycode != DC_DOM) {
557b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru		fprintf(f, ", %s", wday_names[r->r_wday].l_word);
558b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	}
559b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	fprintf(f, ", time %ld", r->r_tod);
560b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	fprintf(f, ", isstd %d", r->r_todisstd);
561b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	fprintf(f, ", isgmt %d", r->r_todisgmt);
562b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	fprintf(f, ", offset %ld", r->r_stdoff);
563b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	fprintf(f, "\n");
564b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
565b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
566b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int
567b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruadd_icu_final_rules(const struct rule* r1, const struct rule* r2) {
568b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	int i;
569b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
570b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	for (i=0; i<finalRulesCount; ++i) { /* i+=2 should work too */
571b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru		if (r1==finalRules[i]) return i; /* [sic] pointer comparison */
572b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	}
573b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
574b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	finalRules = (const struct rule**) (void*) erealloc((char *) finalRules,
575b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru				(finalRulesCount + 2) * sizeof(*finalRules));
576b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	finalRules[finalRulesCount++] = r1;
577b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	finalRules[finalRulesCount++] = r2;
578b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	return finalRulesCount - 2;
579b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
580b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
581b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
582b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char *	psxrules;
583b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char *	lcltime;
584b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char *	directory;
585b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char *	leapsec;
586b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char *	yitcommand;
587b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
588b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint
589b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querumain(argc, argv)
590b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint	argc;
591b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruchar *	argv[];
592b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
593b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register int	i;
594b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register int	j;
595b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register int	c;
596b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
597b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef unix
598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	(void) umask(umask(S_IWGRP | S_IWOTH) | (S_IWGRP | S_IWOTH));
599b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif /* defined unix */
600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if HAVE_GETTEXT
601b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	(void) setlocale(LC_ALL, "");
602b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef TZ_DOMAINDIR
603b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	(void) bindtextdomain(TZ_DOMAIN, TZ_DOMAINDIR);
604b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif /* defined TEXTDOMAINDIR */
605b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	(void) textdomain(TZ_DOMAIN);
606b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif /* HAVE_GETTEXT */
607b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	progname = argv[0];
608b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (TYPE_BIT(zic_t) < 64) {
609b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		(void) fprintf(stderr, "%s: %s\n", progname,
610b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			_("wild compilation-time specification of zic_t"));
611b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		exit(EXIT_FAILURE);
612b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
613b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	for (i = 1; i < argc; ++i)
614b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (strcmp(argv[i], "--version") == 0) {
615b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			(void) printf("%s\n", elsieid);
616b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			exit(EXIT_SUCCESS);
617b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru		} else if (strcmp(argv[i], "--help") == 0) {
618b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru			usage(stdout, EXIT_SUCCESS);
619b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
620b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	while ((c = getopt(argc, argv, "d:l:p:L:vsy:")) != EOF && c != -1)
621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		switch (c) {
622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			default:
623b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru				usage(stderr, EXIT_FAILURE);
624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			case 'd':
625b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				if (directory == NULL)
626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					directory = optarg;
627b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				else {
628b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					(void) fprintf(stderr,
629b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru_("%s: More than one -d option specified\n"),
630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru						progname);
631b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					exit(EXIT_FAILURE);
632b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				}
633b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				break;
634b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			case 'l':
635b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				if (lcltime == NULL)
636b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					lcltime = optarg;
637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				else {
638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					(void) fprintf(stderr,
639b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru_("%s: More than one -l option specified\n"),
640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru						progname);
641b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					exit(EXIT_FAILURE);
642b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				}
643b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				break;
644b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			case 'p':
645b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				if (psxrules == NULL)
646b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					psxrules = optarg;
647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				else {
648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					(void) fprintf(stderr,
649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru_("%s: More than one -p option specified\n"),
650b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru						progname);
651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					exit(EXIT_FAILURE);
652b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				}
653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				break;
654b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			case 'y':
655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				if (yitcommand == NULL)
656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					yitcommand = optarg;
657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				else {
658b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					(void) fprintf(stderr,
659b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru_("%s: More than one -y option specified\n"),
660b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru						progname);
661b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					exit(EXIT_FAILURE);
662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				}
663b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				break;
664b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			case 'L':
665b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				if (leapsec == NULL)
666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					leapsec = optarg;
667b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				else {
668b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					(void) fprintf(stderr,
669b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru_("%s: More than one -L option specified\n"),
670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru						progname);
671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					exit(EXIT_FAILURE);
672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				}
673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				break;
674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			case 'v':
675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				noise = TRUE;
676b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				break;
677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			case 's':
678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				(void) printf("%s: -s ignored\n", progname);
679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				break;
680b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
681b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (optind == argc - 1 && strcmp(argv[optind], "=") == 0)
682b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru		usage(stderr, EXIT_FAILURE);	/* usage message by request */
683b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (directory == NULL)
684b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		directory = TZDIR;
685b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (yitcommand == NULL)
686b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		yitcommand = "yearistype";
687b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
688b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	setboundaries();
689b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
690b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (optind < argc && leapsec != NULL) {
691b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		infile(leapsec);
692b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		adjleap();
693b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
694b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
695b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef ICU
696b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if ((icuFile = fopen(ICU_ZONE_FILE, "w")) == NULL) {
697b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru		const char *e = strerror(errno);
698b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru		(void) fprintf(stderr, _("%s: Can't open %s: %s\n"),
699b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru						progname, ICU_ZONE_FILE, e);
700b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru		(void) exit(EXIT_FAILURE);
701b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	}
702b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
703b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	for (i = optind; i < argc; ++i)
704b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		infile(argv[i]);
705b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (errors)
706b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		exit(EXIT_FAILURE);
707b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	associate();
708b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	for (i = 0; i < nzones; i = j) {
709b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		/*
710b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		** Find the next non-continuation zone entry.
711b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		*/
712b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		for (j = i + 1; j < nzones && zones[j].z_name == NULL; ++j)
713b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			continue;
714b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		outzone(&zones[i], j - i);
715b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
716b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	/*
717b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	** Make links.
718b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	*/
719b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	for (i = 0; i < nlinks; ++i) {
720b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		eat(links[i].l_filename, links[i].l_linenum);
721b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		dolink(links[i].l_from, links[i].l_to);
722b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef ICU
723b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru		emit_icu_link(icuFile, links[i].l_from, links[i].l_to);
724b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
725b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (noise)
726b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			for (j = 0; j < nlinks; ++j)
727b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				if (strcmp(links[i].l_to,
728b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					links[j].l_from) == 0)
729b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru						warning(_("link to link"));
730b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
731b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (lcltime != NULL) {
732b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		eat("command line", 1);
733b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		dolink(lcltime, TZDEFAULT);
734b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
735b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (psxrules != NULL) {
736b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		eat("command line", 1);
737b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		dolink(psxrules, TZDEFRULES);
738b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
739b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef ICU
740b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	for (i=0; i<finalRulesCount; ++i) {
741b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru		emit_icu_rule(icuFile, finalRules[i], i);
742b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	}
743b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif /*ICU*/
744b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	return (errors == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
745b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
746b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
747b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void
748b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querudolink(fromfield, tofield)
749b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruconst char * const	fromfield;
750b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruconst char * const	tofield;
751b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
752b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register char *	fromname;
753b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register char *	toname;
754b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
755b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	if (fromfield[0] == '/')
756b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru		fromname = ecpyalloc(fromfield);
757b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	else {
758b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		fromname = ecpyalloc(directory);
759b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		fromname = ecatalloc(fromname, "/");
760b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru		fromname = ecatalloc(fromname, fromfield);
761b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
762b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	if (tofield[0] == '/')
763b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru		toname = ecpyalloc(tofield);
764b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	else {
765b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		toname = ecpyalloc(directory);
766b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		toname = ecatalloc(toname, "/");
767b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru		toname = ecatalloc(toname, tofield);
768b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
769b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	/*
770b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	** We get to be careful here since
771b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	** there's a fair chance of root running us.
772b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	*/
773b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (!itsdir(toname))
774b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		(void) remove(toname);
775b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (link(fromname, toname) != 0) {
776b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		int	result;
777b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
778b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (mkdirs(toname) != 0)
779b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			exit(EXIT_FAILURE);
780b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
781b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		result = link(fromname, toname);
782b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if HAVE_SYMLINK
783b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (result != 0 &&
784b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			access(fromname, F_OK) == 0 &&
785b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			!itsdir(fromname)) {
786b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru				const char *s = tofield;
787b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				register char * symlinkcontents = NULL;
788b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
789b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				while ((s = strchr(s+1, '/')) != NULL)
790b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					symlinkcontents =
791b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru						ecatalloc(symlinkcontents,
792b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru						"../");
793b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				symlinkcontents =
794b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					ecatalloc(symlinkcontents,
795b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru					fromname);
796b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				result = symlink(symlinkcontents,
797b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					toname);
798b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				if (result == 0)
799b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruwarning(_("hard link failed, symbolic link used"));
800b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				ifree(symlinkcontents);
801b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
802b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif /* HAVE_SYMLINK */
803b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (result != 0) {
804b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			const char *e = strerror(errno);
805b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
806b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			(void) fprintf(stderr,
807b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				_("%s: Can't link from %s to %s: %s\n"),
808b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				progname, fromname, toname, e);
809b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifndef ICU_LINKS
810b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			exit(EXIT_FAILURE);
811b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
812b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
813b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
814b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	ifree(fromname);
815b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	ifree(toname);
816b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
817b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
818b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define TIME_T_BITS_IN_FILE	64
819b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
820b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void
821b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querusetboundaries(void)
822b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
823b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register int	i;
824b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
825b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	min_time = -1;
826b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	for (i = 0; i < TIME_T_BITS_IN_FILE - 1; ++i)
827b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		min_time *= 2;
828b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	max_time = -(min_time + 1);
829b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
830b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
831b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int
832b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruitsdir(name)
833b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst char * const	name;
834b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
835b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register char *	myname;
836b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register int	accres;
837b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
838b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	myname = ecpyalloc(name);
839b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	myname = ecatalloc(myname, "/.");
840b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	accres = access(myname, F_OK);
841b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	ifree(myname);
842b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	return accres == 0;
843b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
844b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
845b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
846b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru** Associate sets of rules with zones.
847b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
848b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
849b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
850b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru** Sort by rule name.
851b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
852b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
853b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int
854b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querurcomp(cp1, cp2)
855b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst void *	cp1;
856b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst void *	cp2;
857b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
858b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	return strcmp(((const struct rule *) cp1)->r_name,
859b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		((const struct rule *) cp2)->r_name);
860b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
861b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
862b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void
863b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruassociate(void)
864b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
865b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register struct zone *	zp;
866b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register struct rule *	rp;
867b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register int		base, out;
868b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register int		i, j;
869b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
870b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (nrules != 0) {
871b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		(void) qsort((void *) rules, (size_t) nrules,
872b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			(size_t) sizeof *rules, rcomp);
873b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		for (i = 0; i < nrules - 1; ++i) {
874b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (strcmp(rules[i].r_name,
875b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				rules[i + 1].r_name) != 0)
876b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					continue;
877b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (strcmp(rules[i].r_filename,
878b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				rules[i + 1].r_filename) == 0)
879b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					continue;
880b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			eat(rules[i].r_filename, rules[i].r_linenum);
881b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			warning(_("same rule name in multiple files"));
882b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			eat(rules[i + 1].r_filename, rules[i + 1].r_linenum);
883b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			warning(_("same rule name in multiple files"));
884b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			for (j = i + 2; j < nrules; ++j) {
885b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				if (strcmp(rules[i].r_name,
886b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					rules[j].r_name) != 0)
887b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru						break;
888b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				if (strcmp(rules[i].r_filename,
889b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					rules[j].r_filename) == 0)
890b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru						continue;
891b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				if (strcmp(rules[i + 1].r_filename,
892b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					rules[j].r_filename) == 0)
893b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru						continue;
894b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				break;
895b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			}
896b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			i = j - 1;
897b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
898b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
899b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	for (i = 0; i < nzones; ++i) {
900b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		zp = &zones[i];
901b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		zp->z_rules = NULL;
902b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		zp->z_nrules = 0;
903b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
904b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	for (base = 0; base < nrules; base = out) {
905b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		rp = &rules[base];
906b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		for (out = base + 1; out < nrules; ++out)
907b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (strcmp(rp->r_name, rules[out].r_name) != 0)
908b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				break;
909b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		for (i = 0; i < nzones; ++i) {
910b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			zp = &zones[i];
911b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (strcmp(zp->z_rule, rp->r_name) != 0)
912b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				continue;
913b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			zp->z_rules = rp;
914b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			zp->z_nrules = out - base;
915b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
916b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
917b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	for (i = 0; i < nzones; ++i) {
918b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		zp = &zones[i];
919b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (zp->z_nrules == 0) {
920b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			/*
921b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			** Maybe we have a local standard time offset.
922b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			*/
923b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			eat(zp->z_filename, zp->z_linenum);
924b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			zp->z_stdoff = gethms(zp->z_rule, _("unruly zone"),
925b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				TRUE);
926b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			/*
927b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			** Note, though, that if there's no rule,
928b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			** a '%s' in the format is a bad thing.
929b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			*/
930b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (strchr(zp->z_format, '%') != 0)
931b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				error(_("%s in ruleless zone"));
932b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
933b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
934b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (errors)
935b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		exit(EXIT_FAILURE);
936b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
937b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
938b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void
939b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruinfile(name)
940b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst char *	name;
941b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
942b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register FILE *			fp;
943b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register char **		fields;
944b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register char *			cp;
945b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register const struct lookup *	lp;
946b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register int			nfields;
947b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register int			wantcont;
948b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register int			num;
949b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	char				buf[BUFSIZ];
950b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
951b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (strcmp(name, "-") == 0) {
952b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		name = _("standard input");
953b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		fp = stdin;
954b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	} else if ((fp = fopen(name, "r")) == NULL) {
955b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		const char *e = strerror(errno);
956b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
957b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		(void) fprintf(stderr, _("%s: Can't open %s: %s\n"),
958b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			progname, name, e);
959b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		exit(EXIT_FAILURE);
960b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
961b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	wantcont = FALSE;
962b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	for (num = 1; ; ++num) {
963b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		eat(name, num);
964b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (fgets(buf, (int) sizeof buf, fp) != buf)
965b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			break;
966b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		cp = strchr(buf, '\n');
967b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (cp == NULL) {
968b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			error(_("line too long"));
969b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			exit(EXIT_FAILURE);
970b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
971b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		*cp = '\0';
972b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		fields = getfields(buf);
973b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		nfields = 0;
974b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		while (fields[nfields] != NULL) {
975b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			static char	nada;
976b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
977b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (strcmp(fields[nfields], "-") == 0)
978b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				fields[nfields] = &nada;
979b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			++nfields;
980b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
981b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (nfields == 0) {
982b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			/* nothing to do */
983b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		} else if (wantcont) {
984b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			wantcont = inzcont(fields, nfields);
985b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		} else {
986b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			lp = byword(fields[0], line_codes);
987b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (lp == NULL)
988b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				error(_("input line of unknown type"));
989b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			else switch ((int) (lp->l_value)) {
990b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				case LC_RULE:
991b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					inrule(fields, nfields);
992b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					wantcont = FALSE;
993b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					break;
994b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				case LC_ZONE:
995b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					wantcont = inzone(fields, nfields);
996b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					break;
997b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				case LC_LINK:
998b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					inlink(fields, nfields);
999b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					wantcont = FALSE;
1000b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					break;
1001b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				case LC_LEAP:
1002b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					if (name != leapsec)
1003b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru						(void) fprintf(stderr,
1004b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru_("%s: Leap line in non leap seconds file %s\n"),
1005b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru							progname, name);
1006b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					else	inleap(fields, nfields);
1007b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					wantcont = FALSE;
1008b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					break;
1009b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				default:	/* "cannot happen" */
1010b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					(void) fprintf(stderr,
1011b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru_("%s: panic: Invalid l_value %d\n"),
1012b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru						progname, lp->l_value);
1013b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					exit(EXIT_FAILURE);
1014b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			}
1015b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
1016b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		ifree((char *) fields);
1017b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1018b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (ferror(fp)) {
1019b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		(void) fprintf(stderr, _("%s: Error reading %s\n"),
1020b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			progname, filename);
1021b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		exit(EXIT_FAILURE);
1022b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1023b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (fp != stdin && fclose(fp)) {
1024b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		const char *e = strerror(errno);
1025b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1026b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		(void) fprintf(stderr, _("%s: Error closing %s: %s\n"),
1027b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			progname, filename, e);
1028b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		exit(EXIT_FAILURE);
1029b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1030b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (wantcont)
1031b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		error(_("expected continuation line not found"));
1032b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1033b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1034b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
1035b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru** Convert a string of one of the forms
1036b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru**	h	-h	hh:mm	-hh:mm	hh:mm:ss	-hh:mm:ss
1037b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru** into a number of seconds.
1038b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru** A null string maps to zero.
1039b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru** Call error with errstring and return zero on errors.
1040b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
1041b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1042b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic long
1043b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querugethms(string, errstring, signable)
1044b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst char *		string;
1045b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst char * const	errstring;
1046b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst int		signable;
1047b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1048b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	long	hh;
1049b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	int	mm, ss, sign;
1050b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1051b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (string == NULL || *string == '\0')
1052b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		return 0;
1053b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (!signable)
1054b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		sign = 1;
1055b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	else if (*string == '-') {
1056b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		sign = -1;
1057b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		++string;
1058b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	} else	sign = 1;
1059b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	if (sscanf(string, scheck(string, "%ld"), &hh) == 1)
1060b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		mm = ss = 0;
1061b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	else if (sscanf(string, scheck(string, "%ld:%d"), &hh, &mm) == 2)
1062b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		ss = 0;
1063b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	else if (sscanf(string, scheck(string, "%ld:%d:%d"),
1064b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		&hh, &mm, &ss) != 3) {
1065b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			error(errstring);
1066b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			return 0;
1067b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1068b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	if (hh < 0 ||
1069b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		mm < 0 || mm >= MINSPERHOUR ||
1070b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru		ss < 0 || ss > SECSPERMIN) {
1071b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			error(errstring);
1072b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			return 0;
1073b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1074b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	if (LONG_MAX / SECSPERHOUR < hh) {
1075b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru		error(_("time overflow"));
1076b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru		return 0;
1077b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	}
1078b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	if (noise && hh == HOURSPERDAY && mm == 0 && ss == 0)
1079b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		warning(_("24:00 not handled by pre-1998 versions of zic"));
1080b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	if (noise && (hh > HOURSPERDAY ||
1081b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru		(hh == HOURSPERDAY && (mm != 0 || ss != 0))))
1082b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruwarning(_("values over 24 hours not handled by pre-2007 versions of zic"));
1083b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	return oadd(eitol(sign) * hh * eitol(SECSPERHOUR),
1084b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru		    eitol(sign) * (eitol(mm) * eitol(SECSPERMIN) + eitol(ss)));
1085b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1086b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1087b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void
1088b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruinrule(fields, nfields)
1089b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruregister char ** const	fields;
1090b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst int		nfields;
1091b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1092b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	static struct rule	r;
1093b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1094b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (nfields != RULE_FIELDS) {
1095b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		error(_("wrong number of fields on Rule line"));
1096b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		return;
1097b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1098b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (*fields[RF_NAME] == '\0') {
1099b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		error(_("nameless rule"));
1100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		return;
1101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	r.r_filename = filename;
1103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	r.r_linenum = linenum;
1104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	r.r_stdoff = gethms(fields[RF_STDOFF], _("invalid saved time"), TRUE);
1105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	rulesub(&r, fields[RF_LOYEAR], fields[RF_HIYEAR], fields[RF_COMMAND],
1106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		fields[RF_MONTH], fields[RF_DAY], fields[RF_TOD]);
1107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	r.r_name = ecpyalloc(fields[RF_NAME]);
1108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	r.r_abbrvar = ecpyalloc(fields[RF_ABBRVAR]);
1109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (max_abbrvar_len < strlen(r.r_abbrvar))
1110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		max_abbrvar_len = strlen(r.r_abbrvar);
1111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	rules = (struct rule *) (void *) erealloc((char *) rules,
1112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		(int) ((nrules + 1) * sizeof *rules));
1113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	rules[nrules++] = r;
1114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int
1117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruinzone(fields, nfields)
1118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruregister char ** const	fields;
1119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst int		nfields;
1120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register int	i;
1122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	static char *	buf;
1123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (nfields < ZONE_MINFIELDS || nfields > ZONE_MAXFIELDS) {
1125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		error(_("wrong number of fields on Zone line"));
1126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		return FALSE;
1127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (strcmp(fields[ZF_NAME], TZDEFAULT) == 0 && lcltime != NULL) {
1129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		buf = erealloc(buf, (int) (132 + strlen(TZDEFAULT)));
1130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		(void) sprintf(buf,
1131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru_("\"Zone %s\" line and -l option are mutually exclusive"),
1132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			TZDEFAULT);
1133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		error(buf);
1134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		return FALSE;
1135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (strcmp(fields[ZF_NAME], TZDEFRULES) == 0 && psxrules != NULL) {
1137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		buf = erealloc(buf, (int) (132 + strlen(TZDEFRULES)));
1138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		(void) sprintf(buf,
1139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru_("\"Zone %s\" line and -p option are mutually exclusive"),
1140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			TZDEFRULES);
1141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		error(buf);
1142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		return FALSE;
1143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	for (i = 0; i < nzones; ++i)
1145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (zones[i].z_name != NULL &&
1146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			strcmp(zones[i].z_name, fields[ZF_NAME]) == 0) {
1147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				buf = erealloc(buf, (int) (132 +
1148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					strlen(fields[ZF_NAME]) +
1149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					strlen(zones[i].z_filename)));
1150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				(void) sprintf(buf,
1151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru_("duplicate zone name %s (file \"%s\", line %d)"),
1152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					fields[ZF_NAME],
1153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					zones[i].z_filename,
1154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					zones[i].z_linenum);
1155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				error(buf);
1156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				return FALSE;
1157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
1158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	return inzsub(fields, nfields, FALSE);
1159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int
1162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruinzcont(fields, nfields)
1163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruregister char ** const	fields;
1164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst int		nfields;
1165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (nfields < ZONEC_MINFIELDS || nfields > ZONEC_MAXFIELDS) {
1167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		error(_("wrong number of fields on Zone continuation line"));
1168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		return FALSE;
1169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	return inzsub(fields, nfields, TRUE);
1171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int
1174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruinzsub(fields, nfields, iscont)
1175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruregister char ** const	fields;
1176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst int		nfields;
1177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst int		iscont;
1178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register char *		cp;
1180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	static struct zone	z;
1181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register int		i_gmtoff, i_rule, i_format;
1182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register int		i_untilyear, i_untilmonth;
1183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register int		i_untilday, i_untiltime;
1184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register int		hasuntil;
1185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (iscont) {
1187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		i_gmtoff = ZFC_GMTOFF;
1188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		i_rule = ZFC_RULE;
1189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		i_format = ZFC_FORMAT;
1190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		i_untilyear = ZFC_TILYEAR;
1191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		i_untilmonth = ZFC_TILMONTH;
1192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		i_untilday = ZFC_TILDAY;
1193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		i_untiltime = ZFC_TILTIME;
1194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		z.z_name = NULL;
1195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	} else {
1196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		i_gmtoff = ZF_GMTOFF;
1197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		i_rule = ZF_RULE;
1198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		i_format = ZF_FORMAT;
1199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		i_untilyear = ZF_TILYEAR;
1200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		i_untilmonth = ZF_TILMONTH;
1201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		i_untilday = ZF_TILDAY;
1202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		i_untiltime = ZF_TILTIME;
1203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		z.z_name = ecpyalloc(fields[ZF_NAME]);
1204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	z.z_filename = filename;
1206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	z.z_linenum = linenum;
1207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	z.z_gmtoff = gethms(fields[i_gmtoff], _("invalid UTC offset"), TRUE);
1208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if ((cp = strchr(fields[i_format], '%')) != 0) {
1209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (*++cp != 's' || strchr(cp, '%') != 0) {
1210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			error(_("invalid abbreviation format"));
1211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			return FALSE;
1212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
1213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	z.z_rule = ecpyalloc(fields[i_rule]);
1215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	z.z_format = ecpyalloc(fields[i_format]);
1216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (max_format_len < strlen(z.z_format))
1217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		max_format_len = strlen(z.z_format);
1218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	hasuntil = nfields > i_untilyear;
1219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (hasuntil) {
1220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		z.z_untilrule.r_filename = filename;
1221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		z.z_untilrule.r_linenum = linenum;
1222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		rulesub(&z.z_untilrule,
1223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			fields[i_untilyear],
1224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			"only",
1225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			"",
1226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			(nfields > i_untilmonth) ?
1227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			fields[i_untilmonth] : "Jan",
1228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			(nfields > i_untilday) ? fields[i_untilday] : "1",
1229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			(nfields > i_untiltime) ? fields[i_untiltime] : "0");
1230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		z.z_untiltime = rpytime(&z.z_untilrule,
1231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			z.z_untilrule.r_loyear);
1232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (iscont && nzones > 0 &&
1233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			z.z_untiltime > min_time &&
1234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			z.z_untiltime < max_time &&
1235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			zones[nzones - 1].z_untiltime > min_time &&
1236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			zones[nzones - 1].z_untiltime < max_time &&
1237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			zones[nzones - 1].z_untiltime >= z.z_untiltime) {
1238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				error(_(
1239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru"Zone continuation line end time is not after end time of previous line"
1240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					));
1241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				return FALSE;
1242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
1243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	zones = (struct zone *) (void *) erealloc((char *) zones,
1245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		(int) ((nzones + 1) * sizeof *zones));
1246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	zones[nzones++] = z;
1247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	/*
1248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	** If there was an UNTIL field on this line,
1249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	** there's more information about the zone on the next line.
1250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	*/
1251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	return hasuntil;
1252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void
1255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruinleap(fields, nfields)
1256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruregister char ** const	fields;
1257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst int		nfields;
1258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register const char *		cp;
1260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register const struct lookup *	lp;
1261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register int			i, j;
1262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	int				year, month, day;
1263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	long				dayoff, tod;
1264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	zic_t				t;
1265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (nfields != LEAP_FIELDS) {
1267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		error(_("wrong number of fields on Leap line"));
1268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		return;
1269b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1270b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	dayoff = 0;
1271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	cp = fields[LP_YEAR];
1272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (sscanf(cp, scheck(cp, "%d"), &year) != 1) {
1273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		/*
1274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		** Leapin' Lizards!
1275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		*/
1276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		error(_("invalid leaping year"));
1277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		return;
1278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (!leapseen || leapmaxyear < year)
1280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		leapmaxyear = year;
1281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (!leapseen || leapminyear > year)
1282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		leapminyear = year;
1283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	leapseen = TRUE;
1284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	j = EPOCH_YEAR;
1285b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	while (j != year) {
1286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (year > j) {
1287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			i = len_years[isleap(j)];
1288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			++j;
1289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		} else {
1290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			--j;
1291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			i = -len_years[isleap(j)];
1292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
1293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		dayoff = oadd(dayoff, eitol(i));
1294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if ((lp = byword(fields[LP_MONTH], mon_names)) == NULL) {
1296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		error(_("invalid month name"));
1297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		return;
1298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	month = lp->l_value;
1300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	j = TM_JANUARY;
1301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	while (j != month) {
1302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		i = len_months[isleap(year)][j];
1303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		dayoff = oadd(dayoff, eitol(i));
1304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		++j;
1305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	cp = fields[LP_DAY];
1307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (sscanf(cp, scheck(cp, "%d"), &day) != 1 ||
1308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		day <= 0 || day > len_months[isleap(year)][month]) {
1309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			error(_("invalid day of month"));
1310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			return;
1311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	dayoff = oadd(dayoff, eitol(day - 1));
1313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (dayoff < 0 && !TYPE_SIGNED(zic_t)) {
1314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		error(_("time before zero"));
1315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		return;
1316b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (dayoff < min_time / SECSPERDAY) {
1318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		error(_("time too small"));
1319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		return;
1320b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (dayoff > max_time / SECSPERDAY) {
1322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		error(_("time too large"));
1323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		return;
1324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	t = (zic_t) dayoff * SECSPERDAY;
1326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	tod = gethms(fields[LP_TIME], _("invalid time of day"), FALSE);
1327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	cp = fields[LP_CORR];
1328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{
1329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		register int	positive;
1330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		int		count;
1331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (strcmp(cp, "") == 0) { /* infile() turns "-" into "" */
1333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			positive = FALSE;
1334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			count = 1;
1335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		} else if (strcmp(cp, "--") == 0) {
1336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			positive = FALSE;
1337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			count = 2;
1338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		} else if (strcmp(cp, "+") == 0) {
1339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			positive = TRUE;
1340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			count = 1;
1341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		} else if (strcmp(cp, "++") == 0) {
1342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			positive = TRUE;
1343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			count = 2;
1344b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		} else {
1345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			error(_("illegal CORRECTION field on Leap line"));
1346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			return;
1347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
1348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if ((lp = byword(fields[LP_ROLL], leap_types)) == NULL) {
1349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			error(_(
1350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				"illegal Rolling/Stationary field on Leap line"
1351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				));
1352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			return;
1353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
1354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		leapadd(tadd(t, tod), positive, lp->l_value, count);
1355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1356b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void
1359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruinlink(fields, nfields)
1360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruregister char ** const	fields;
1361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst int		nfields;
1362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	struct link	l;
1364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (nfields != LINK_FIELDS) {
1366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		error(_("wrong number of fields on Link line"));
1367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		return;
1368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (*fields[LF_FROM] == '\0') {
1370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		error(_("blank FROM field on Link line"));
1371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		return;
1372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (*fields[LF_TO] == '\0') {
1374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		error(_("blank TO field on Link line"));
1375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		return;
1376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	l.l_filename = filename;
1378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	l.l_linenum = linenum;
1379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	l.l_from = ecpyalloc(fields[LF_FROM]);
1380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	l.l_to = ecpyalloc(fields[LF_TO]);
1381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	links = (struct link *) (void *) erealloc((char *) links,
1382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		(int) ((nlinks + 1) * sizeof *links));
1383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	links[nlinks++] = l;
1384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void
1387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querurulesub(rp, loyearp, hiyearp, typep, monthp, dayp, timep)
1388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruregister struct rule * const	rp;
1389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst char * const		loyearp;
1390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst char * const		hiyearp;
1391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst char * const		typep;
1392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst char * const		monthp;
1393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst char * const		dayp;
1394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst char * const		timep;
1395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register const struct lookup *	lp;
1397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register const char *		cp;
1398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register char *			dp;
1399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register char *			ep;
1400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if ((lp = byword(monthp, mon_names)) == NULL) {
1402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		error(_("invalid month name"));
1403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		return;
1404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	rp->r_month = lp->l_value;
1406b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	rp->r_todisstd = FALSE;
1407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	rp->r_todisgmt = FALSE;
1408b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	dp = ecpyalloc(timep);
1409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (*dp != '\0') {
1410b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		ep = dp + strlen(dp) - 1;
1411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		switch (lowerit(*ep)) {
1412b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			case 's':	/* Standard */
1413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				rp->r_todisstd = TRUE;
1414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				rp->r_todisgmt = FALSE;
1415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				*ep = '\0';
1416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				break;
1417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			case 'w':	/* Wall */
1418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				rp->r_todisstd = FALSE;
1419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				rp->r_todisgmt = FALSE;
1420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				*ep = '\0';
1421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				break;
1422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			case 'g':	/* Greenwich */
1423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			case 'u':	/* Universal */
1424b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			case 'z':	/* Zulu */
1425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				rp->r_todisstd = TRUE;
1426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				rp->r_todisgmt = TRUE;
1427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				*ep = '\0';
1428b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				break;
1429b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
1430b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	rp->r_tod = gethms(dp, _("invalid time of day"), FALSE);
1432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	ifree(dp);
1433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	/*
1434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	** Year work.
1435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	*/
1436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	cp = loyearp;
1437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	lp = byword(cp, begin_years);
1438b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	rp->r_lowasnum = lp == NULL;
1439b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (!rp->r_lowasnum) switch ((int) lp->l_value) {
1440b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		case YR_MINIMUM:
1441b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			rp->r_loyear = INT_MIN;
1442b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			break;
1443b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		case YR_MAXIMUM:
1444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			rp->r_loyear = INT_MAX;
1445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			break;
1446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		default:	/* "cannot happen" */
1447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			(void) fprintf(stderr,
1448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				_("%s: panic: Invalid l_value %d\n"),
1449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				progname, lp->l_value);
1450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			exit(EXIT_FAILURE);
1451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	} else if (sscanf(cp, scheck(cp, "%d"), &rp->r_loyear) != 1) {
1452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		error(_("invalid starting year"));
1453b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		return;
1454b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1455b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	cp = hiyearp;
1456b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	lp = byword(cp, end_years);
1457b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	rp->r_hiwasnum = lp == NULL;
1458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (!rp->r_hiwasnum) switch ((int) lp->l_value) {
1459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		case YR_MINIMUM:
1460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			rp->r_hiyear = INT_MIN;
1461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			break;
1462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		case YR_MAXIMUM:
1463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			rp->r_hiyear = INT_MAX;
1464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			break;
1465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		case YR_ONLY:
1466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			rp->r_hiyear = rp->r_loyear;
1467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			break;
1468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		default:	/* "cannot happen" */
1469b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			(void) fprintf(stderr,
1470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				_("%s: panic: Invalid l_value %d\n"),
1471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				progname, lp->l_value);
1472b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			exit(EXIT_FAILURE);
1473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	} else if (sscanf(cp, scheck(cp, "%d"), &rp->r_hiyear) != 1) {
1474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		error(_("invalid ending year"));
1475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		return;
1476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (rp->r_loyear > rp->r_hiyear) {
1478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		error(_("starting year greater than ending year"));
1479b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		return;
1480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1481b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (*typep == '\0')
1482b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		rp->r_yrtype = NULL;
1483b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	else {
1484b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (rp->r_loyear == rp->r_hiyear) {
1485b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			error(_("typed single year"));
1486b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			return;
1487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
1488b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		rp->r_yrtype = ecpyalloc(typep);
1489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1490b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	/*
1491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	** Day work.
1492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	** Accept things such as:
1493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	**	1
1494b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	**	last-Sunday
1495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	**	Sun<=20
1496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	**	Sun>=7
1497b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	*/
1498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	dp = ecpyalloc(dayp);
1499b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if ((lp = byword(dp, lasts)) != NULL) {
1500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		rp->r_dycode = DC_DOWLEQ;
1501b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		rp->r_wday = lp->l_value;
1502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		rp->r_dayofmonth = len_months[1][rp->r_month];
1503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	} else {
1504b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if ((ep = strchr(dp, '<')) != 0)
1505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			rp->r_dycode = DC_DOWLEQ;
1506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		else if ((ep = strchr(dp, '>')) != 0)
1507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			rp->r_dycode = DC_DOWGEQ;
1508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		else {
1509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			ep = dp;
1510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			rp->r_dycode = DC_DOM;
1511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
1512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (rp->r_dycode != DC_DOM) {
1513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			*ep++ = 0;
1514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (*ep++ != '=') {
1515b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				error(_("invalid day of month"));
1516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				ifree(dp);
1517b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				return;
1518b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			}
1519b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if ((lp = byword(dp, wday_names)) == NULL) {
1520b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				error(_("invalid weekday name"));
1521b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				ifree(dp);
1522b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				return;
1523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			}
1524b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			rp->r_wday = lp->l_value;
1525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
1526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (sscanf(ep, scheck(ep, "%d"), &rp->r_dayofmonth) != 1 ||
1527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			rp->r_dayofmonth <= 0 ||
1528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			(rp->r_dayofmonth > len_months[1][rp->r_month])) {
1529b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				error(_("invalid day of month"));
1530b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				ifree(dp);
1531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				return;
1532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
1533b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	ifree(dp);
1535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1536b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1537b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void
1538b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconvert(val, buf)
1539b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst long	val;
1540b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruchar * const	buf;
1541b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1542b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register int	i;
1543b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register int	shift;
1544b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1545b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	for (i = 0, shift = 24; i < 4; ++i, shift -= 8)
1546b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		buf[i] = val >> shift;
1547b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1548b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1549b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void
1550b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconvert64(val, buf)
1551b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst zic_t	val;
1552b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruchar * const	buf;
1553b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1554b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register int	i;
1555b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register int	shift;
1556b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	for (i = 0, shift = 56; i < 8; ++i, shift -= 8)
1558b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		buf[i] = val >> shift;
1559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1560b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1561b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void
1562b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruputtzcode(val, fp)
1563b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst long	val;
1564b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruFILE * const	fp;
1565b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1566b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	char	buf[4];
1567b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1568b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	convert(val, buf);
1569b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	(void) fwrite((void *) buf, (size_t) sizeof buf, (size_t) 1, fp);
1570b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1571b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1572b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void
1573b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruputtzcode64(val, fp)
1574b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst zic_t	val;
1575b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruFILE * const	fp;
1576b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1577b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	char	buf[8];
1578b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1579b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	convert64(val, buf);
1580b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	(void) fwrite((void *) buf, (size_t) sizeof buf, (size_t) 1, fp);
1581b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1582b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1583b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int
1584b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruatcomp(avp, bvp)
1585b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst void *	avp;
1586b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst void *	bvp;
1587b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1588b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	const zic_t	a = ((const struct attype *) avp)->at;
1589b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	const zic_t	b = ((const struct attype *) bvp)->at;
1590b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1591b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	return (a < b) ? -1 : (a > b);
1592b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1593b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1594b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int
1595b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruis32(x)
1596b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst zic_t	x;
1597b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	return INT32_MIN <= x && x <= INT32_MAX;
1599b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1601b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void
1602b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruwritezone(name, string)
1603b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst char * const	name;
1604b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst char * const	string;
1605b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1606b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register FILE *			fp;
1607b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register int			i, j;
1608b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register int			leapcnt32, leapi32;
1609b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register int			timecnt32, timei32;
1610b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register int			pass;
1611b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	static char *			fullname;
1612b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	static const struct tzhead	tzh0;
1613b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	static struct tzhead		tzh;
1614b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	zic_t				ats[TZ_MAX_TIMES];
1615b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	unsigned char			types[TZ_MAX_TIMES];
1616b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1617b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	/*
1618b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	** Sort.
1619b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	*/
1620b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (timecnt > 1)
1621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		(void) qsort((void *) attypes, (size_t) timecnt,
1622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			(size_t) sizeof *attypes, atcomp);
1623b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	/*
1624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	** Optimize.
1625b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	*/
1626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	{
1627b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		int	fromi;
1628b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		int	toi;
1629b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		toi = 0;
1631b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		fromi = 0;
1632b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		while (fromi < timecnt && attypes[fromi].at < min_time)
1633b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			++fromi;
1634b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (isdsts[0] == 0)
1635b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			while (fromi < timecnt && attypes[fromi].type == 0)
1636b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				++fromi;	/* handled by default rule */
1637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		for ( ; fromi < timecnt; ++fromi) {
1638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (toi != 0 && ((attypes[fromi].at +
1639b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				gmtoffs[attypes[toi - 1].type]) <=
1640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				(attypes[toi - 1].at + gmtoffs[toi == 1 ? 0
1641b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				: attypes[toi - 2].type]))) {
1642b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					attypes[toi - 1].type =
1643b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru						attypes[fromi].type;
1644b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					continue;
1645b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			}
1646b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (toi == 0 ||
1647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				attypes[toi - 1].type != attypes[fromi].type)
1648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					attypes[toi++] = attypes[fromi];
1649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
1650b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		timecnt = toi;
1651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1652b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	/*
1653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	** Transfer.
1654b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	*/
1655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	for (i = 0; i < timecnt; ++i) {
1656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		ats[i] = attypes[i].at;
1657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		types[i] = attypes[i].type;
1658b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1659b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	/*
1660b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	** Correct for leap seconds.
1661b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	*/
1662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	for (i = 0; i < timecnt; ++i) {
1663b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		j = leapcnt;
1664b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		while (--j >= 0)
1665b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (ats[i] > trans[j] - corr[j]) {
1666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				ats[i] = tadd(ats[i], corr[j]);
1667b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				break;
1668b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			}
1669b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	/*
1671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	** Figure out 32-bit-limited starts and counts.
1672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	*/
1673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	timecnt32 = timecnt;
1674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	timei32 = 0;
1675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	leapcnt32 = leapcnt;
1676b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	leapi32 = 0;
1677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	while (timecnt32 > 0 && !is32(ats[timecnt32 - 1]))
1678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		--timecnt32;
1679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	while (timecnt32 > 0 && !is32(ats[timei32])) {
1680b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		--timecnt32;
1681b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		++timei32;
1682b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1683b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	while (leapcnt32 > 0 && !is32(trans[leapcnt32 - 1]))
1684b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		--leapcnt32;
1685b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	while (leapcnt32 > 0 && !is32(trans[leapi32])) {
1686b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		--leapcnt32;
1687b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		++leapi32;
1688b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1689b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	fullname = erealloc(fullname,
1690b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		(int) (strlen(directory) + 1 + strlen(name) + 1));
1691b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	(void) sprintf(fullname, "%s/%s", directory, name);
1692b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	/*
1693b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	** Remove old file, if any, to snap links.
1694b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	*/
1695b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (!itsdir(fullname) && remove(fullname) != 0 && errno != ENOENT) {
1696b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		const char *e = strerror(errno);
1697b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1698b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		(void) fprintf(stderr, _("%s: Can't remove %s: %s\n"),
1699b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			progname, fullname, e);
1700b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		exit(EXIT_FAILURE);
1701b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1702b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if ((fp = fopen(fullname, "wb")) == NULL) {
1703b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (mkdirs(fullname) != 0)
1704b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			exit(EXIT_FAILURE);
1705b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if ((fp = fopen(fullname, "wb")) == NULL) {
1706b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			const char *e = strerror(errno);
1707b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1708b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			(void) fprintf(stderr, _("%s: Can't create %s: %s\n"),
1709b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				progname, fullname, e);
1710b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			exit(EXIT_FAILURE);
1711b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
1712b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1713b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	for (pass = 1; pass <= 2; ++pass) {
1714b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		register int	thistimei, thistimecnt;
1715b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		register int	thisleapi, thisleapcnt;
1716b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		register int	thistimelim, thisleaplim;
1717b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		int		writetype[TZ_MAX_TIMES];
1718b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		int		typemap[TZ_MAX_TYPES];
1719b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		register int	thistypecnt;
1720b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		char		thischars[TZ_MAX_CHARS];
1721b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		char		thischarcnt;
1722b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		int 		indmap[TZ_MAX_CHARS];
1723b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1724b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (pass == 1) {
1725b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			thistimei = timei32;
1726b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			thistimecnt = timecnt32;
1727b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			thisleapi = leapi32;
1728b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			thisleapcnt = leapcnt32;
1729b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		} else {
1730b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			thistimei = 0;
1731b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			thistimecnt = timecnt;
1732b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			thisleapi = 0;
1733b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			thisleapcnt = leapcnt;
1734b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
1735b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		thistimelim = thistimei + thistimecnt;
1736b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		thisleaplim = thisleapi + thisleapcnt;
1737b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		for (i = 0; i < typecnt; ++i)
1738b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			writetype[i] = thistimecnt == timecnt;
1739b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (thistimecnt == 0) {
1740b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			/*
1741b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			** No transition times fall in the current
1742b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			** (32- or 64-bit) window.
1743b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			*/
1744b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (typecnt != 0)
1745b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				writetype[typecnt - 1] = TRUE;
1746b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		} else {
1747b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			for (i = thistimei - 1; i < thistimelim; ++i)
1748b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				if (i >= 0)
1749b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					writetype[types[i]] = TRUE;
1750b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			/*
1751b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			** For America/Godthab and Antarctica/Palmer
1752b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			*/
1753b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (thistimei == 0)
1754b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				writetype[0] = TRUE;
1755b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
1756b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		thistypecnt = 0;
1757b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		for (i = 0; i < typecnt; ++i)
1758b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			typemap[i] = writetype[i] ?  thistypecnt++ : -1;
1759b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		for (i = 0; i < sizeof indmap / sizeof indmap[0]; ++i)
1760b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			indmap[i] = -1;
1761b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		thischarcnt = 0;
1762b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		for (i = 0; i < typecnt; ++i) {
1763b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			register char *	thisabbr;
1764b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1765b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (!writetype[i])
1766b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				continue;
1767b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (indmap[abbrinds[i]] >= 0)
1768b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				continue;
1769b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			thisabbr = &chars[abbrinds[i]];
1770b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			for (j = 0; j < thischarcnt; ++j)
1771b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				if (strcmp(&thischars[j], thisabbr) == 0)
1772b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					break;
1773b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (j == thischarcnt) {
1774b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				(void) strcpy(&thischars[(int) thischarcnt],
1775b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					thisabbr);
1776b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				thischarcnt += strlen(thisabbr) + 1;
1777b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			}
1778b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			indmap[abbrinds[i]] = j;
1779b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
1780b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define DO(field)	(void) fwrite((void *) tzh.field, \
1781b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				(size_t) sizeof tzh.field, (size_t) 1, fp)
1782b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		tzh = tzh0;
1783b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef ICU
1784b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru		* (ICUZoneinfoVersion*) &tzh.tzh_reserved = TZ_ICU_VERSION;
1785b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru		(void) strncpy(tzh.tzh_magic, TZ_ICU_MAGIC, sizeof tzh.tzh_magic);
1786b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#else
1787b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		(void) strncpy(tzh.tzh_magic, TZ_MAGIC, sizeof tzh.tzh_magic);
1788b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
1789b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		tzh.tzh_version[0] = ZIC_VERSION;
1790b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		convert(eitol(thistypecnt), tzh.tzh_ttisgmtcnt);
1791b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		convert(eitol(thistypecnt), tzh.tzh_ttisstdcnt);
1792b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		convert(eitol(thisleapcnt), tzh.tzh_leapcnt);
1793b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		convert(eitol(thistimecnt), tzh.tzh_timecnt);
1794b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		convert(eitol(thistypecnt), tzh.tzh_typecnt);
1795b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		convert(eitol(thischarcnt), tzh.tzh_charcnt);
1796b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		DO(tzh_magic);
1797b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		DO(tzh_version);
1798b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		DO(tzh_reserved);
1799b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		DO(tzh_ttisgmtcnt);
1800b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		DO(tzh_ttisstdcnt);
1801b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		DO(tzh_leapcnt);
1802b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		DO(tzh_timecnt);
1803b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		DO(tzh_typecnt);
1804b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		DO(tzh_charcnt);
1805b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#undef DO
1806b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		for (i = thistimei; i < thistimelim; ++i)
1807b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (pass == 1)
1808b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				puttzcode((long) ats[i], fp);
1809b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			else	puttzcode64(ats[i], fp);
1810b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		for (i = thistimei; i < thistimelim; ++i) {
1811b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			unsigned char	uc;
1812b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1813b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			uc = typemap[types[i]];
1814b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			(void) fwrite((void *) &uc,
1815b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				(size_t) sizeof uc,
1816b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				(size_t) 1,
1817b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				fp);
1818b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
1819b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		for (i = 0; i < typecnt; ++i)
1820b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (writetype[i]) {
1821b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef ICU
1822b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru				puttzcode((long) rawoffs[i], fp);
1823b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru				puttzcode((long) dstoffs[i], fp);
1824b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#else
1825b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru				puttzcode(gmtoffs[i], fp);
1826b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
1827b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				(void) putc(isdsts[i], fp);
1828b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				(void) putc((unsigned char) indmap[abbrinds[i]], fp);
1829b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			}
1830b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (thischarcnt != 0)
1831b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			(void) fwrite((void *) thischars,
1832b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				(size_t) sizeof thischars[0],
1833b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				(size_t) thischarcnt, fp);
1834b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		for (i = thisleapi; i < thisleaplim; ++i) {
1835b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			register zic_t	todo;
1836b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1837b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (roll[i]) {
1838b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				if (timecnt == 0 || trans[i] < ats[0]) {
1839b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					j = 0;
1840b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					while (isdsts[j])
1841b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru						if (++j >= typecnt) {
1842b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru							j = 0;
1843b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru							break;
1844b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru						}
1845b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				} else {
1846b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					j = 1;
1847b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					while (j < timecnt &&
1848b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru						trans[i] >= ats[j])
1849b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru							++j;
1850b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					j = types[j - 1];
1851b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				}
1852b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				todo = tadd(trans[i], -gmtoffs[j]);
1853b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			} else	todo = trans[i];
1854b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (pass == 1)
1855b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				puttzcode((long) todo, fp);
1856b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			else	puttzcode64(todo, fp);
1857b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			puttzcode(corr[i], fp);
1858b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
1859b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		for (i = 0; i < typecnt; ++i)
1860b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (writetype[i])
1861b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				(void) putc(ttisstds[i], fp);
1862b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		for (i = 0; i < typecnt; ++i)
1863b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (writetype[i])
1864b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				(void) putc(ttisgmts[i], fp);
1865b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1866b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	(void) fprintf(fp, "\n%s\n", string);
1867b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (ferror(fp) || fclose(fp)) {
1868b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		(void) fprintf(stderr, _("%s: Error writing %s\n"),
1869b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			progname, fullname);
1870b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		exit(EXIT_FAILURE);
1871b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1872b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1873b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1874b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void
1875b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querudoabbr(abbr, format, letters, isdst, doquotes)
1876b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruchar * const		abbr;
1877b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst char * const	format;
1878b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst char * const	letters;
1879b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst int		isdst;
1880b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst int		doquotes;
1881b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1882b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register char *	cp;
1883b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register char *	slashp;
1884b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register int	len;
1885b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1886b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	slashp = strchr(format, '/');
1887b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (slashp == NULL) {
1888b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (letters == NULL)
1889b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			(void) strcpy(abbr, format);
1890b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		else	(void) sprintf(abbr, format, letters);
1891b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	} else if (isdst) {
1892b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		(void) strcpy(abbr, slashp + 1);
1893b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	} else {
1894b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (slashp > format)
1895b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			(void) strncpy(abbr, format,
1896b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				(unsigned) (slashp - format));
1897b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		abbr[slashp - format] = '\0';
1898b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1899b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (!doquotes)
1900b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		return;
1901b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	for (cp = abbr; *cp != '\0'; ++cp)
1902b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ", *cp) == NULL &&
1903b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			strchr("abcdefghijklmnopqrstuvwxyz", *cp) == NULL)
1904b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				break;
1905b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	len = strlen(abbr);
1906b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (len > 0 && *cp == '\0')
1907b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		return;
1908b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	abbr[len + 2] = '\0';
1909b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	abbr[len + 1] = '>';
1910b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	for ( ; len > 0; --len)
1911b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		abbr[len] = abbr[len - 1];
1912b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	abbr[0] = '<';
1913b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1914b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1915b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void
1916b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruupdateminmax(x)
1917b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst int	x;
1918b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1919b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (min_year > x)
1920b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		min_year = x;
1921b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (max_year < x)
1922b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		max_year = x;
1923b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1924b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1925b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int
1926b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustringoffset(result, offset)
1927b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruchar *	result;
1928b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querulong	offset;
1929b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1930b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register int	hours;
1931b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register int	minutes;
1932b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register int	seconds;
1933b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1934b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	result[0] = '\0';
1935b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (offset < 0) {
1936b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		(void) strcpy(result, "-");
1937b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		offset = -offset;
1938b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1939b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	seconds = offset % SECSPERMIN;
1940b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	offset /= SECSPERMIN;
1941b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	minutes = offset % MINSPERHOUR;
1942b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	offset /= MINSPERHOUR;
1943b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	hours = offset;
1944b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (hours >= HOURSPERDAY) {
1945b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		result[0] = '\0';
1946b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		return -1;
1947b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1948b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	(void) sprintf(end(result), "%d", hours);
1949b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (minutes != 0 || seconds != 0) {
1950b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		(void) sprintf(end(result), ":%02d", minutes);
1951b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (seconds != 0)
1952b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			(void) sprintf(end(result), ":%02d", seconds);
1953b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1954b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	return 0;
1955b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1956b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1957b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int
1958b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustringrule(result, rp, dstoff, gmtoff)
1959b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruchar *				result;
1960b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst struct rule * const	rp;
1961b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst long			dstoff;
1962b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst long			gmtoff;
1963b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1964b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register long	tod;
1965b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1966b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	result = end(result);
1967b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (rp->r_dycode == DC_DOM) {
1968b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		register int	month, total;
1969b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1970b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (rp->r_dayofmonth == 29 && rp->r_month == TM_FEBRUARY)
1971b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			return -1;
1972b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		total = 0;
1973b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		for (month = 0; month < rp->r_month; ++month)
1974b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			total += len_months[0][month];
1975b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		(void) sprintf(result, "J%d", total + rp->r_dayofmonth);
1976b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	} else {
1977b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		register int	week;
1978b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1979b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (rp->r_dycode == DC_DOWGEQ) {
1980b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			week = 1 + rp->r_dayofmonth / DAYSPERWEEK;
1981b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if ((week - 1) * DAYSPERWEEK + 1 != rp->r_dayofmonth)
1982b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				return -1;
1983b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		} else if (rp->r_dycode == DC_DOWLEQ) {
1984b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (rp->r_dayofmonth == len_months[1][rp->r_month])
1985b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				week = 5;
1986b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			else {
1987b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				week = 1 + rp->r_dayofmonth / DAYSPERWEEK;
1988b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				if (week * DAYSPERWEEK - 1 != rp->r_dayofmonth)
1989b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					return -1;
1990b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			}
1991b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		} else	return -1;	/* "cannot happen" */
1992b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		(void) sprintf(result, "M%d.%d.%d",
1993b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			rp->r_month + 1, week, rp->r_wday);
1994b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
1995b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	tod = rp->r_tod;
1996b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (rp->r_todisgmt)
1997b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		tod += gmtoff;
1998b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (rp->r_todisstd && rp->r_stdoff == 0)
1999b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		tod += dstoff;
2000b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (tod < 0) {
2001b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		result[0] = '\0';
2002b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		return -1;
2003b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
2004b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (tod != 2 * SECSPERMIN * MINSPERHOUR) {
2005b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		(void) strcat(result, "/");
2006b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (stringoffset(end(result), tod) != 0)
2007b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			return -1;
2008b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
2009b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	return 0;
2010b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2011b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2012b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void
2013b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustringzone(result, zpfirst, zonecount)
2014b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruchar *				result;
2015b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst struct zone * const	zpfirst;
2016b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst int			zonecount;
2017b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
2018b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register const struct zone *	zp;
2019b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register struct rule *		rp;
2020b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register struct rule *		stdrp;
2021b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register struct rule *		dstrp;
2022b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register int			i;
2023b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register const char *		abbrvar;
2024b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2025b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	result[0] = '\0';
2026b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	zp = zpfirst + zonecount - 1;
2027b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	stdrp = dstrp = NULL;
2028b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	for (i = 0; i < zp->z_nrules; ++i) {
2029b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		rp = &zp->z_rules[i];
2030b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (rp->r_hiwasnum || rp->r_hiyear != INT_MAX)
2031b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			continue;
2032b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (rp->r_yrtype != NULL)
2033b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			continue;
2034b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (rp->r_stdoff == 0) {
2035b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (stdrp == NULL)
2036b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				stdrp = rp;
2037b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			else	return;
2038b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		} else {
2039b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (dstrp == NULL)
2040b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				dstrp = rp;
2041b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			else	return;
2042b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
2043b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
2044b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (stdrp == NULL && dstrp == NULL) {
2045b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		/*
2046b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		** There are no rules running through "max".
2047b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		** Let's find the latest rule.
2048b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		*/
2049b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		for (i = 0; i < zp->z_nrules; ++i) {
2050b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			rp = &zp->z_rules[i];
2051b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (stdrp == NULL || rp->r_hiyear > stdrp->r_hiyear ||
2052b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				(rp->r_hiyear == stdrp->r_hiyear &&
2053b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				rp->r_month > stdrp->r_month))
2054b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					stdrp = rp;
2055b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
2056b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (stdrp != NULL && stdrp->r_stdoff != 0)
2057b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			return;	/* We end up in DST (a POSIX no-no). */
2058b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		/*
2059b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		** Horrid special case: if year is 2037,
2060b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		** presume this is a zone handled on a year-by-year basis;
2061b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		** do not try to apply a rule to the zone.
2062b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		*/
2063b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (stdrp != NULL && stdrp->r_hiyear == 2037)
2064b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			return;
2065b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
2066b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (stdrp == NULL && zp->z_nrules != 0)
2067b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		return;
2068b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	abbrvar = (stdrp == NULL) ? "" : stdrp->r_abbrvar;
2069b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	doabbr(result, zp->z_format, abbrvar, FALSE, TRUE);
2070b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (stringoffset(end(result), -zp->z_gmtoff) != 0) {
2071b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		result[0] = '\0';
2072b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		return;
2073b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
2074b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (dstrp == NULL)
2075b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		return;
2076b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	doabbr(end(result), zp->z_format, dstrp->r_abbrvar, TRUE, TRUE);
2077b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (dstrp->r_stdoff != SECSPERMIN * MINSPERHOUR)
2078b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (stringoffset(end(result),
2079b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			-(zp->z_gmtoff + dstrp->r_stdoff)) != 0) {
2080b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				result[0] = '\0';
2081b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				return;
2082b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
2083b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	(void) strcat(result, ",");
2084b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (stringrule(result, dstrp, dstrp->r_stdoff, zp->z_gmtoff) != 0) {
2085b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		result[0] = '\0';
2086b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		return;
2087b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
2088b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	(void) strcat(result, ",");
2089b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (stringrule(result, stdrp, dstrp->r_stdoff, zp->z_gmtoff) != 0) {
2090b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		result[0] = '\0';
2091b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		return;
2092b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
2093b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2094b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2095b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void
2096b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruoutzone(zpfirst, zonecount)
2097b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst struct zone * const	zpfirst;
2098b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst int			zonecount;
2099b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
2100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register const struct zone *	zp;
2101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register struct rule *		rp;
2102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register int			i, j;
2103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register int			usestart, useuntil;
2104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register zic_t			starttime, untiltime;
2105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register long			gmtoff;
2106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register long			stdoff;
2107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register int			year;
2108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register long			startoff;
2109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register int			startttisstd;
2110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register int			startttisgmt;
2111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register int			type;
2112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register char *			startbuf;
2113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register char *			ab;
2114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register char *			envvar;
2115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register int			max_abbr_len;
2116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register int			max_envvar_len;
2117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef ICU
2118b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	int						finalRuleYear, finalRuleIndex;
2119b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	const struct rule*		finalRule1;
2120b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	const struct rule*		finalRule2;
2121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
2122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	max_abbr_len = 2 + max_format_len + max_abbrvar_len;
2124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	max_envvar_len = 2 * max_abbr_len + 5 * 9;
2125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	startbuf = emalloc(max_abbr_len + 1);
2126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	ab = emalloc(max_abbr_len + 1);
2127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	envvar = emalloc(max_envvar_len + 1);
2128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	INITIALIZE(untiltime);
2129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	INITIALIZE(starttime);
2130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	/*
2131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	** Now. . .finally. . .generate some useful data!
2132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	*/
2133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	timecnt = 0;
2134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	typecnt = 0;
2135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	charcnt = 0;
2136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	/*
2137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	** Thanks to Earl Chew
2138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	** for noting the need to unconditionally initialize startttisstd.
2139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	*/
2140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	startttisstd = FALSE;
2141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	startttisgmt = FALSE;
2142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	min_year = max_year = EPOCH_YEAR;
2143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (leapseen) {
2144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		updateminmax(leapminyear);
2145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		updateminmax(leapmaxyear);
2146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
2147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	for (i = 0; i < zonecount; ++i) {
2148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		zp = &zpfirst[i];
2149b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru		if (i < zonecount - 1)
2150b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru			updateminmax(zp->z_untilrule.r_loyear);
2151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		for (j = 0; j < zp->z_nrules; ++j) {
2152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			rp = &zp->z_rules[j];
2153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (rp->r_lowasnum)
2154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				updateminmax(rp->r_loyear);
2155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (rp->r_hiwasnum)
2156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				updateminmax(rp->r_hiyear);
2157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
2158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
2159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	/*
2160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	** Generate lots of data if a rule can't cover all future times.
2161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	*/
2162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	stringzone(envvar, zpfirst, zonecount);
2163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (noise && envvar[0] == '\0') {
2164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		register char *	wp;
2165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruwp = ecpyalloc(_("no POSIX environment variable for zone"));
2167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		wp = ecatalloc(wp, " ");
2168b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru		wp = ecatalloc(wp, zpfirst->z_name);
2169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		warning(wp);
2170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		ifree(wp);
2171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
2172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (envvar[0] == '\0') {
2173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (min_year >= INT_MIN + YEARSPERREPEAT)
2174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			min_year -= YEARSPERREPEAT;
2175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		else	min_year = INT_MIN;
2176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (max_year <= INT_MAX - YEARSPERREPEAT)
2177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			max_year += YEARSPERREPEAT;
2178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		else	max_year = INT_MAX;
2179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
2180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	/*
2181b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	** For the benefit of older systems,
2182b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	** generate data from 1900 through 2037.
2183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	*/
2184b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	if (min_year > 1900)
2185b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru		min_year = 1900;
2186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (max_year < 2037)
2187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		max_year = 2037;
2188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	for (i = 0; i < zonecount; ++i) {
2189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		/*
2190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		** A guess that may well be corrected later.
2191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		*/
2192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		stdoff = 0;
2193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		zp = &zpfirst[i];
2194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		usestart = i > 0 && (zp - 1)->z_untiltime > min_time;
2195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		useuntil = i < (zonecount - 1);
2196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (useuntil && zp->z_untiltime <= min_time)
2197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			continue;
2198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		gmtoff = zp->z_gmtoff;
2199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		eat(zp->z_filename, zp->z_linenum);
2200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		*startbuf = '\0';
2201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		startoff = zp->z_gmtoff;
2202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef ICU
2203b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru		finalRuleYear = finalRuleIndex = -1;
2204b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru		finalRule1 = finalRule2 = NULL;
2205b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru		if (i == (zonecount - 1)) { /* !useuntil */
2206b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru			/* Look for exactly 2 rules that end at 'max' and
2207b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru			 * note them. Determine max(r_loyear) for the 2 of
2208b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru			 * them. */
2209b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru			for (j=0; j<zp->z_nrules; ++j) {
2210b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru				rp = &zp->z_rules[j];
2211b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru				if (rp->r_hiyear == INT_MAX) {
22128393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius					if (rp->r_loyear > finalRuleYear) {
22138393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius						finalRuleYear = rp->r_loyear;
22148393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius					}
2215b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru					if (finalRule1 == NULL) {
2216b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru						finalRule1 = rp;
22178393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius					} else if (finalRule2 == NULL) {
2218b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru						finalRule2 = rp;
2219b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru					} else {
2220b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru						error("more than two max rules found (ICU)");
2221b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru						exit(EXIT_FAILURE);
2222b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru					}
22238393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius				} else if (rp->r_hiyear >= finalRuleYear) {
22248393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius					/* There might be an overriding non-max rule
222559d709d503bab6e2b61931737e662dd293b40578ccornelius					 * to be applied to a specific year after one of
222659d709d503bab6e2b61931737e662dd293b40578ccornelius					 * max rule's start year. For example,
222759d709d503bab6e2b61931737e662dd293b40578ccornelius					 *
222859d709d503bab6e2b61931737e662dd293b40578ccornelius					 * Rule Foo 2010 max ...
222959d709d503bab6e2b61931737e662dd293b40578ccornelius					 * Rule Foo 2015 only ...
223059d709d503bab6e2b61931737e662dd293b40578ccornelius					 *
223159d709d503bab6e2b61931737e662dd293b40578ccornelius					 * In this case, we need to change the start year of
223259d709d503bab6e2b61931737e662dd293b40578ccornelius					 * the final (max) rules to the next year. */
22338393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius					finalRuleYear = rp->r_hiyear + 1;
223459d709d503bab6e2b61931737e662dd293b40578ccornelius
223559d709d503bab6e2b61931737e662dd293b40578ccornelius					/* When above adjustment is done, max_year might need
223659d709d503bab6e2b61931737e662dd293b40578ccornelius					 * to be adjusted, so the final rule will be properly
223759d709d503bab6e2b61931737e662dd293b40578ccornelius					 * evaluated and emitted by the later code block.
223859d709d503bab6e2b61931737e662dd293b40578ccornelius					 *
223959d709d503bab6e2b61931737e662dd293b40578ccornelius					 * Note: This may push the start year of the final
224059d709d503bab6e2b61931737e662dd293b40578ccornelius					 * rules ahead by 1 year unnecessarily. For example,
224159d709d503bab6e2b61931737e662dd293b40578ccornelius					 * If there are two rules, non-max rule and max rule
224259d709d503bab6e2b61931737e662dd293b40578ccornelius					 * starting in the same year, such as
224359d709d503bab6e2b61931737e662dd293b40578ccornelius					 *
224459d709d503bab6e2b61931737e662dd293b40578ccornelius					 * Rule Foo 2010 only ....
224559d709d503bab6e2b61931737e662dd293b40578ccornelius					 * Rule Foo 2010 max ....
224659d709d503bab6e2b61931737e662dd293b40578ccornelius					 *
224759d709d503bab6e2b61931737e662dd293b40578ccornelius					 * In this case, the final (max) rule actually starts
224859d709d503bab6e2b61931737e662dd293b40578ccornelius					 * in 2010, instead of 2010. We could make this tool
224959d709d503bab6e2b61931737e662dd293b40578ccornelius					 * more intelligent to detect such situation. But pushing
225059d709d503bab6e2b61931737e662dd293b40578ccornelius					 * final rule start year to 1 year ahead (in the worst case)
225159d709d503bab6e2b61931737e662dd293b40578ccornelius					 * will just populate a few extra transitions, and it still
225259d709d503bab6e2b61931737e662dd293b40578ccornelius					 * works fine. So for now, we're not trying to put additional
225359d709d503bab6e2b61931737e662dd293b40578ccornelius					 * logic to optimize the case.
225459d709d503bab6e2b61931737e662dd293b40578ccornelius					 */
225559d709d503bab6e2b61931737e662dd293b40578ccornelius					if (max_year < finalRuleYear) {
225659d709d503bab6e2b61931737e662dd293b40578ccornelius						max_year = finalRuleYear;
225759d709d503bab6e2b61931737e662dd293b40578ccornelius					}
2258b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru				}
2259b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru			}
2260b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru			if (finalRule1 != NULL) {
226159d709d503bab6e2b61931737e662dd293b40578ccornelius				if (finalRule2 == NULL) {
226259d709d503bab6e2b61931737e662dd293b40578ccornelius					warning("only one max rule found (ICU)");
2263b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru					finalRuleYear = finalRuleIndex = -1;
226459d709d503bab6e2b61931737e662dd293b40578ccornelius					finalRule1 = NULL;
2265b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru				} else {
226659d709d503bab6e2b61931737e662dd293b40578ccornelius					if (finalRule1->r_stdoff == finalRule2->r_stdoff) {
226759d709d503bab6e2b61931737e662dd293b40578ccornelius						/* America/Resolute in 2009a uses a pair of rules
226859d709d503bab6e2b61931737e662dd293b40578ccornelius						 * which does not change the offset.  ICU ignores
226959d709d503bab6e2b61931737e662dd293b40578ccornelius						 * such rules without actual time transitions. */
227059d709d503bab6e2b61931737e662dd293b40578ccornelius						finalRuleYear = finalRuleIndex = -1;
227159d709d503bab6e2b61931737e662dd293b40578ccornelius						finalRule1 = finalRule2 = NULL;
227259d709d503bab6e2b61931737e662dd293b40578ccornelius					} else {
227359d709d503bab6e2b61931737e662dd293b40578ccornelius						/* Swap if necessary so finalRule1 occurs before
227459d709d503bab6e2b61931737e662dd293b40578ccornelius						 * finalRule2 */
227559d709d503bab6e2b61931737e662dd293b40578ccornelius						if (finalRule1->r_month > finalRule2->r_month) {
227659d709d503bab6e2b61931737e662dd293b40578ccornelius							const struct rule* t = finalRule1;
227759d709d503bab6e2b61931737e662dd293b40578ccornelius							finalRule1 = finalRule2;
227859d709d503bab6e2b61931737e662dd293b40578ccornelius							finalRule2 = t;
227959d709d503bab6e2b61931737e662dd293b40578ccornelius						}
228059d709d503bab6e2b61931737e662dd293b40578ccornelius						/* Add final rule to our list */
228159d709d503bab6e2b61931737e662dd293b40578ccornelius						finalRuleIndex = add_icu_final_rules(finalRule1, finalRule2);
2282b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru					}
2283b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru				}
2284b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru			}
2285b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru		}
2286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
2287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (zp->z_nrules == 0) {
2289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			stdoff = zp->z_stdoff;
2290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			doabbr(startbuf, zp->z_format,
2291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				(char *) NULL, stdoff != 0, FALSE);
2292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			type = addtype(oadd(zp->z_gmtoff, stdoff),
2293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef ICU
2294b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru				zp->z_gmtoff, stdoff,
2295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
2296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				startbuf, stdoff != 0, startttisstd,
2297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				startttisgmt);
2298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (usestart) {
2299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				addtt(starttime, type);
2300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				usestart = FALSE;
2301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			} else if (stdoff != 0)
2302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				addtt(min_time, type);
2303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		} else for (year = min_year; year <= max_year; ++year) {
2304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (useuntil && year > zp->z_untilrule.r_hiyear)
2305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				break;
2306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			/*
2307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			** Mark which rules to do in the current year.
2308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			** For those to do, calculate rpytime(rp, year);
2309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			*/
2310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			for (j = 0; j < zp->z_nrules; ++j) {
2311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				rp = &zp->z_rules[j];
2312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				eats(zp->z_filename, zp->z_linenum,
2313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					rp->r_filename, rp->r_linenum);
2314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				rp->r_todo = year >= rp->r_loyear &&
2315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru						year <= rp->r_hiyear &&
2316b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru						yearistype(year, rp->r_yrtype);
2317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				if (rp->r_todo)
2318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					rp->r_temp = rpytime(rp, year);
2319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			}
2320b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			for ( ; ; ) {
2321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				register int	k;
2322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				register zic_t	jtime, ktime;
2323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				register long	offset;
2324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				INITIALIZE(ktime);
2326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				if (useuntil) {
2327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					/*
2328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					** Turn untiltime into UTC
2329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					** assuming the current gmtoff and
2330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					** stdoff values.
2331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					*/
2332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					untiltime = zp->z_untiltime;
2333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					if (!zp->z_untilrule.r_todisgmt)
2334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru						untiltime = tadd(untiltime,
2335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru							-gmtoff);
2336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					if (!zp->z_untilrule.r_todisstd)
2337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru						untiltime = tadd(untiltime,
2338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru							-stdoff);
2339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				}
2340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				/*
2341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				** Find the rule (of those to do, if any)
2342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				** that takes effect earliest in the year.
2343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				*/
2344b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				k = -1;
2345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				for (j = 0; j < zp->z_nrules; ++j) {
2346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					rp = &zp->z_rules[j];
2347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					if (!rp->r_todo)
2348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru						continue;
2349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					eats(zp->z_filename, zp->z_linenum,
2350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru						rp->r_filename, rp->r_linenum);
2351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					offset = rp->r_todisgmt ? 0 : gmtoff;
2352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					if (!rp->r_todisstd)
2353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru						offset = oadd(offset, stdoff);
2354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					jtime = rp->r_temp;
2355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					if (jtime == min_time ||
2356b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru						jtime == max_time)
2357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru							continue;
2358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					jtime = tadd(jtime, -offset);
2359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					if (k < 0 || jtime < ktime) {
2360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru						k = j;
2361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru						ktime = jtime;
2362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					}
2363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				}
2364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				if (k < 0)
2365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					break;	/* go on to next year */
2366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				rp = &zp->z_rules[k];
2367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				rp->r_todo = FALSE;
2368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				if (useuntil && ktime >= untiltime)
2369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					break;
2370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				stdoff = rp->r_stdoff;
2371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				if (usestart && ktime == starttime)
2372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					usestart = FALSE;
2373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				if (usestart) {
2374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					if (ktime < starttime) {
2375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru						startoff = oadd(zp->z_gmtoff,
2376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru							stdoff);
2377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru						doabbr(startbuf, zp->z_format,
2378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru							rp->r_abbrvar,
2379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru							rp->r_stdoff != 0,
2380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru							FALSE);
2381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru						continue;
2382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					}
2383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					if (*startbuf == '\0' &&
2384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru						startoff == oadd(zp->z_gmtoff,
2385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru						stdoff)) {
2386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru							doabbr(startbuf,
2387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru								zp->z_format,
2388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru								rp->r_abbrvar,
2389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru								rp->r_stdoff !=
2390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru								0,
2391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru								FALSE);
2392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					}
2393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				}
2394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef ICU
2395b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru				if (year >= finalRuleYear && rp == finalRule1) {
2396b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru					/* We want to shift final year 1 year after
2397b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru					 * the actual final rule takes effect (year + 1),
2398b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru					 * because the previous type is valid until the first
2399b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru					 * transition defined by the final rule.  Otherwise
2400b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru					 * we may see unexpected offset shift at the
2401b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru					 * begining of the year when the final rule takes
240259d709d503bab6e2b61931737e662dd293b40578ccornelius					 * effect.
240359d709d503bab6e2b61931737e662dd293b40578ccornelius					 *
240459d709d503bab6e2b61931737e662dd293b40578ccornelius					 * Note: This may results some 64bit second transitions
240559d709d503bab6e2b61931737e662dd293b40578ccornelius					 * at the very end (year 2038). ICU 4.2 or older releases
240659d709d503bab6e2b61931737e662dd293b40578ccornelius					 * cannot handle 64bit second transitions and they are
240759d709d503bab6e2b61931737e662dd293b40578ccornelius					 * dropped from zoneinfo.txt. */
2408b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru					emit_icu_zone(icuFile,
2409b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru							zpfirst->z_name, zp->z_gmtoff,
241050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho							rp, finalRuleIndex, year + 1);
2411b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru					/* only emit this for the first year */
2412b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru					finalRule1 = NULL;
2413b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru				}
2414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
2415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				eats(zp->z_filename, zp->z_linenum,
2416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					rp->r_filename, rp->r_linenum);
2417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				doabbr(ab, zp->z_format, rp->r_abbrvar,
2418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					rp->r_stdoff != 0, FALSE);
2419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				offset = oadd(zp->z_gmtoff, rp->r_stdoff);
2420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef ICU
2421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				type = addtype(offset, zp->z_gmtoff, rp->r_stdoff,
2422b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru					ab, rp->r_stdoff != 0,
2423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					rp->r_todisstd, rp->r_todisgmt);
2424b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#else
2425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				type = addtype(offset, ab, rp->r_stdoff != 0,
2426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					rp->r_todisstd, rp->r_todisgmt);
2427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
2428b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				addtt(ktime, type);
2429b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			}
2430b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
2431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (usestart) {
2432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (*startbuf == '\0' &&
2433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				zp->z_format != NULL &&
2434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				strchr(zp->z_format, '%') == NULL &&
2435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				strchr(zp->z_format, '/') == NULL)
2436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					(void) strcpy(startbuf, zp->z_format);
2437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			eat(zp->z_filename, zp->z_linenum);
2438b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (*startbuf == '\0')
2439b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruerror(_("can't determine time zone abbreviation to use just after until time"));
2440b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			else	addtt(starttime,
2441b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef ICU
2442b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					addtype(startoff,
2443b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru						zp->z_gmtoff, startoff - zp->z_gmtoff,
2444b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru						startbuf,
2445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru						startoff != zp->z_gmtoff,
2446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru						startttisstd,
2447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru						startttisgmt));
2448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#else
2449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					addtype(startoff, startbuf,
2450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru						startoff != zp->z_gmtoff,
2451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru						startttisstd,
2452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru						startttisgmt));
2453b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
2454b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
2455b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		/*
2456b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		** Now we may get to set starttime for the next zone line.
2457b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		*/
2458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (useuntil) {
2459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			startttisstd = zp->z_untilrule.r_todisstd;
2460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			startttisgmt = zp->z_untilrule.r_todisgmt;
2461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			starttime = zp->z_untiltime;
2462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (!startttisstd)
2463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				starttime = tadd(starttime, -stdoff);
2464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (!startttisgmt)
2465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				starttime = tadd(starttime, -gmtoff);
2466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
2467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
2468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	writezone(zpfirst->z_name, envvar);
2469b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	ifree(startbuf);
2470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	ifree(ab);
2471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	ifree(envvar);
2472b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void
2475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruaddtt(starttime, type)
2476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst zic_t	starttime;
2477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint		type;
2478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
2479b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (starttime <= min_time ||
2480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		(timecnt == 1 && attypes[0].at < min_time)) {
2481b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		gmtoffs[0] = gmtoffs[type];
2482b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef ICU
2483b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		rawoffs[0] = rawoffs[type];
2484b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		dstoffs[0] = dstoffs[type];
2485b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
2486b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		isdsts[0] = isdsts[type];
2487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		ttisstds[0] = ttisstds[type];
2488b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		ttisgmts[0] = ttisgmts[type];
2489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (abbrinds[type] != 0)
2490b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			(void) strcpy(chars, &chars[abbrinds[type]]);
2491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		abbrinds[0] = 0;
2492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		charcnt = strlen(chars) + 1;
2493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		typecnt = 1;
2494b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		timecnt = 0;
2495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		type = 0;
2496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
2497b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (timecnt >= TZ_MAX_TIMES) {
2498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		error(_("too many transitions?!"));
2499b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		exit(EXIT_FAILURE);
2500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
2501b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	attypes[timecnt].at = starttime;
2502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	attypes[timecnt].type = type;
2503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	++timecnt;
2504b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int
2507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef ICU
2508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruaddtype(gmtoff, rawoff, dstoff, abbr, isdst, ttisstd, ttisgmt)
2509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst long		gmtoff;
2510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst long		rawoff;
2511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst long		dstoff;
2512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#else
2513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruaddtype(gmtoff, abbr, isdst, ttisstd, ttisgmt)
2514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst long		gmtoff;
2515b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
2516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst char * const	abbr;
2517b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst int		isdst;
2518b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst int		ttisstd;
2519b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst int		ttisgmt;
2520b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
2521b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register int	i, j;
2522b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (isdst != TRUE && isdst != FALSE) {
2524b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		error(_("internal error - addtype called with bad isdst"));
2525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		exit(EXIT_FAILURE);
2526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
2527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (ttisstd != TRUE && ttisstd != FALSE) {
2528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		error(_("internal error - addtype called with bad ttisstd"));
2529b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		exit(EXIT_FAILURE);
2530b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
2531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (ttisgmt != TRUE && ttisgmt != FALSE) {
2532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		error(_("internal error - addtype called with bad ttisgmt"));
2533b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		exit(EXIT_FAILURE);
2534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
2535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef ICU
2536b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (isdst != (dstoff != 0)) {
2537b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		error(_("internal error - addtype called with bad isdst/dstoff"));
2538b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		(void) exit(EXIT_FAILURE);
2539b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
2540b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	if (gmtoff != (rawoff + dstoff)) {
2541b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		error(_("internal error - addtype called with bad gmt/raw/dstoff"));
2542b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		(void) exit(EXIT_FAILURE);
2543b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	}
2544b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
2545b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	/*
2546b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	** See if there's already an entry for this zone type.
2547b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	** If so, just return its index.
2548b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	*/
2549b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	for (i = 0; i < typecnt; ++i) {
2550b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (gmtoff == gmtoffs[i] && isdst == isdsts[i] &&
2551b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef ICU
2552b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru			rawoff == rawoffs[i] && dstoff == dstoffs[i] &&
2553b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
2554b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			strcmp(abbr, &chars[abbrinds[i]]) == 0 &&
2555b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			ttisstd == ttisstds[i] &&
2556b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			ttisgmt == ttisgmts[i])
2557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				return i;
2558b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
2559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	/*
2560b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	** There isn't one; add a new one, unless there are already too
2561b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	** many.
2562b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	*/
2563b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (typecnt >= TZ_MAX_TYPES) {
2564b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		error(_("too many local time types"));
2565b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		exit(EXIT_FAILURE);
2566b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
2567b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	if (! (-1L - 2147483647L <= gmtoff && gmtoff <= 2147483647L)) {
2568b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru		error(_("UTC offset out of range"));
2569b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru		exit(EXIT_FAILURE);
2570b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	}
2571b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	gmtoffs[i] = gmtoff;
2572b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef ICU
2573b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	rawoffs[i] = rawoff;
2574b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru	dstoffs[i] = dstoff;
2575b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
2576b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	isdsts[i] = isdst;
2577b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	ttisstds[i] = ttisstd;
2578b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	ttisgmts[i] = ttisgmt;
2579b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2580b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	for (j = 0; j < charcnt; ++j)
2581b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (strcmp(&chars[j], abbr) == 0)
2582b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			break;
2583b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (j == charcnt)
2584b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		newabbr(abbr);
2585b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	abbrinds[i] = j;
2586b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	++typecnt;
2587b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	return i;
2588b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2589b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2590b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void
2591b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruleapadd(t, positive, rolling, count)
2592b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst zic_t	t;
2593b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst int	positive;
2594b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst int	rolling;
2595b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint		count;
2596b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
2597b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register int	i, j;
2598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2599b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (leapcnt + (positive ? count : 1) > TZ_MAX_LEAPS) {
2600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		error(_("too many leap seconds"));
2601b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		exit(EXIT_FAILURE);
2602b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
2603b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	for (i = 0; i < leapcnt; ++i)
2604b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (t <= trans[i]) {
2605b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (t == trans[i]) {
2606b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				error(_("repeated leap second moment"));
2607b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				exit(EXIT_FAILURE);
2608b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			}
2609b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			break;
2610b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
2611b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	do {
2612b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		for (j = leapcnt; j > i; --j) {
2613b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			trans[j] = trans[j - 1];
2614b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			corr[j] = corr[j - 1];
2615b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			roll[j] = roll[j - 1];
2616b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
2617b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		trans[i] = t;
2618b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		corr[i] = positive ? 1L : eitol(-count);
2619b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		roll[i] = rolling;
2620b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		++leapcnt;
2621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	} while (positive && --count != 0);
2622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2623b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void
2625b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruadjleap(void)
2626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
2627b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register int	i;
2628b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register long	last = 0;
2629b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	/*
2631b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	** propagate leap seconds forward
2632b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	*/
2633b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	for (i = 0; i < leapcnt; ++i) {
2634b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		trans[i] = tadd(trans[i], last);
2635b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		last = corr[i] += last;
2636b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
2637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2639b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int
2640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruyearistype(year, type)
2641b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst int		year;
2642b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst char * const	type;
2643b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
2644b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	static char *	buf;
2645b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	int		result;
2646b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (type == NULL || *type == '\0')
2648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		return TRUE;
2649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	buf = erealloc(buf, (int) (132 + strlen(yitcommand) + strlen(type)));
2650b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	(void) sprintf(buf, "%s %d %s", yitcommand, year, type);
2651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	result = system(buf);
2652b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (WIFEXITED(result)) switch (WEXITSTATUS(result)) {
2653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		case 0:
2654b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			return TRUE;
2655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		case 1:
2656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			return FALSE;
2657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
2658b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	error(_("Wild result from command execution"));
2659b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	(void) fprintf(stderr, _("%s: command was '%s', result was %d\n"),
2660b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		progname, buf, result);
2661b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	for ( ; ; )
2662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		exit(EXIT_FAILURE);
2663b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2664b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2665b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int
2666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querulowerit(a)
2667b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint	a;
2668b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
2669b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	a = (unsigned char) a;
2670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	return (isascii(a) && isupper(a)) ? tolower(a) : a;
2671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int
2674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruciequal(ap, bp)		/* case-insensitive equality */
2675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruregister const char *	ap;
2676b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruregister const char *	bp;
2677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
2678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	while (lowerit(*ap) == lowerit(*bp++))
2679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (*ap++ == '\0')
2680b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			return TRUE;
2681b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	return FALSE;
2682b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2683b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2684b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int
2685b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruitsabbr(abbr, word)
2686b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruregister const char *	abbr;
2687b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruregister const char *	word;
2688b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
2689b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (lowerit(*abbr) != lowerit(*word))
2690b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		return FALSE;
2691b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	++word;
2692b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	while (*++abbr != '\0')
2693b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		do {
2694b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (*word == '\0')
2695b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				return FALSE;
2696b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		} while (lowerit(*word++) != lowerit(*abbr));
2697b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	return TRUE;
2698b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2699b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2700b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const struct lookup *
2701b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querubyword(word, table)
2702b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruregister const char * const		word;
2703b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruregister const struct lookup * const	table;
2704b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
2705b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register const struct lookup *	foundlp;
2706b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register const struct lookup *	lp;
2707b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2708b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (word == NULL || table == NULL)
2709b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		return NULL;
2710b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	/*
2711b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	** Look for exact match.
2712b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	*/
2713b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	for (lp = table; lp->l_word != NULL; ++lp)
2714b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (ciequal(word, lp->l_word))
2715b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			return lp;
2716b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	/*
2717b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	** Look for inexact match.
2718b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	*/
2719b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	foundlp = NULL;
2720b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	for (lp = table; lp->l_word != NULL; ++lp)
2721b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (itsabbr(word, lp->l_word)) {
2722b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (foundlp == NULL)
2723b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				foundlp = lp;
2724b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			else	return NULL;	/* multiple inexact matches */
2725b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
2726b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	return foundlp;
2727b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2728b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2729b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic char **
2730b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querugetfields(cp)
2731b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruregister char *	cp;
2732b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
2733b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register char *		dp;
2734b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register char **	array;
2735b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register int		nsubs;
2736b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2737b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (cp == NULL)
2738b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		return NULL;
2739b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	array = (char **) (void *)
2740b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		emalloc((int) ((strlen(cp) + 1) * sizeof *array));
2741b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	nsubs = 0;
2742b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	for ( ; ; ) {
2743b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		while (isascii((unsigned char) *cp) &&
2744b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			isspace((unsigned char) *cp))
2745b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				++cp;
2746b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (*cp == '\0' || *cp == '#')
2747b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			break;
2748b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		array[nsubs++] = dp = cp;
2749b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		do {
2750b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if ((*dp = *cp++) != '"')
2751b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				++dp;
2752b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			else while ((*dp = *cp++) != '"')
2753b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				if (*dp != '\0')
2754b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					++dp;
2755b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru				else {
2756b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru					error(_(
2757b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru						"Odd number of quotation marks"
2758b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru						));
2759b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru					exit(1);
2760b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru				}
2761b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		} while (*cp != '\0' && *cp != '#' &&
2762b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			(!isascii(*cp) || !isspace((unsigned char) *cp)));
2763b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (isascii(*cp) && isspace((unsigned char) *cp))
2764b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			++cp;
2765b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		*dp = '\0';
2766b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
2767b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	array[nsubs] = NULL;
2768b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	return array;
2769b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2770b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2771b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic long
2772b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruoadd(t1, t2)
2773b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst long	t1;
2774b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst long	t2;
2775b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
2776b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register long	t;
2777b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2778b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	t = t1 + t2;
2779b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if ((t2 > 0 && t <= t1) || (t2 < 0 && t >= t1)) {
2780b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		error(_("time overflow"));
2781b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		exit(EXIT_FAILURE);
2782b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
2783b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	return t;
2784b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2785b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2786b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic zic_t
2787b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querutadd(t1, t2)
2788b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst zic_t	t1;
2789b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst long	t2;
2790b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
2791b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register zic_t	t;
2792b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2793b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (t1 == max_time && t2 > 0)
2794b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		return max_time;
2795b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (t1 == min_time && t2 < 0)
2796b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		return min_time;
2797b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	t = t1 + t2;
2798b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if ((t2 > 0 && t <= t1) || (t2 < 0 && t >= t1)) {
2799b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		error(_("time overflow"));
2800b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		exit(EXIT_FAILURE);
2801b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
2802b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	return t;
2803b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2804b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2805b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
2806b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru** Given a rule, and a year, compute the date - in seconds since January 1,
2807b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru** 1970, 00:00 LOCAL time - in that year that the rule refers to.
2808b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
2809b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2810b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic zic_t
2811b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querurpytime(rp, wantedy)
2812b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruregister const struct rule * const	rp;
2813b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruregister const int			wantedy;
2814b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
2815b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register int	y, m, i;
2816b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register long	dayoff;			/* with a nod to Margaret O. */
2817b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register zic_t	t;
2818b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2819b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (wantedy == INT_MIN)
2820b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		return min_time;
2821b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (wantedy == INT_MAX)
2822b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		return max_time;
2823b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	dayoff = 0;
2824b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	m = TM_JANUARY;
2825b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	y = EPOCH_YEAR;
2826b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	while (wantedy != y) {
2827b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (wantedy > y) {
2828b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			i = len_years[isleap(y)];
2829b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			++y;
2830b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		} else {
2831b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			--y;
2832b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			i = -len_years[isleap(y)];
2833b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
2834b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		dayoff = oadd(dayoff, eitol(i));
2835b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
2836b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	while (m != rp->r_month) {
2837b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		i = len_months[isleap(y)][m];
2838b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		dayoff = oadd(dayoff, eitol(i));
2839b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		++m;
2840b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
2841b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	i = rp->r_dayofmonth;
2842b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (m == TM_FEBRUARY && i == 29 && !isleap(y)) {
2843b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (rp->r_dycode == DC_DOWLEQ)
2844b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			--i;
2845b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		else {
2846b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			error(_("use of 2/29 in non leap-year"));
2847b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			exit(EXIT_FAILURE);
2848b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
2849b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
2850b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	--i;
2851b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	dayoff = oadd(dayoff, eitol(i));
2852b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (rp->r_dycode == DC_DOWGEQ || rp->r_dycode == DC_DOWLEQ) {
2853b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		register long	wday;
2854b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2855b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define LDAYSPERWEEK	((long) DAYSPERWEEK)
2856b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		wday = eitol(EPOCH_WDAY);
2857b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		/*
2858b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		** Don't trust mod of negative numbers.
2859b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		*/
2860b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (dayoff >= 0)
2861b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			wday = (wday + dayoff) % LDAYSPERWEEK;
2862b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		else {
2863b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			wday -= ((-dayoff) % LDAYSPERWEEK);
2864b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (wday < 0)
2865b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				wday += LDAYSPERWEEK;
2866b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
2867b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		while (wday != eitol(rp->r_wday))
2868b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (rp->r_dycode == DC_DOWGEQ) {
2869b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				dayoff = oadd(dayoff, (long) 1);
2870b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				if (++wday >= LDAYSPERWEEK)
2871b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					wday = 0;
2872b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				++i;
2873b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			} else {
2874b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				dayoff = oadd(dayoff, (long) -1);
2875b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				if (--wday < 0)
2876b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					wday = LDAYSPERWEEK - 1;
2877b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				--i;
2878b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			}
2879b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (i < 0 || i >= len_months[isleap(y)][m]) {
2880b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (noise)
2881b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				warning(_("rule goes past start/end of month--\
2882b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruwill not work with pre-2004 versions of zic"));
2883b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
2884b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
2885b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (dayoff < min_time / SECSPERDAY)
2886b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		return min_time;
2887b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (dayoff > max_time / SECSPERDAY)
2888b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		return max_time;
2889b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	t = (zic_t) dayoff * SECSPERDAY;
2890b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	return tadd(t, rp->r_tod);
2891b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2892b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2893b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void
2894b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querunewabbr(string)
2895b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst char * const	string;
2896b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
2897b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register int	i;
2898b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2899b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (strcmp(string, GRANDPARENTED) != 0) {
2900b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		register const char *	cp;
2901b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		register char *		wp;
2902b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2903b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		/*
2904b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		** Want one to ZIC_MAX_ABBR_LEN_WO_WARN alphabetics
2905b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		** optionally followed by a + or - and a number from 1 to 14.
2906b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		*/
2907b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		cp = string;
2908b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		wp = NULL;
2909b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		while (isascii((unsigned char) *cp) &&
2910b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			isalpha((unsigned char) *cp))
2911b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				++cp;
2912b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (cp - string == 0)
2913b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruwp = _("time zone abbreviation lacks alphabetic at start");
2914b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (noise && cp - string > 3)
2915b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruwp = _("time zone abbreviation has more than 3 alphabetics");
2916b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (cp - string > ZIC_MAX_ABBR_LEN_WO_WARN)
2917b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruwp = _("time zone abbreviation has too many alphabetics");
2918b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (wp == NULL && (*cp == '+' || *cp == '-')) {
2919b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			++cp;
2920b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (isascii((unsigned char) *cp) &&
2921b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				isdigit((unsigned char) *cp))
2922b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					if (*cp++ == '1' &&
2923b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru						*cp >= '0' && *cp <= '4')
2924b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru							++cp;
2925b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
2926b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (*cp != '\0')
2927b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruwp = _("time zone abbreviation differs from POSIX standard");
2928b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (wp != NULL) {
2929b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			wp = ecpyalloc(wp);
2930b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			wp = ecatalloc(wp, " (");
2931b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			wp = ecatalloc(wp, string);
2932b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			wp = ecatalloc(wp, ")");
2933b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			warning(wp);
2934b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			ifree(wp);
2935b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
2936b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
2937b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	i = strlen(string) + 1;
2938b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (charcnt + i > TZ_MAX_CHARS) {
2939b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		error(_("too many, or too long, time zone abbreviations"));
2940b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		exit(EXIT_FAILURE);
2941b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
2942b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	(void) strcpy(&chars[charcnt], string);
2943b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	charcnt += eitol(i);
2944b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2945b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2946b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int
2947b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querumkdirs(argname)
2948b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruchar *		argname;
2949b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
2950b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register char *	name;
2951b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	register char *	cp;
2952b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2953b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if (argname == NULL || *argname == '\0')
2954b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		return 0;
2955b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	cp = name = ecpyalloc(argname);
2956b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	while ((cp = strchr(cp + 1, '/')) != 0) {
2957b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		*cp = '\0';
2958b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifndef unix
2959b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		/*
2960b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		** DOS drive specifier?
2961b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		*/
2962b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (isalpha((unsigned char) name[0]) &&
2963b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			name[1] == ':' && name[2] == '\0') {
2964b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				*cp = '/';
2965b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				continue;
2966b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
2967b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif /* !defined unix */
2968b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		if (!itsdir(name)) {
2969b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			/*
2970b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			** It doesn't seem to exist, so we try to create it.
2971b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			** Creation may fail because of the directory being
2972b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			** created by some other multiprocessor, so we get
2973b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			** to do extra checking.
2974b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			*/
2975b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			if (mkdir(name, MKDIR_UMASK) != 0) {
2976b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				const char *e = strerror(errno);
2977b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2978b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				if (errno != EEXIST || !itsdir(name)) {
2979b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					(void) fprintf(stderr,
2980b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru_("%s: Can't create directory %s: %s\n"),
2981b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru						progname, name, e);
2982b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					ifree(name);
2983b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru					return -1;
2984b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru				}
2985b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			}
2986b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		}
2987b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		*cp = '/';
2988b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
2989b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	ifree(name);
2990b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	return 0;
2991b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2992b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2993b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic long
2994b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querueitol(i)
2995b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst int	i;
2996b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
2997b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	long	l;
2998b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2999b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	l = i;
3000b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	if ((i < 0 && l >= 0) || (i == 0 && l != 0) || (i > 0 && l <= 0)) {
3001b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		(void) fprintf(stderr,
3002b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			_("%s: %d did not sign extend correctly\n"),
3003b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru			progname, i);
3004b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru		exit(EXIT_FAILURE);
3005b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	}
3006b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru	return l;
3007b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
3008b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
3009b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
3010b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru** UNIX was a registered trademark of The Open Group in 2003.
3011b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
3012