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