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