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