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