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