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