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