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