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