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