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