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