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