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