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