mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	Sync our copy of the timezone library with IANA release tzcode2019b.
A large fraction of this diff is just due to upstream's somewhat random decision to rename a bunch of internal variables and struct fields. However, there is an interesting new feature in zic: it's grown a "-b slim" option that emits zone files without 32-bit data and other backwards-compatibility hacks. We should consider whether we wish to enable that.
This commit is contained in:
		@@ -55,7 +55,7 @@ match properly on the old version.
 | 
			
		||||
Time Zone code
 | 
			
		||||
==============
 | 
			
		||||
 | 
			
		||||
The code in this directory is currently synced with tzcode release 2019a.
 | 
			
		||||
The code in this directory is currently synced with tzcode release 2019b.
 | 
			
		||||
There are many cosmetic (and not so cosmetic) differences from the
 | 
			
		||||
original tzcode library, but diffs in the upstream version should usually
 | 
			
		||||
be propagated to our version.  Here are some notes about that.
 | 
			
		||||
@@ -127,4 +127,7 @@ and then run them through pgindent.  (The first three sed patterns deal
 | 
			
		||||
with conversion of their block comment style to something pgindent
 | 
			
		||||
won't make a hash of; the remainder address other points noted above.)
 | 
			
		||||
After that, the files can be diff'd directly against our corresponding
 | 
			
		||||
files.
 | 
			
		||||
files.  Also, it's typically helpful to diff against the previous tzcode
 | 
			
		||||
release (after processing that the same way), and then try to apply the
 | 
			
		||||
diff to our files.  This will take care of most of the changes
 | 
			
		||||
mechanically.
 | 
			
		||||
 
 | 
			
		||||
@@ -107,15 +107,15 @@ static bool typesequiv(struct state const *, int, int);
 | 
			
		||||
 | 
			
		||||
static struct pg_tm tm;
 | 
			
		||||
 | 
			
		||||
/* Initialize *S to a value based on GMTOFF, ISDST, and ABBRIND.  */
 | 
			
		||||
/* Initialize *S to a value based on UTOFF, ISDST, and DESIGIDX.  */
 | 
			
		||||
static void
 | 
			
		||||
init_ttinfo(struct ttinfo *s, int32 gmtoff, bool isdst, int abbrind)
 | 
			
		||||
init_ttinfo(struct ttinfo *s, int32 utoff, bool isdst, int desigidx)
 | 
			
		||||
{
 | 
			
		||||
	s->tt_gmtoff = gmtoff;
 | 
			
		||||
	s->tt_utoff = utoff;
 | 
			
		||||
	s->tt_isdst = isdst;
 | 
			
		||||
	s->tt_abbrind = abbrind;
 | 
			
		||||
	s->tt_desigidx = desigidx;
 | 
			
		||||
	s->tt_ttisstd = false;
 | 
			
		||||
	s->tt_ttisgmt = false;
 | 
			
		||||
	s->tt_ttisut = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int32
 | 
			
		||||
@@ -251,7 +251,7 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
 | 
			
		||||
	for (stored = 4; stored <= 8; stored *= 2)
 | 
			
		||||
	{
 | 
			
		||||
		int32		ttisstdcnt = detzcode(up->tzhead.tzh_ttisstdcnt);
 | 
			
		||||
		int32		ttisgmtcnt = detzcode(up->tzhead.tzh_ttisgmtcnt);
 | 
			
		||||
		int32		ttisutcnt = detzcode(up->tzhead.tzh_ttisutcnt);
 | 
			
		||||
		int64		prevtr = 0;
 | 
			
		||||
		int32		prevcorr = 0;
 | 
			
		||||
		int32		leapcnt = detzcode(up->tzhead.tzh_leapcnt);
 | 
			
		||||
@@ -270,7 +270,7 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
 | 
			
		||||
			  && 0 <= timecnt && timecnt < TZ_MAX_TIMES
 | 
			
		||||
			  && 0 <= charcnt && charcnt < TZ_MAX_CHARS
 | 
			
		||||
			  && (ttisstdcnt == typecnt || ttisstdcnt == 0)
 | 
			
		||||
			  && (ttisgmtcnt == typecnt || ttisgmtcnt == 0)))
 | 
			
		||||
			  && (ttisutcnt == typecnt || ttisutcnt == 0)))
 | 
			
		||||
			return EINVAL;
 | 
			
		||||
		if (nread
 | 
			
		||||
			< (tzheadsize		/* struct tzhead */
 | 
			
		||||
@@ -280,7 +280,7 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
 | 
			
		||||
			   + charcnt		/* chars */
 | 
			
		||||
			   + leapcnt * (stored + 4) /* lsinfos */
 | 
			
		||||
			   + ttisstdcnt		/* ttisstds */
 | 
			
		||||
			   + ttisgmtcnt))	/* ttisgmts */
 | 
			
		||||
			   + ttisutcnt))	/* ttisuts */
 | 
			
		||||
			return EINVAL;
 | 
			
		||||
		sp->leapcnt = leapcnt;
 | 
			
		||||
		sp->timecnt = timecnt;
 | 
			
		||||
@@ -332,19 +332,19 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
 | 
			
		||||
		{
 | 
			
		||||
			struct ttinfo *ttisp;
 | 
			
		||||
			unsigned char isdst,
 | 
			
		||||
						abbrind;
 | 
			
		||||
						desigidx;
 | 
			
		||||
 | 
			
		||||
			ttisp = &sp->ttis[i];
 | 
			
		||||
			ttisp->tt_gmtoff = detzcode(p);
 | 
			
		||||
			ttisp->tt_utoff = detzcode(p);
 | 
			
		||||
			p += 4;
 | 
			
		||||
			isdst = *p++;
 | 
			
		||||
			if (!(isdst < 2))
 | 
			
		||||
				return EINVAL;
 | 
			
		||||
			ttisp->tt_isdst = isdst;
 | 
			
		||||
			abbrind = *p++;
 | 
			
		||||
			if (!(abbrind < sp->charcnt))
 | 
			
		||||
			desigidx = *p++;
 | 
			
		||||
			if (!(desigidx < sp->charcnt))
 | 
			
		||||
				return EINVAL;
 | 
			
		||||
			ttisp->tt_abbrind = abbrind;
 | 
			
		||||
			ttisp->tt_desigidx = desigidx;
 | 
			
		||||
		}
 | 
			
		||||
		for (i = 0; i < sp->charcnt; ++i)
 | 
			
		||||
			sp->chars[i] = *p++;
 | 
			
		||||
@@ -398,13 +398,13 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
 | 
			
		||||
			struct ttinfo *ttisp;
 | 
			
		||||
 | 
			
		||||
			ttisp = &sp->ttis[i];
 | 
			
		||||
			if (ttisgmtcnt == 0)
 | 
			
		||||
				ttisp->tt_ttisgmt = false;
 | 
			
		||||
			if (ttisutcnt == 0)
 | 
			
		||||
				ttisp->tt_ttisut = false;
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				if (*p != true && *p != false)
 | 
			
		||||
					return EINVAL;
 | 
			
		||||
				ttisp->tt_ttisgmt = *p++;
 | 
			
		||||
				ttisp->tt_ttisut = *p++;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@@ -438,13 +438,13 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
 | 
			
		||||
 | 
			
		||||
			for (i = 0; i < ts->typecnt; i++)
 | 
			
		||||
			{
 | 
			
		||||
				char	   *tsabbr = ts->chars + ts->ttis[i].tt_abbrind;
 | 
			
		||||
				char	   *tsabbr = ts->chars + ts->ttis[i].tt_desigidx;
 | 
			
		||||
				int			j;
 | 
			
		||||
 | 
			
		||||
				for (j = 0; j < charcnt; j++)
 | 
			
		||||
					if (strcmp(sp->chars + j, tsabbr) == 0)
 | 
			
		||||
					{
 | 
			
		||||
						ts->ttis[i].tt_abbrind = j;
 | 
			
		||||
						ts->ttis[i].tt_desigidx = j;
 | 
			
		||||
						gotabbr++;
 | 
			
		||||
						break;
 | 
			
		||||
					}
 | 
			
		||||
@@ -456,7 +456,7 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
 | 
			
		||||
					{
 | 
			
		||||
						strcpy(sp->chars + j, tsabbr);
 | 
			
		||||
						charcnt = j + tsabbrlen + 1;
 | 
			
		||||
						ts->ttis[i].tt_abbrind = j;
 | 
			
		||||
						ts->ttis[i].tt_desigidx = j;
 | 
			
		||||
						gotabbr++;
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
@@ -614,12 +614,13 @@ typesequiv(const struct state *sp, int a, int b)
 | 
			
		||||
		const struct ttinfo *ap = &sp->ttis[a];
 | 
			
		||||
		const struct ttinfo *bp = &sp->ttis[b];
 | 
			
		||||
 | 
			
		||||
		result = ap->tt_gmtoff == bp->tt_gmtoff &&
 | 
			
		||||
			ap->tt_isdst == bp->tt_isdst &&
 | 
			
		||||
			ap->tt_ttisstd == bp->tt_ttisstd &&
 | 
			
		||||
			ap->tt_ttisgmt == bp->tt_ttisgmt &&
 | 
			
		||||
			strcmp(&sp->chars[ap->tt_abbrind],
 | 
			
		||||
				   &sp->chars[bp->tt_abbrind]) == 0;
 | 
			
		||||
		result = (ap->tt_utoff == bp->tt_utoff
 | 
			
		||||
				  && ap->tt_isdst == bp->tt_isdst
 | 
			
		||||
				  && ap->tt_ttisstd == bp->tt_ttisstd
 | 
			
		||||
				  && ap->tt_ttisut == bp->tt_ttisut
 | 
			
		||||
				  && (strcmp(&sp->chars[ap->tt_desigidx],
 | 
			
		||||
							 &sp->chars[bp->tt_desigidx])
 | 
			
		||||
					  == 0));
 | 
			
		||||
	}
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
@@ -1176,7 +1177,7 @@ tzparse(const char *name, struct state *sp, bool lastditch)
 | 
			
		||||
				if (!sp->ttis[j].tt_isdst)
 | 
			
		||||
				{
 | 
			
		||||
					theirstdoffset =
 | 
			
		||||
						-sp->ttis[j].tt_gmtoff;
 | 
			
		||||
						-sp->ttis[j].tt_utoff;
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
@@ -1187,7 +1188,7 @@ tzparse(const char *name, struct state *sp, bool lastditch)
 | 
			
		||||
				if (sp->ttis[j].tt_isdst)
 | 
			
		||||
				{
 | 
			
		||||
					theirdstoffset =
 | 
			
		||||
						-sp->ttis[j].tt_gmtoff;
 | 
			
		||||
						-sp->ttis[j].tt_utoff;
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
@@ -1206,7 +1207,7 @@ tzparse(const char *name, struct state *sp, bool lastditch)
 | 
			
		||||
			{
 | 
			
		||||
				j = sp->types[i];
 | 
			
		||||
				sp->types[i] = sp->ttis[j].tt_isdst;
 | 
			
		||||
				if (sp->ttis[j].tt_ttisgmt)
 | 
			
		||||
				if (sp->ttis[j].tt_ttisut)
 | 
			
		||||
				{
 | 
			
		||||
					/* No adjustment to transition time */
 | 
			
		||||
				}
 | 
			
		||||
@@ -1234,7 +1235,7 @@ tzparse(const char *name, struct state *sp, bool lastditch)
 | 
			
		||||
							theirstdoffset;
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				theiroffset = -sp->ttis[j].tt_gmtoff;
 | 
			
		||||
				theiroffset = -sp->ttis[j].tt_utoff;
 | 
			
		||||
				if (sp->ttis[j].tt_isdst)
 | 
			
		||||
					theirdstoffset = theiroffset;
 | 
			
		||||
				else
 | 
			
		||||
@@ -1357,14 +1358,14 @@ localsub(struct state const *sp, pg_time_t const *timep,
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * To get (wrong) behavior that's compatible with System V Release 2.0
 | 
			
		||||
	 * you'd replace the statement below with t += ttisp->tt_gmtoff;
 | 
			
		||||
	 * you'd replace the statement below with t += ttisp->tt_utoff;
 | 
			
		||||
	 * timesub(&t, 0L, sp, tmp);
 | 
			
		||||
	 */
 | 
			
		||||
	result = timesub(&t, ttisp->tt_gmtoff, sp, tmp);
 | 
			
		||||
	result = timesub(&t, ttisp->tt_utoff, sp, tmp);
 | 
			
		||||
	if (result)
 | 
			
		||||
	{
 | 
			
		||||
		result->tm_isdst = ttisp->tt_isdst;
 | 
			
		||||
		result->tm_zone = (char *) &sp->chars[ttisp->tt_abbrind];
 | 
			
		||||
		result->tm_zone = (char *) &sp->chars[ttisp->tt_desigidx];
 | 
			
		||||
	}
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
@@ -1647,7 +1648,7 @@ pg_next_dst_boundary(const pg_time_t *timep,
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
		ttisp = &sp->ttis[i];
 | 
			
		||||
		*before_gmtoff = ttisp->tt_gmtoff;
 | 
			
		||||
		*before_gmtoff = ttisp->tt_utoff;
 | 
			
		||||
		*before_isdst = ttisp->tt_isdst;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -1700,7 +1701,7 @@ pg_next_dst_boundary(const pg_time_t *timep,
 | 
			
		||||
		/* No known transition > t, so use last known segment's type */
 | 
			
		||||
		i = sp->types[sp->timecnt - 1];
 | 
			
		||||
		ttisp = &sp->ttis[i];
 | 
			
		||||
		*before_gmtoff = ttisp->tt_gmtoff;
 | 
			
		||||
		*before_gmtoff = ttisp->tt_utoff;
 | 
			
		||||
		*before_isdst = ttisp->tt_isdst;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -1715,13 +1716,13 @@ pg_next_dst_boundary(const pg_time_t *timep,
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
		ttisp = &sp->ttis[i];
 | 
			
		||||
		*before_gmtoff = ttisp->tt_gmtoff;
 | 
			
		||||
		*before_gmtoff = ttisp->tt_utoff;
 | 
			
		||||
		*before_isdst = ttisp->tt_isdst;
 | 
			
		||||
		*boundary = sp->ats[0];
 | 
			
		||||
		/* And for "after", use the first segment's type */
 | 
			
		||||
		i = sp->types[0];
 | 
			
		||||
		ttisp = &sp->ttis[i];
 | 
			
		||||
		*after_gmtoff = ttisp->tt_gmtoff;
 | 
			
		||||
		*after_gmtoff = ttisp->tt_utoff;
 | 
			
		||||
		*after_isdst = ttisp->tt_isdst;
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
@@ -1743,12 +1744,12 @@ pg_next_dst_boundary(const pg_time_t *timep,
 | 
			
		||||
	}
 | 
			
		||||
	j = sp->types[i - 1];
 | 
			
		||||
	ttisp = &sp->ttis[j];
 | 
			
		||||
	*before_gmtoff = ttisp->tt_gmtoff;
 | 
			
		||||
	*before_gmtoff = ttisp->tt_utoff;
 | 
			
		||||
	*before_isdst = ttisp->tt_isdst;
 | 
			
		||||
	*boundary = sp->ats[i];
 | 
			
		||||
	j = sp->types[i];
 | 
			
		||||
	ttisp = &sp->ttis[j];
 | 
			
		||||
	*after_gmtoff = ttisp->tt_gmtoff;
 | 
			
		||||
	*after_gmtoff = ttisp->tt_utoff;
 | 
			
		||||
	*after_isdst = ttisp->tt_isdst;
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
@@ -1832,9 +1833,9 @@ pg_interpret_timezone_abbrev(const char *abbrev,
 | 
			
		||||
	for (i = cutoff - 1; i >= 0; i--)
 | 
			
		||||
	{
 | 
			
		||||
		ttisp = &sp->ttis[sp->types[i]];
 | 
			
		||||
		if (ttisp->tt_abbrind == abbrind)
 | 
			
		||||
		if (ttisp->tt_desigidx == abbrind)
 | 
			
		||||
		{
 | 
			
		||||
			*gmtoff = ttisp->tt_gmtoff;
 | 
			
		||||
			*gmtoff = ttisp->tt_utoff;
 | 
			
		||||
			*isdst = ttisp->tt_isdst;
 | 
			
		||||
			return true;
 | 
			
		||||
		}
 | 
			
		||||
@@ -1846,9 +1847,9 @@ pg_interpret_timezone_abbrev(const char *abbrev,
 | 
			
		||||
	for (i = cutoff; i < sp->timecnt; i++)
 | 
			
		||||
	{
 | 
			
		||||
		ttisp = &sp->ttis[sp->types[i]];
 | 
			
		||||
		if (ttisp->tt_abbrind == abbrind)
 | 
			
		||||
		if (ttisp->tt_desigidx == abbrind)
 | 
			
		||||
		{
 | 
			
		||||
			*gmtoff = ttisp->tt_gmtoff;
 | 
			
		||||
			*gmtoff = ttisp->tt_utoff;
 | 
			
		||||
			*isdst = ttisp->tt_isdst;
 | 
			
		||||
			return true;
 | 
			
		||||
		}
 | 
			
		||||
@@ -1875,10 +1876,10 @@ pg_get_timezone_offset(const pg_tz *tz, long int *gmtoff)
 | 
			
		||||
	sp = &tz->state;
 | 
			
		||||
	for (i = 1; i < sp->typecnt; i++)
 | 
			
		||||
	{
 | 
			
		||||
		if (sp->ttis[i].tt_gmtoff != sp->ttis[0].tt_gmtoff)
 | 
			
		||||
		if (sp->ttis[i].tt_utoff != sp->ttis[0].tt_utoff)
 | 
			
		||||
			return false;
 | 
			
		||||
	}
 | 
			
		||||
	*gmtoff = sp->ttis[0].tt_gmtoff;
 | 
			
		||||
	*gmtoff = sp->ttis[0].tt_utoff;
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -25,11 +25,11 @@
 | 
			
		||||
 | 
			
		||||
struct ttinfo
 | 
			
		||||
{								/* time type information */
 | 
			
		||||
	int32		tt_gmtoff;		/* UT offset in seconds */
 | 
			
		||||
	int32		tt_utoff;		/* UT offset in seconds */
 | 
			
		||||
	bool		tt_isdst;		/* used to set tm_isdst */
 | 
			
		||||
	int			tt_abbrind;		/* abbreviation list index */
 | 
			
		||||
	int			tt_desigidx;	/* abbreviation list index */
 | 
			
		||||
	bool		tt_ttisstd;		/* transition is std time */
 | 
			
		||||
	bool		tt_ttisgmt;		/* transition is UT */
 | 
			
		||||
	bool		tt_ttisut;		/* transition is UT */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct lsinfo
 | 
			
		||||
 
 | 
			
		||||
@@ -41,7 +41,7 @@ struct tzhead
 | 
			
		||||
	char		tzh_magic[4];	/* TZ_MAGIC */
 | 
			
		||||
	char		tzh_version[1]; /* '\0' or '2' or '3' as of 2013 */
 | 
			
		||||
	char		tzh_reserved[15];	/* reserved; must be zero */
 | 
			
		||||
	char		tzh_ttisgmtcnt[4];	/* coded number of trans. time flags */
 | 
			
		||||
	char		tzh_ttisutcnt[4];	/* coded number of trans. time flags */
 | 
			
		||||
	char		tzh_ttisstdcnt[4];	/* coded number of trans. time flags */
 | 
			
		||||
	char		tzh_leapcnt[4]; /* coded number of leap seconds */
 | 
			
		||||
	char		tzh_timecnt[4]; /* coded number of transition times */
 | 
			
		||||
@@ -64,14 +64,15 @@ struct tzhead
 | 
			
		||||
 *		one (char [4])		total correction after above
 | 
			
		||||
 *	tzh_ttisstdcnt (char)s		indexed by type; if 1, transition
 | 
			
		||||
 *					time is standard time, if 0,
 | 
			
		||||
 *					transition time is wall clock time
 | 
			
		||||
 *					if absent, transition times are
 | 
			
		||||
 *					assumed to be wall clock time
 | 
			
		||||
 *	tzh_ttisgmtcnt (char)s		indexed by type; if 1, transition
 | 
			
		||||
 *					time is UT, if 0,
 | 
			
		||||
 *					transition time is local time
 | 
			
		||||
 *					if absent, transition times are
 | 
			
		||||
 *					transition time is local (wall clock)
 | 
			
		||||
 *					time; if absent, transition times are
 | 
			
		||||
 *					assumed to be local time
 | 
			
		||||
 *	tzh_ttisutcnt (char)s		indexed by type; if 1, transition
 | 
			
		||||
 *					time is UT, if 0, transition time is
 | 
			
		||||
 *					local time; if absent, transition
 | 
			
		||||
 *					times are assumed to be local time.
 | 
			
		||||
 *					When this is 1, the corresponding
 | 
			
		||||
 *					std/wall indicator must also be 1.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 
 | 
			
		||||
@@ -77,12 +77,10 @@ struct rule
 | 
			
		||||
	int			r_wday;
 | 
			
		||||
 | 
			
		||||
	zic_t		r_tod;			/* time from midnight */
 | 
			
		||||
	bool		r_todisstd;		/* above is standard time if 1 or wall clock
 | 
			
		||||
								 * time if 0 */
 | 
			
		||||
	bool		r_todisgmt;		/* above is GMT if 1 or local time if 0 */
 | 
			
		||||
	bool		r_todisstd;		/* is r_tod standard time? */
 | 
			
		||||
	bool		r_todisut;		/* is r_tod UT? */
 | 
			
		||||
	bool		r_isdst;		/* is this daylight saving time? */
 | 
			
		||||
	zic_t		r_stdoff;		/* offset from default time (which is usually
 | 
			
		||||
								 * standard time) */
 | 
			
		||||
	zic_t		r_save;			/* offset from standard time */
 | 
			
		||||
	const char *r_abbrvar;		/* variable part of abbreviation */
 | 
			
		||||
 | 
			
		||||
	bool		r_todo;			/* a rule to do (used in outzone) */
 | 
			
		||||
@@ -103,13 +101,13 @@ struct zone
 | 
			
		||||
	lineno_t	z_linenum;
 | 
			
		||||
 | 
			
		||||
	const char *z_name;
 | 
			
		||||
	zic_t		z_gmtoff;
 | 
			
		||||
	zic_t		z_stdoff;
 | 
			
		||||
	char	   *z_rule;
 | 
			
		||||
	const char *z_format;
 | 
			
		||||
	char		z_format_specifier;
 | 
			
		||||
 | 
			
		||||
	bool		z_isdst;
 | 
			
		||||
	zic_t		z_stdoff;
 | 
			
		||||
	zic_t		z_save;
 | 
			
		||||
 | 
			
		||||
	struct rule *z_rules;
 | 
			
		||||
	ptrdiff_t	z_nrules;
 | 
			
		||||
@@ -133,7 +131,7 @@ static void associate(void);
 | 
			
		||||
static void dolink(const char *, const char *, bool);
 | 
			
		||||
static char **getfields(char *buf);
 | 
			
		||||
static zic_t gethms(const char *string, const char *errstring);
 | 
			
		||||
static zic_t getstdoff(char *, bool *);
 | 
			
		||||
static zic_t getsave(char *, bool *);
 | 
			
		||||
static void infile(const char *filename);
 | 
			
		||||
static void inleap(char **fields, int nfields);
 | 
			
		||||
static void inlink(char **fields, int nfields);
 | 
			
		||||
@@ -210,7 +208,7 @@ static int	typecnt;
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define ZF_NAME		1
 | 
			
		||||
#define ZF_GMTOFF	2
 | 
			
		||||
#define ZF_STDOFF	2
 | 
			
		||||
#define ZF_RULE		3
 | 
			
		||||
#define ZF_FORMAT	4
 | 
			
		||||
#define ZF_TILYEAR	5
 | 
			
		||||
@@ -224,7 +222,7 @@ static int	typecnt;
 | 
			
		||||
 * Which fields are which on a Zone continuation line.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define ZFC_GMTOFF	0
 | 
			
		||||
#define ZFC_STDOFF	0
 | 
			
		||||
#define ZFC_RULE	1
 | 
			
		||||
#define ZFC_FORMAT	2
 | 
			
		||||
#define ZFC_TILYEAR	3
 | 
			
		||||
@@ -245,7 +243,7 @@ static int	typecnt;
 | 
			
		||||
#define RF_MONTH	5
 | 
			
		||||
#define RF_DAY		6
 | 
			
		||||
#define RF_TOD		7
 | 
			
		||||
#define RF_STDOFF	8
 | 
			
		||||
#define RF_SAVE		8
 | 
			
		||||
#define RF_ABBRVAR	9
 | 
			
		||||
#define RULE_FIELDS	10
 | 
			
		||||
 | 
			
		||||
@@ -389,11 +387,11 @@ static struct attype
 | 
			
		||||
	bool		dontmerge;
 | 
			
		||||
	unsigned char type;
 | 
			
		||||
}		   *attypes;
 | 
			
		||||
static zic_t gmtoffs[TZ_MAX_TYPES];
 | 
			
		||||
static zic_t utoffs[TZ_MAX_TYPES];
 | 
			
		||||
static char isdsts[TZ_MAX_TYPES];
 | 
			
		||||
static unsigned char abbrinds[TZ_MAX_TYPES];
 | 
			
		||||
static unsigned char desigidx[TZ_MAX_TYPES];
 | 
			
		||||
static bool ttisstds[TZ_MAX_TYPES];
 | 
			
		||||
static bool ttisgmts[TZ_MAX_TYPES];
 | 
			
		||||
static bool ttisuts[TZ_MAX_TYPES];
 | 
			
		||||
static char chars[TZ_MAX_CHARS];
 | 
			
		||||
static zic_t trans[TZ_MAX_LEAPS];
 | 
			
		||||
static zic_t corr[TZ_MAX_LEAPS];
 | 
			
		||||
@@ -540,8 +538,9 @@ usage(FILE *stream, int status)
 | 
			
		||||
{
 | 
			
		||||
	fprintf(stream,
 | 
			
		||||
			_("%s: usage is %s [ --version ] [ --help ] [ -v ] [ -P ] \\\n"
 | 
			
		||||
			  "\t[ -l localtime ] [ -p posixrules ] [ -d directory ] \\\n"
 | 
			
		||||
			  "\t[ -t localtime-link ] [ -L leapseconds ] [ -r '[@lo][/@hi]' ] \\\n"
 | 
			
		||||
			  "\t[ -b {slim|fat} ] [ -d directory ] [ -l localtime ]"
 | 
			
		||||
			  " [ -L leapseconds ] \\\n"
 | 
			
		||||
			  "\t[ -p posixrules ] [ -r '[@lo][/@hi]' ] [ -t localtime-link ] \\\n"
 | 
			
		||||
			  "\t[ filename ... ]\n\n"
 | 
			
		||||
			  "Report bugs to %s.\n"),
 | 
			
		||||
			progname, progname, PACKAGE_BUGREPORT);
 | 
			
		||||
@@ -625,6 +624,21 @@ static const char *leapsec;
 | 
			
		||||
static const char *tzdefault;
 | 
			
		||||
static const char *yitcommand;
 | 
			
		||||
 | 
			
		||||
/* -1 if the TZif output file should be slim, 0 if default, 1 if the
 | 
			
		||||
   output should be fat for backward compatibility.  Currently the
 | 
			
		||||
   default is fat, although this may change.  */
 | 
			
		||||
static int	bloat;
 | 
			
		||||
 | 
			
		||||
static bool
 | 
			
		||||
want_bloat(void)
 | 
			
		||||
{
 | 
			
		||||
	return 0 <= bloat;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifndef ZIC_BLOAT_DEFAULT
 | 
			
		||||
#define ZIC_BLOAT_DEFAULT "fat"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
main(int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
@@ -655,11 +669,27 @@ main(int argc, char **argv)
 | 
			
		||||
		{
 | 
			
		||||
			usage(stdout, EXIT_SUCCESS);
 | 
			
		||||
		}
 | 
			
		||||
	while ((c = getopt(argc, argv, "d:l:L:p:Pr:st:vy:")) != EOF && c != -1)
 | 
			
		||||
	while ((c = getopt(argc, argv, "b:d:l:L:p:Pr:st:vy:")) != EOF && c != -1)
 | 
			
		||||
		switch (c)
 | 
			
		||||
		{
 | 
			
		||||
			default:
 | 
			
		||||
				usage(stderr, EXIT_FAILURE);
 | 
			
		||||
			case 'b':
 | 
			
		||||
				if (strcmp(optarg, "slim") == 0)
 | 
			
		||||
				{
 | 
			
		||||
					if (0 < bloat)
 | 
			
		||||
						error(_("incompatible -b options"));
 | 
			
		||||
					bloat = -1;
 | 
			
		||||
				}
 | 
			
		||||
				else if (strcmp(optarg, "fat") == 0)
 | 
			
		||||
				{
 | 
			
		||||
					if (bloat < 0)
 | 
			
		||||
						error(_("incompatible -b options"));
 | 
			
		||||
					bloat = 1;
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
					error(_("invalid option: -b '%s'"), optarg);
 | 
			
		||||
				break;
 | 
			
		||||
			case 'd':
 | 
			
		||||
				if (directory == NULL)
 | 
			
		||||
					directory = strdup(optarg);
 | 
			
		||||
@@ -759,6 +789,8 @@ main(int argc, char **argv)
 | 
			
		||||
		}
 | 
			
		||||
	if (optind == argc - 1 && strcmp(argv[optind], "=") == 0)
 | 
			
		||||
		usage(stderr, EXIT_FAILURE);	/* usage message by request */
 | 
			
		||||
	if (bloat == 0)
 | 
			
		||||
		bloat = strcmp(ZIC_BLOAT_DEFAULT, "slim") == 0 ? -1 : 1;
 | 
			
		||||
	if (directory == NULL)
 | 
			
		||||
		directory = "data";
 | 
			
		||||
	if (tzdefault == NULL)
 | 
			
		||||
@@ -1183,7 +1215,7 @@ associate(void)
 | 
			
		||||
			 * Maybe we have a local standard time offset.
 | 
			
		||||
			 */
 | 
			
		||||
			eat(zp->z_filename, zp->z_linenum);
 | 
			
		||||
			zp->z_stdoff = getstdoff(zp->z_rule, &zp->z_isdst);
 | 
			
		||||
			zp->z_save = getsave(zp->z_rule, &zp->z_isdst);
 | 
			
		||||
 | 
			
		||||
			/*
 | 
			
		||||
			 * Note, though, that if there's no rule, a '%s' in the format is
 | 
			
		||||
@@ -1380,10 +1412,10 @@ gethms(char const *string, char const *errstring)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static zic_t
 | 
			
		||||
getstdoff(char *field, bool *isdst)
 | 
			
		||||
getsave(char *field, bool *isdst)
 | 
			
		||||
{
 | 
			
		||||
	int			dst = -1;
 | 
			
		||||
	zic_t		stdoff;
 | 
			
		||||
	zic_t		save;
 | 
			
		||||
	size_t		fieldlen = strlen(field);
 | 
			
		||||
 | 
			
		||||
	if (fieldlen != 0)
 | 
			
		||||
@@ -1402,9 +1434,9 @@ getstdoff(char *field, bool *isdst)
 | 
			
		||||
				break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	stdoff = gethms(field, _("invalid saved time"));
 | 
			
		||||
	*isdst = dst < 0 ? stdoff != 0 : dst;
 | 
			
		||||
	return stdoff;
 | 
			
		||||
	save = gethms(field, _("invalid saved time"));
 | 
			
		||||
	*isdst = dst < 0 ? save != 0 : dst;
 | 
			
		||||
	return save;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -1443,7 +1475,7 @@ inrule(char **fields, int nfields)
 | 
			
		||||
	}
 | 
			
		||||
	r.r_filename = filename;
 | 
			
		||||
	r.r_linenum = linenum;
 | 
			
		||||
	r.r_stdoff = getstdoff(fields[RF_STDOFF], &r.r_isdst);
 | 
			
		||||
	r.r_save = getsave(fields[RF_SAVE], &r.r_isdst);
 | 
			
		||||
	rulesub(&r, fields[RF_LOYEAR], fields[RF_HIYEAR], fields[RF_COMMAND],
 | 
			
		||||
			fields[RF_MONTH], fields[RF_DAY], fields[RF_TOD]);
 | 
			
		||||
	r.r_name = ecpyalloc(fields[RF_NAME]);
 | 
			
		||||
@@ -1509,7 +1541,7 @@ inzsub(char **fields, int nfields, bool iscont)
 | 
			
		||||
	char	   *cp;
 | 
			
		||||
	char	   *cp1;
 | 
			
		||||
	static struct zone z;
 | 
			
		||||
	int			i_gmtoff,
 | 
			
		||||
	int			i_stdoff,
 | 
			
		||||
				i_rule,
 | 
			
		||||
				i_format;
 | 
			
		||||
	int			i_untilyear,
 | 
			
		||||
@@ -1520,7 +1552,7 @@ inzsub(char **fields, int nfields, bool iscont)
 | 
			
		||||
 | 
			
		||||
	if (iscont)
 | 
			
		||||
	{
 | 
			
		||||
		i_gmtoff = ZFC_GMTOFF;
 | 
			
		||||
		i_stdoff = ZFC_STDOFF;
 | 
			
		||||
		i_rule = ZFC_RULE;
 | 
			
		||||
		i_format = ZFC_FORMAT;
 | 
			
		||||
		i_untilyear = ZFC_TILYEAR;
 | 
			
		||||
@@ -1533,7 +1565,7 @@ inzsub(char **fields, int nfields, bool iscont)
 | 
			
		||||
		return false;
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		i_gmtoff = ZF_GMTOFF;
 | 
			
		||||
		i_stdoff = ZF_STDOFF;
 | 
			
		||||
		i_rule = ZF_RULE;
 | 
			
		||||
		i_format = ZF_FORMAT;
 | 
			
		||||
		i_untilyear = ZF_TILYEAR;
 | 
			
		||||
@@ -1544,7 +1576,7 @@ inzsub(char **fields, int nfields, bool iscont)
 | 
			
		||||
	}
 | 
			
		||||
	z.z_filename = filename;
 | 
			
		||||
	z.z_linenum = linenum;
 | 
			
		||||
	z.z_gmtoff = gethms(fields[i_gmtoff], _("invalid UT offset"));
 | 
			
		||||
	z.z_stdoff = gethms(fields[i_stdoff], _("invalid UT offset"));
 | 
			
		||||
	if ((cp = strchr(fields[i_format], '%')) != NULL)
 | 
			
		||||
	{
 | 
			
		||||
		if ((*++cp != 's' && *cp != 'z') || strchr(cp, '%')
 | 
			
		||||
@@ -1768,7 +1800,7 @@ rulesub(struct rule *rp, const char *loyearp, const char *hiyearp,
 | 
			
		||||
	}
 | 
			
		||||
	rp->r_month = lp->l_value;
 | 
			
		||||
	rp->r_todisstd = false;
 | 
			
		||||
	rp->r_todisgmt = false;
 | 
			
		||||
	rp->r_todisut = false;
 | 
			
		||||
	dp = ecpyalloc(timep);
 | 
			
		||||
	if (*dp != '\0')
 | 
			
		||||
	{
 | 
			
		||||
@@ -1777,19 +1809,19 @@ rulesub(struct rule *rp, const char *loyearp, const char *hiyearp,
 | 
			
		||||
		{
 | 
			
		||||
			case 's':			/* Standard */
 | 
			
		||||
				rp->r_todisstd = true;
 | 
			
		||||
				rp->r_todisgmt = false;
 | 
			
		||||
				rp->r_todisut = false;
 | 
			
		||||
				*ep = '\0';
 | 
			
		||||
				break;
 | 
			
		||||
			case 'w':			/* Wall */
 | 
			
		||||
				rp->r_todisstd = false;
 | 
			
		||||
				rp->r_todisgmt = false;
 | 
			
		||||
				rp->r_todisut = false;
 | 
			
		||||
				*ep = '\0';
 | 
			
		||||
				break;
 | 
			
		||||
			case 'g':			/* Greenwich */
 | 
			
		||||
			case 'u':			/* Universal */
 | 
			
		||||
			case 'z':			/* Zulu */
 | 
			
		||||
				rp->r_todisstd = true;
 | 
			
		||||
				rp->r_todisgmt = true;
 | 
			
		||||
				rp->r_todisut = true;
 | 
			
		||||
				*ep = '\0';
 | 
			
		||||
				break;
 | 
			
		||||
		}
 | 
			
		||||
@@ -1977,41 +2009,6 @@ atcomp(const void *avp, const void *bvp)
 | 
			
		||||
	return (a < b) ? -1 : (a > b);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
swaptypes(int i, int j)
 | 
			
		||||
{
 | 
			
		||||
	{
 | 
			
		||||
		zic_t		t = gmtoffs[i];
 | 
			
		||||
 | 
			
		||||
		gmtoffs[i] = gmtoffs[j];
 | 
			
		||||
		gmtoffs[j] = t;
 | 
			
		||||
	}
 | 
			
		||||
	{
 | 
			
		||||
		char		t = isdsts[i];
 | 
			
		||||
 | 
			
		||||
		isdsts[i] = isdsts[j];
 | 
			
		||||
		isdsts[j] = t;
 | 
			
		||||
	}
 | 
			
		||||
	{
 | 
			
		||||
		unsigned char t = abbrinds[i];
 | 
			
		||||
 | 
			
		||||
		abbrinds[i] = abbrinds[j];
 | 
			
		||||
		abbrinds[j] = t;
 | 
			
		||||
	}
 | 
			
		||||
	{
 | 
			
		||||
		bool		t = ttisstds[i];
 | 
			
		||||
 | 
			
		||||
		ttisstds[i] = ttisstds[j];
 | 
			
		||||
		ttisstds[j] = t;
 | 
			
		||||
	}
 | 
			
		||||
	{
 | 
			
		||||
		bool		t = ttisgmts[i];
 | 
			
		||||
 | 
			
		||||
		ttisgmts[i] = ttisgmts[j];
 | 
			
		||||
		ttisgmts[j] = t;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct timerange
 | 
			
		||||
{
 | 
			
		||||
	int			defaulttype;
 | 
			
		||||
@@ -2091,10 +2088,12 @@ writezone(const char *const name, const char *const string, char version,
 | 
			
		||||
		fromi = 0;
 | 
			
		||||
		for (; fromi < timecnt; ++fromi)
 | 
			
		||||
		{
 | 
			
		||||
			if (toi != 0 && ((attypes[fromi].at +
 | 
			
		||||
							  gmtoffs[attypes[toi - 1].type]) <=
 | 
			
		||||
							 (attypes[toi - 1].at + gmtoffs[toi == 1 ? 0
 | 
			
		||||
															: attypes[toi - 2].type])))
 | 
			
		||||
			if (toi != 0
 | 
			
		||||
				&& ((attypes[fromi].at
 | 
			
		||||
					 + utoffs[attypes[toi - 1].type])
 | 
			
		||||
					<= (attypes[toi - 1].at
 | 
			
		||||
						+ utoffs[toi == 1 ? 0
 | 
			
		||||
								 : attypes[toi - 2].type])))
 | 
			
		||||
			{
 | 
			
		||||
				attypes[toi - 1].type =
 | 
			
		||||
					attypes[fromi].type;
 | 
			
		||||
@@ -2102,7 +2101,12 @@ writezone(const char *const name, const char *const string, char version,
 | 
			
		||||
			}
 | 
			
		||||
			if (toi == 0
 | 
			
		||||
				|| attypes[fromi].dontmerge
 | 
			
		||||
				|| attypes[toi - 1].type != attypes[fromi].type)
 | 
			
		||||
				|| (utoffs[attypes[toi - 1].type]
 | 
			
		||||
					!= utoffs[attypes[fromi].type])
 | 
			
		||||
				|| (isdsts[attypes[toi - 1].type]
 | 
			
		||||
					!= isdsts[attypes[fromi].type])
 | 
			
		||||
				|| (desigidx[attypes[toi - 1].type]
 | 
			
		||||
					!= desigidx[attypes[fromi].type]))
 | 
			
		||||
				attypes[toi++] = attypes[fromi];
 | 
			
		||||
		}
 | 
			
		||||
		timecnt = toi;
 | 
			
		||||
@@ -2151,7 +2155,7 @@ writezone(const char *const name, const char *const string, char version,
 | 
			
		||||
	 * before 32-bit pg_time_t rolls around, and this occurs at a slightly
 | 
			
		||||
	 * different moment if transitions are leap-second corrected.
 | 
			
		||||
	 */
 | 
			
		||||
	if (WORK_AROUND_QTBUG_53071 && timecnt != 0
 | 
			
		||||
	if (WORK_AROUND_QTBUG_53071 && timecnt != 0 && want_bloat()
 | 
			
		||||
		&& ats[timecnt - 1] < y2038_boundary - 1 && strchr(string, '<'))
 | 
			
		||||
	{
 | 
			
		||||
		ats[timecnt] = y2038_boundary - 1;
 | 
			
		||||
@@ -2213,7 +2217,9 @@ writezone(const char *const name, const char *const string, char version,
 | 
			
		||||
		int			old0;
 | 
			
		||||
		char		omittype[TZ_MAX_TYPES];
 | 
			
		||||
		int			typemap[TZ_MAX_TYPES];
 | 
			
		||||
		int			thistypecnt;
 | 
			
		||||
		int			thistypecnt,
 | 
			
		||||
					stdcnt,
 | 
			
		||||
					utcnt;
 | 
			
		||||
		char		thischars[TZ_MAX_CHARS];
 | 
			
		||||
		int			thischarcnt;
 | 
			
		||||
		bool		toomanytimes;
 | 
			
		||||
@@ -2293,7 +2299,6 @@ writezone(const char *const name, const char *const string, char version,
 | 
			
		||||
		 * in the output instead of OLD0.  TYPEMAP also omits unused types.
 | 
			
		||||
		 */
 | 
			
		||||
		old0 = strlen(omittype);
 | 
			
		||||
		swaptypes(old0, thisdefaulttype);
 | 
			
		||||
 | 
			
		||||
#ifndef LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH
 | 
			
		||||
 | 
			
		||||
@@ -2303,6 +2308,7 @@ writezone(const char *const name, const char *const string, char version,
 | 
			
		||||
		 * offset, append an (unused) copy of the most recently used type (to
 | 
			
		||||
		 * help get global "altzone" and "timezone" variables set correctly).
 | 
			
		||||
		 */
 | 
			
		||||
		if (want_bloat())
 | 
			
		||||
		{
 | 
			
		||||
			int			mrudst,
 | 
			
		||||
						mrustd,
 | 
			
		||||
@@ -2317,34 +2323,39 @@ writezone(const char *const name, const char *const string, char version,
 | 
			
		||||
				else
 | 
			
		||||
					mrustd = types[i];
 | 
			
		||||
			for (i = old0; i < typecnt; i++)
 | 
			
		||||
				if (!omittype[i])
 | 
			
		||||
			{
 | 
			
		||||
				int			h = (i == old0 ? thisdefaulttype
 | 
			
		||||
								 : i == thisdefaulttype ? old0 : i);
 | 
			
		||||
 | 
			
		||||
				if (!omittype[h])
 | 
			
		||||
				{
 | 
			
		||||
					if (isdsts[i])
 | 
			
		||||
					if (isdsts[h])
 | 
			
		||||
						hidst = i;
 | 
			
		||||
					else
 | 
			
		||||
						histd = i;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if (hidst >= 0 && mrudst >= 0 && hidst != mrudst &&
 | 
			
		||||
				gmtoffs[hidst] != gmtoffs[mrudst])
 | 
			
		||||
				utoffs[hidst] != utoffs[mrudst])
 | 
			
		||||
			{
 | 
			
		||||
				isdsts[mrudst] = -1;
 | 
			
		||||
				type = addtype(gmtoffs[mrudst],
 | 
			
		||||
							   &chars[abbrinds[mrudst]],
 | 
			
		||||
				type = addtype(utoffs[mrudst],
 | 
			
		||||
							   &chars[desigidx[mrudst]],
 | 
			
		||||
							   true,
 | 
			
		||||
							   ttisstds[mrudst],
 | 
			
		||||
							   ttisgmts[mrudst]);
 | 
			
		||||
							   ttisuts[mrudst]);
 | 
			
		||||
				isdsts[mrudst] = 1;
 | 
			
		||||
				omittype[type] = false;
 | 
			
		||||
			}
 | 
			
		||||
			if (histd >= 0 && mrustd >= 0 && histd != mrustd &&
 | 
			
		||||
				gmtoffs[histd] != gmtoffs[mrustd])
 | 
			
		||||
				utoffs[histd] != utoffs[mrustd])
 | 
			
		||||
			{
 | 
			
		||||
				isdsts[mrustd] = -1;
 | 
			
		||||
				type = addtype(gmtoffs[mrustd],
 | 
			
		||||
							   &chars[abbrinds[mrustd]],
 | 
			
		||||
				type = addtype(utoffs[mrustd],
 | 
			
		||||
							   &chars[desigidx[mrustd]],
 | 
			
		||||
							   false,
 | 
			
		||||
							   ttisstds[mrustd],
 | 
			
		||||
							   ttisgmts[mrustd]);
 | 
			
		||||
							   ttisuts[mrustd]);
 | 
			
		||||
				isdsts[mrustd] = 0;
 | 
			
		||||
				omittype[type] = false;
 | 
			
		||||
			}
 | 
			
		||||
@@ -2360,16 +2371,20 @@ writezone(const char *const name, const char *const string, char version,
 | 
			
		||||
 | 
			
		||||
		for (i = 0; i < sizeof indmap / sizeof indmap[0]; ++i)
 | 
			
		||||
			indmap[i] = -1;
 | 
			
		||||
		thischarcnt = 0;
 | 
			
		||||
		thischarcnt = stdcnt = utcnt = 0;
 | 
			
		||||
		for (i = old0; i < typecnt; i++)
 | 
			
		||||
		{
 | 
			
		||||
			char	   *thisabbr;
 | 
			
		||||
 | 
			
		||||
			if (omittype[i])
 | 
			
		||||
				continue;
 | 
			
		||||
			if (indmap[abbrinds[i]] >= 0)
 | 
			
		||||
			if (ttisstds[i])
 | 
			
		||||
				stdcnt = thistypecnt;
 | 
			
		||||
			if (ttisuts[i])
 | 
			
		||||
				utcnt = thistypecnt;
 | 
			
		||||
			if (indmap[desigidx[i]] >= 0)
 | 
			
		||||
				continue;
 | 
			
		||||
			thisabbr = &chars[abbrinds[i]];
 | 
			
		||||
			thisabbr = &chars[desigidx[i]];
 | 
			
		||||
			for (j = 0; j < thischarcnt; ++j)
 | 
			
		||||
				if (strcmp(&thischars[j], thisabbr) == 0)
 | 
			
		||||
					break;
 | 
			
		||||
@@ -2378,14 +2393,21 @@ writezone(const char *const name, const char *const string, char version,
 | 
			
		||||
				strcpy(&thischars[thischarcnt], thisabbr);
 | 
			
		||||
				thischarcnt += strlen(thisabbr) + 1;
 | 
			
		||||
			}
 | 
			
		||||
			indmap[abbrinds[i]] = j;
 | 
			
		||||
			indmap[desigidx[i]] = j;
 | 
			
		||||
		}
 | 
			
		||||
		if (pass == 1 && !want_bloat())
 | 
			
		||||
		{
 | 
			
		||||
			utcnt = stdcnt = thisleapcnt = 0;
 | 
			
		||||
			thistimecnt = -locut - hicut;
 | 
			
		||||
			thistypecnt = thischarcnt = 1;
 | 
			
		||||
			thistimelim = thistimei;
 | 
			
		||||
		}
 | 
			
		||||
#define DO(field)	fwrite(tzh.field, sizeof tzh.field, 1, fp)
 | 
			
		||||
		tzh = tzh0;
 | 
			
		||||
		memcpy(tzh.tzh_magic, TZ_MAGIC, sizeof tzh.tzh_magic);
 | 
			
		||||
		tzh.tzh_version[0] = version;
 | 
			
		||||
		convert(thistypecnt, tzh.tzh_ttisgmtcnt);
 | 
			
		||||
		convert(thistypecnt, tzh.tzh_ttisstdcnt);
 | 
			
		||||
		convert(utcnt, tzh.tzh_ttisutcnt);
 | 
			
		||||
		convert(stdcnt, tzh.tzh_ttisstdcnt);
 | 
			
		||||
		convert(thisleapcnt, tzh.tzh_leapcnt);
 | 
			
		||||
		convert(locut + thistimecnt + hicut, tzh.tzh_timecnt);
 | 
			
		||||
		convert(thistypecnt, tzh.tzh_typecnt);
 | 
			
		||||
@@ -2393,13 +2415,22 @@ writezone(const char *const name, const char *const string, char version,
 | 
			
		||||
		DO(tzh_magic);
 | 
			
		||||
		DO(tzh_version);
 | 
			
		||||
		DO(tzh_reserved);
 | 
			
		||||
		DO(tzh_ttisgmtcnt);
 | 
			
		||||
		DO(tzh_ttisutcnt);
 | 
			
		||||
		DO(tzh_ttisstdcnt);
 | 
			
		||||
		DO(tzh_leapcnt);
 | 
			
		||||
		DO(tzh_timecnt);
 | 
			
		||||
		DO(tzh_typecnt);
 | 
			
		||||
		DO(tzh_charcnt);
 | 
			
		||||
#undef DO
 | 
			
		||||
		if (pass == 1 && !want_bloat())
 | 
			
		||||
		{
 | 
			
		||||
			/* Output a minimal data block with just one time type.  */
 | 
			
		||||
			puttzcode(0, fp);	/* utoff */
 | 
			
		||||
			putc(0, fp);		/* dst */
 | 
			
		||||
			putc(0, fp);		/* index of abbreviation */
 | 
			
		||||
			putc(0, fp);		/* empty-string abbreviation */
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* PG: print current timezone abbreviations if requested */
 | 
			
		||||
		if (print_abbrevs && pass == 2)
 | 
			
		||||
@@ -2410,14 +2441,14 @@ writezone(const char *const name, const char *const string, char version,
 | 
			
		||||
				if (i == thistimelim - 1 || ats[i + 1] > print_cutoff)
 | 
			
		||||
				{
 | 
			
		||||
					unsigned char tm = types[i];
 | 
			
		||||
					char	   *thisabbrev = &thischars[indmap[abbrinds[tm]]];
 | 
			
		||||
					char	   *thisabbrev = &thischars[indmap[desigidx[tm]]];
 | 
			
		||||
 | 
			
		||||
					/* filter out assorted junk entries */
 | 
			
		||||
					if (strcmp(thisabbrev, GRANDPARENTED) != 0 &&
 | 
			
		||||
						strcmp(thisabbrev, "zzz") != 0)
 | 
			
		||||
						fprintf(stdout, "%s\t" INT64_FORMAT "%s\n",
 | 
			
		||||
								thisabbrev,
 | 
			
		||||
								gmtoffs[tm],
 | 
			
		||||
								utoffs[tm],
 | 
			
		||||
								isdsts[tm] ? "\tD" : "");
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
@@ -2425,14 +2456,14 @@ writezone(const char *const name, const char *const string, char version,
 | 
			
		||||
			if (thistimei >= thistimelim)
 | 
			
		||||
			{
 | 
			
		||||
				unsigned char tm = defaulttype;
 | 
			
		||||
				char	   *thisabbrev = &thischars[indmap[abbrinds[tm]]];
 | 
			
		||||
				char	   *thisabbrev = &thischars[indmap[desigidx[tm]]];
 | 
			
		||||
 | 
			
		||||
				/* filter out assorted junk entries */
 | 
			
		||||
				if (strcmp(thisabbrev, GRANDPARENTED) != 0 &&
 | 
			
		||||
					strcmp(thisabbrev, "zzz") != 0)
 | 
			
		||||
					fprintf(stdout, "%s\t" INT64_FORMAT "%s\n",
 | 
			
		||||
							thisabbrev,
 | 
			
		||||
							gmtoffs[tm],
 | 
			
		||||
							utoffs[tm],
 | 
			
		||||
							isdsts[tm] ? "\tD" : "");
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
@@ -2465,12 +2496,17 @@ writezone(const char *const name, const char *const string, char version,
 | 
			
		||||
			putc(currenttype, fp);
 | 
			
		||||
 | 
			
		||||
		for (i = old0; i < typecnt; i++)
 | 
			
		||||
			if (!omittype[i])
 | 
			
		||||
		{
 | 
			
		||||
			int			h = (i == old0 ? thisdefaulttype
 | 
			
		||||
							 : i == thisdefaulttype ? old0 : i);
 | 
			
		||||
 | 
			
		||||
			if (!omittype[h])
 | 
			
		||||
			{
 | 
			
		||||
				puttzcode(gmtoffs[i], fp);
 | 
			
		||||
				putc(isdsts[i], fp);
 | 
			
		||||
				putc((unsigned char) indmap[abbrinds[i]], fp);
 | 
			
		||||
				puttzcode(utoffs[h], fp);
 | 
			
		||||
				putc(isdsts[h], fp);
 | 
			
		||||
				putc(indmap[desigidx[h]], fp);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if (thischarcnt != 0)
 | 
			
		||||
			fwrite(thischars, sizeof thischars[0],
 | 
			
		||||
				   thischarcnt, fp);
 | 
			
		||||
@@ -2498,20 +2534,21 @@ writezone(const char *const name, const char *const string, char version,
 | 
			
		||||
						++j;
 | 
			
		||||
					j = types[j - 1];
 | 
			
		||||
				}
 | 
			
		||||
				todo = tadd(trans[i], -gmtoffs[j]);
 | 
			
		||||
				todo = tadd(trans[i], -utoffs[j]);
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
				todo = trans[i];
 | 
			
		||||
			puttzcodepass(todo, fp, pass);
 | 
			
		||||
			puttzcode(corr[i], fp);
 | 
			
		||||
		}
 | 
			
		||||
		for (i = old0; i < typecnt; i++)
 | 
			
		||||
			if (!omittype[i])
 | 
			
		||||
				putc(ttisstds[i], fp);
 | 
			
		||||
		for (i = old0; i < typecnt; i++)
 | 
			
		||||
			if (!omittype[i])
 | 
			
		||||
				putc(ttisgmts[i], fp);
 | 
			
		||||
		swaptypes(old0, thisdefaulttype);
 | 
			
		||||
		if (stdcnt != 0)
 | 
			
		||||
			for (i = old0; i < typecnt; i++)
 | 
			
		||||
				if (!omittype[i])
 | 
			
		||||
					putc(ttisstds[i], fp);
 | 
			
		||||
		if (utcnt != 0)
 | 
			
		||||
			for (i = old0; i < typecnt; i++)
 | 
			
		||||
				if (!omittype[i])
 | 
			
		||||
					putc(ttisuts[i], fp);
 | 
			
		||||
	}
 | 
			
		||||
	fprintf(fp, "\n%s\n", string);
 | 
			
		||||
	close_file(fp, directory, name);
 | 
			
		||||
@@ -2564,7 +2601,7 @@ abbroffset(char *buf, zic_t offset)
 | 
			
		||||
 | 
			
		||||
static size_t
 | 
			
		||||
doabbr(char *abbr, struct zone const *zp, char const *letters,
 | 
			
		||||
	   bool isdst, zic_t stdoff, bool doquotes)
 | 
			
		||||
	   bool isdst, zic_t save, bool doquotes)
 | 
			
		||||
{
 | 
			
		||||
	char	   *cp;
 | 
			
		||||
	char	   *slashp;
 | 
			
		||||
@@ -2577,7 +2614,7 @@ doabbr(char *abbr, struct zone const *zp, char const *letters,
 | 
			
		||||
		char		letterbuf[PERCENT_Z_LEN_BOUND + 1];
 | 
			
		||||
 | 
			
		||||
		if (zp->z_format_specifier == 'z')
 | 
			
		||||
			letters = abbroffset(letterbuf, zp->z_gmtoff + stdoff);
 | 
			
		||||
			letters = abbroffset(letterbuf, zp->z_stdoff + save);
 | 
			
		||||
		else if (!letters)
 | 
			
		||||
			letters = "%s";
 | 
			
		||||
		sprintf(abbr, format, letters);
 | 
			
		||||
@@ -2649,8 +2686,7 @@ stringoffset(char *result, zic_t offset)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
stringrule(char *result, const struct rule *const rp, const zic_t dstoff,
 | 
			
		||||
		   const zic_t gmtoff)
 | 
			
		||||
stringrule(char *result, struct rule *const rp, zic_t save, zic_t stdoff)
 | 
			
		||||
{
 | 
			
		||||
	zic_t		tod = rp->r_tod;
 | 
			
		||||
	int			compat = 0;
 | 
			
		||||
@@ -2707,10 +2743,10 @@ stringrule(char *result, const struct rule *const rp, const zic_t dstoff,
 | 
			
		||||
		result += sprintf(result, "M%d.%d.%d",
 | 
			
		||||
						  rp->r_month + 1, week, wday);
 | 
			
		||||
	}
 | 
			
		||||
	if (rp->r_todisgmt)
 | 
			
		||||
		tod += gmtoff;
 | 
			
		||||
	if (rp->r_todisut)
 | 
			
		||||
		tod += stdoff;
 | 
			
		||||
	if (rp->r_todisstd && !rp->r_isdst)
 | 
			
		||||
		tod += dstoff;
 | 
			
		||||
		tod += save;
 | 
			
		||||
	if (tod != 2 * SECSPERMIN * MINSPERHOUR)
 | 
			
		||||
	{
 | 
			
		||||
		*result++ = '/';
 | 
			
		||||
@@ -2744,10 +2780,6 @@ rule_cmp(struct rule const *a, struct rule const *b)
 | 
			
		||||
	return a->r_dayofmonth - b->r_dayofmonth;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
enum
 | 
			
		||||
{
 | 
			
		||||
YEAR_BY_YEAR_ZONE = 1};
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
stringzone(char *result, struct zone const *zpfirst, ptrdiff_t zonecount)
 | 
			
		||||
{
 | 
			
		||||
@@ -2813,15 +2845,6 @@ stringzone(char *result, struct zone const *zpfirst, ptrdiff_t zonecount)
 | 
			
		||||
			if (rule_cmp(stdrp, rp) < 0)
 | 
			
		||||
				stdrp = rp;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
		 * Horrid special case: if year is 2037, presume this is a zone
 | 
			
		||||
		 * handled on a year-by-year basis; do not try to apply a rule to the
 | 
			
		||||
		 * zone.
 | 
			
		||||
		 */
 | 
			
		||||
		if (stdrp != NULL && stdrp->r_hiyear == 2037)
 | 
			
		||||
			return YEAR_BY_YEAR_ZONE;
 | 
			
		||||
 | 
			
		||||
		if (stdrp != NULL && stdrp->r_isdst)
 | 
			
		||||
		{
 | 
			
		||||
			/* Perpetual DST.  */
 | 
			
		||||
@@ -2829,17 +2852,17 @@ stringzone(char *result, struct zone const *zpfirst, ptrdiff_t zonecount)
 | 
			
		||||
			dstr.r_dycode = DC_DOM;
 | 
			
		||||
			dstr.r_dayofmonth = 1;
 | 
			
		||||
			dstr.r_tod = 0;
 | 
			
		||||
			dstr.r_todisstd = dstr.r_todisgmt = false;
 | 
			
		||||
			dstr.r_todisstd = dstr.r_todisut = false;
 | 
			
		||||
			dstr.r_isdst = stdrp->r_isdst;
 | 
			
		||||
			dstr.r_stdoff = stdrp->r_stdoff;
 | 
			
		||||
			dstr.r_save = stdrp->r_save;
 | 
			
		||||
			dstr.r_abbrvar = stdrp->r_abbrvar;
 | 
			
		||||
			stdr.r_month = TM_DECEMBER;
 | 
			
		||||
			stdr.r_dycode = DC_DOM;
 | 
			
		||||
			stdr.r_dayofmonth = 31;
 | 
			
		||||
			stdr.r_tod = SECSPERDAY + stdrp->r_stdoff;
 | 
			
		||||
			stdr.r_todisstd = stdr.r_todisgmt = false;
 | 
			
		||||
			stdr.r_tod = SECSPERDAY + stdrp->r_save;
 | 
			
		||||
			stdr.r_todisstd = stdr.r_todisut = false;
 | 
			
		||||
			stdr.r_isdst = false;
 | 
			
		||||
			stdr.r_stdoff = 0;
 | 
			
		||||
			stdr.r_save = 0;
 | 
			
		||||
			stdr.r_abbrvar
 | 
			
		||||
				= (stdabbrrp ? stdabbrrp->r_abbrvar : "");
 | 
			
		||||
			dstrp = &dstr;
 | 
			
		||||
@@ -2850,7 +2873,7 @@ stringzone(char *result, struct zone const *zpfirst, ptrdiff_t zonecount)
 | 
			
		||||
		return -1;
 | 
			
		||||
	abbrvar = (stdrp == NULL) ? "" : stdrp->r_abbrvar;
 | 
			
		||||
	len = doabbr(result, zp, abbrvar, false, 0, true);
 | 
			
		||||
	offsetlen = stringoffset(result + len, -zp->z_gmtoff);
 | 
			
		||||
	offsetlen = stringoffset(result + len, -zp->z_stdoff);
 | 
			
		||||
	if (!offsetlen)
 | 
			
		||||
	{
 | 
			
		||||
		result[0] = '\0';
 | 
			
		||||
@@ -2860,11 +2883,11 @@ stringzone(char *result, struct zone const *zpfirst, ptrdiff_t zonecount)
 | 
			
		||||
	if (dstrp == NULL)
 | 
			
		||||
		return compat;
 | 
			
		||||
	len += doabbr(result + len, zp, dstrp->r_abbrvar,
 | 
			
		||||
				  dstrp->r_isdst, dstrp->r_stdoff, true);
 | 
			
		||||
	if (dstrp->r_stdoff != SECSPERMIN * MINSPERHOUR)
 | 
			
		||||
				  dstrp->r_isdst, dstrp->r_save, true);
 | 
			
		||||
	if (dstrp->r_save != SECSPERMIN * MINSPERHOUR)
 | 
			
		||||
	{
 | 
			
		||||
		offsetlen = stringoffset(result + len,
 | 
			
		||||
								 -(zp->z_gmtoff + dstrp->r_stdoff));
 | 
			
		||||
								 -(zp->z_stdoff + dstrp->r_save));
 | 
			
		||||
		if (!offsetlen)
 | 
			
		||||
		{
 | 
			
		||||
			result[0] = '\0';
 | 
			
		||||
@@ -2873,7 +2896,7 @@ stringzone(char *result, struct zone const *zpfirst, ptrdiff_t zonecount)
 | 
			
		||||
		len += offsetlen;
 | 
			
		||||
	}
 | 
			
		||||
	result[len++] = ',';
 | 
			
		||||
	c = stringrule(result + len, dstrp, dstrp->r_stdoff, zp->z_gmtoff);
 | 
			
		||||
	c = stringrule(result + len, dstrp, dstrp->r_save, zp->z_stdoff);
 | 
			
		||||
	if (c < 0)
 | 
			
		||||
	{
 | 
			
		||||
		result[0] = '\0';
 | 
			
		||||
@@ -2883,7 +2906,7 @@ stringzone(char *result, struct zone const *zpfirst, ptrdiff_t zonecount)
 | 
			
		||||
		compat = c;
 | 
			
		||||
	len += strlen(result + len);
 | 
			
		||||
	result[len++] = ',';
 | 
			
		||||
	c = stringrule(result + len, stdrp, dstrp->r_stdoff, zp->z_gmtoff);
 | 
			
		||||
	c = stringrule(result + len, stdrp, dstrp->r_save, zp->z_stdoff);
 | 
			
		||||
	if (c < 0)
 | 
			
		||||
	{
 | 
			
		||||
		result[0] = '\0';
 | 
			
		||||
@@ -2905,12 +2928,12 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
 | 
			
		||||
				useuntil;
 | 
			
		||||
	zic_t		starttime,
 | 
			
		||||
				untiltime;
 | 
			
		||||
	zic_t		gmtoff;
 | 
			
		||||
	zic_t		stdoff;
 | 
			
		||||
	zic_t		save;
 | 
			
		||||
	zic_t		year;
 | 
			
		||||
	zic_t		startoff;
 | 
			
		||||
	bool		startttisstd;
 | 
			
		||||
	bool		startttisgmt;
 | 
			
		||||
	bool		startttisut;
 | 
			
		||||
	int			type;
 | 
			
		||||
	char	   *startbuf;
 | 
			
		||||
	char	   *ab;
 | 
			
		||||
@@ -2948,7 +2971,7 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
 | 
			
		||||
	 * startttisstd.
 | 
			
		||||
	 */
 | 
			
		||||
	startttisstd = false;
 | 
			
		||||
	startttisgmt = false;
 | 
			
		||||
	startttisut = false;
 | 
			
		||||
	min_year = max_year = EPOCH_YEAR;
 | 
			
		||||
	if (leapseen)
 | 
			
		||||
	{
 | 
			
		||||
@@ -2977,14 +3000,14 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
 | 
			
		||||
	 */
 | 
			
		||||
	compat = stringzone(envvar, zpfirst, zonecount);
 | 
			
		||||
	version = compat < 2013 ? ZIC_VERSION_PRE_2013 : ZIC_VERSION;
 | 
			
		||||
	do_extend = compat < 0 || compat == YEAR_BY_YEAR_ZONE;
 | 
			
		||||
	do_extend = compat < 0;
 | 
			
		||||
	if (noise)
 | 
			
		||||
	{
 | 
			
		||||
		if (!*envvar)
 | 
			
		||||
			warning("%s %s",
 | 
			
		||||
					_("no POSIX environment variable for zone"),
 | 
			
		||||
					zpfirst->z_name);
 | 
			
		||||
		else if (compat != 0 && compat != YEAR_BY_YEAR_ZONE)
 | 
			
		||||
		else if (compat != 0)
 | 
			
		||||
		{
 | 
			
		||||
			/*
 | 
			
		||||
			 * Circa-COMPAT clients, and earlier clients, might not work for
 | 
			
		||||
@@ -3033,37 +3056,43 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
 | 
			
		||||
			max_year = min_year + years_of_observations;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * For the benefit of older systems, generate data from 1900 through 2038.
 | 
			
		||||
	 */
 | 
			
		||||
	if (min_year > 1900)
 | 
			
		||||
		min_year = 1900;
 | 
			
		||||
	max_year0 = max_year;
 | 
			
		||||
	if (max_year < 2038)
 | 
			
		||||
		max_year = 2038;
 | 
			
		||||
	if (want_bloat())
 | 
			
		||||
	{
 | 
			
		||||
		/*
 | 
			
		||||
		 * For the benefit of older systems, generate data from 1900 through
 | 
			
		||||
		 * 2038.
 | 
			
		||||
		 */
 | 
			
		||||
		if (min_year > 1900)
 | 
			
		||||
			min_year = 1900;
 | 
			
		||||
		if (max_year < 2038)
 | 
			
		||||
			max_year = 2038;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < zonecount; ++i)
 | 
			
		||||
	{
 | 
			
		||||
		struct rule *prevrp = NULL;
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
		 * A guess that may well be corrected later.
 | 
			
		||||
		 */
 | 
			
		||||
		stdoff = 0;
 | 
			
		||||
		save = 0;
 | 
			
		||||
		zp = &zpfirst[i];
 | 
			
		||||
		usestart = i > 0 && (zp - 1)->z_untiltime > min_time;
 | 
			
		||||
		useuntil = i < (zonecount - 1);
 | 
			
		||||
		if (useuntil && zp->z_untiltime <= min_time)
 | 
			
		||||
			continue;
 | 
			
		||||
		gmtoff = zp->z_gmtoff;
 | 
			
		||||
		stdoff = zp->z_stdoff;
 | 
			
		||||
		eat(zp->z_filename, zp->z_linenum);
 | 
			
		||||
		*startbuf = '\0';
 | 
			
		||||
		startoff = zp->z_gmtoff;
 | 
			
		||||
		startoff = zp->z_stdoff;
 | 
			
		||||
		if (zp->z_nrules == 0)
 | 
			
		||||
		{
 | 
			
		||||
			stdoff = zp->z_stdoff;
 | 
			
		||||
			doabbr(startbuf, zp, NULL, zp->z_isdst, stdoff, false);
 | 
			
		||||
			type = addtype(oadd(zp->z_gmtoff, stdoff),
 | 
			
		||||
			save = zp->z_save;
 | 
			
		||||
			doabbr(startbuf, zp, NULL, zp->z_isdst, save, false);
 | 
			
		||||
			type = addtype(oadd(zp->z_stdoff, save),
 | 
			
		||||
						   startbuf, zp->z_isdst, startttisstd,
 | 
			
		||||
						   startttisgmt);
 | 
			
		||||
						   startttisut);
 | 
			
		||||
			if (usestart)
 | 
			
		||||
			{
 | 
			
		||||
				addtt(starttime, type);
 | 
			
		||||
@@ -3109,16 +3138,16 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
 | 
			
		||||
					if (useuntil)
 | 
			
		||||
					{
 | 
			
		||||
						/*
 | 
			
		||||
						 * Turn untiltime into UT assuming the current gmtoff
 | 
			
		||||
						 * and stdoff values.
 | 
			
		||||
						 * Turn untiltime into UT assuming the current stdoff
 | 
			
		||||
						 * and save values.
 | 
			
		||||
						 */
 | 
			
		||||
						untiltime = zp->z_untiltime;
 | 
			
		||||
						if (!zp->z_untilrule.r_todisgmt)
 | 
			
		||||
							untiltime = tadd(untiltime,
 | 
			
		||||
											 -gmtoff);
 | 
			
		||||
						if (!zp->z_untilrule.r_todisstd)
 | 
			
		||||
						if (!zp->z_untilrule.r_todisut)
 | 
			
		||||
							untiltime = tadd(untiltime,
 | 
			
		||||
											 -stdoff);
 | 
			
		||||
						if (!zp->z_untilrule.r_todisstd)
 | 
			
		||||
							untiltime = tadd(untiltime,
 | 
			
		||||
											 -save);
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					/*
 | 
			
		||||
@@ -3133,9 +3162,9 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
 | 
			
		||||
							continue;
 | 
			
		||||
						eats(zp->z_filename, zp->z_linenum,
 | 
			
		||||
							 rp->r_filename, rp->r_linenum);
 | 
			
		||||
						offset = rp->r_todisgmt ? 0 : gmtoff;
 | 
			
		||||
						offset = rp->r_todisut ? 0 : stdoff;
 | 
			
		||||
						if (!rp->r_todisstd)
 | 
			
		||||
							offset = oadd(offset, stdoff);
 | 
			
		||||
							offset = oadd(offset, save);
 | 
			
		||||
						jtime = rp->r_temp;
 | 
			
		||||
						if (jtime == min_time ||
 | 
			
		||||
							jtime == max_time)
 | 
			
		||||
@@ -3166,41 +3195,46 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
 | 
			
		||||
					rp->r_todo = false;
 | 
			
		||||
					if (useuntil && ktime >= untiltime)
 | 
			
		||||
						break;
 | 
			
		||||
					stdoff = rp->r_stdoff;
 | 
			
		||||
					save = rp->r_save;
 | 
			
		||||
					if (usestart && ktime == starttime)
 | 
			
		||||
						usestart = false;
 | 
			
		||||
					if (usestart)
 | 
			
		||||
					{
 | 
			
		||||
						if (ktime < starttime)
 | 
			
		||||
						{
 | 
			
		||||
							startoff = oadd(zp->z_gmtoff,
 | 
			
		||||
											stdoff);
 | 
			
		||||
							startoff = oadd(zp->z_stdoff,
 | 
			
		||||
											save);
 | 
			
		||||
							doabbr(startbuf, zp,
 | 
			
		||||
								   rp->r_abbrvar,
 | 
			
		||||
								   rp->r_isdst,
 | 
			
		||||
								   rp->r_stdoff,
 | 
			
		||||
								   rp->r_save,
 | 
			
		||||
								   false);
 | 
			
		||||
							continue;
 | 
			
		||||
						}
 | 
			
		||||
						if (*startbuf == '\0' &&
 | 
			
		||||
							startoff == oadd(zp->z_gmtoff,
 | 
			
		||||
											 stdoff))
 | 
			
		||||
						if (*startbuf == '\0'
 | 
			
		||||
							&& startoff == oadd(zp->z_stdoff,
 | 
			
		||||
												save))
 | 
			
		||||
						{
 | 
			
		||||
							doabbr(startbuf,
 | 
			
		||||
								   zp,
 | 
			
		||||
								   rp->r_abbrvar,
 | 
			
		||||
								   rp->r_isdst,
 | 
			
		||||
								   rp->r_stdoff,
 | 
			
		||||
								   rp->r_save,
 | 
			
		||||
								   false);
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
					eats(zp->z_filename, zp->z_linenum,
 | 
			
		||||
						 rp->r_filename, rp->r_linenum);
 | 
			
		||||
					doabbr(ab, zp, rp->r_abbrvar,
 | 
			
		||||
						   rp->r_isdst, rp->r_stdoff, false);
 | 
			
		||||
					offset = oadd(zp->z_gmtoff, rp->r_stdoff);
 | 
			
		||||
						   rp->r_isdst, rp->r_save, false);
 | 
			
		||||
					offset = oadd(zp->z_stdoff, rp->r_save);
 | 
			
		||||
					if (!want_bloat() && !useuntil && !do_extend
 | 
			
		||||
						&& prevrp
 | 
			
		||||
						&& rp->r_hiyear == ZIC_MAX
 | 
			
		||||
						&& prevrp->r_hiyear == ZIC_MAX)
 | 
			
		||||
						break;
 | 
			
		||||
					type = addtype(offset, ab, rp->r_isdst,
 | 
			
		||||
								   rp->r_todisstd, rp->r_todisgmt);
 | 
			
		||||
								   rp->r_todisstd, rp->r_todisut);
 | 
			
		||||
					if (defaulttype < 0 && !rp->r_isdst)
 | 
			
		||||
						defaulttype = type;
 | 
			
		||||
					if (rp->r_hiyear == ZIC_MAX
 | 
			
		||||
@@ -3208,6 +3242,7 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
 | 
			
		||||
							 && ktime < attypes[lastatmax].at))
 | 
			
		||||
						lastatmax = timecnt;
 | 
			
		||||
					addtt(ktime, type);
 | 
			
		||||
					prevrp = rp;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		if (usestart)
 | 
			
		||||
@@ -3222,10 +3257,10 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
 | 
			
		||||
				error(_("cannot determine time zone abbreviation to use just after until time"));
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				bool		isdst = startoff != zp->z_gmtoff;
 | 
			
		||||
				bool		isdst = startoff != zp->z_stdoff;
 | 
			
		||||
 | 
			
		||||
				type = addtype(startoff, startbuf, isdst,
 | 
			
		||||
							   startttisstd, startttisgmt);
 | 
			
		||||
							   startttisstd, startttisut);
 | 
			
		||||
				if (defaulttype < 0 && !isdst)
 | 
			
		||||
					defaulttype = type;
 | 
			
		||||
				addtt(starttime, type);
 | 
			
		||||
@@ -3238,12 +3273,12 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
 | 
			
		||||
		if (useuntil)
 | 
			
		||||
		{
 | 
			
		||||
			startttisstd = zp->z_untilrule.r_todisstd;
 | 
			
		||||
			startttisgmt = zp->z_untilrule.r_todisgmt;
 | 
			
		||||
			startttisut = zp->z_untilrule.r_todisut;
 | 
			
		||||
			starttime = zp->z_untiltime;
 | 
			
		||||
			if (!startttisstd)
 | 
			
		||||
				starttime = tadd(starttime, -save);
 | 
			
		||||
			if (!startttisut)
 | 
			
		||||
				starttime = tadd(starttime, -stdoff);
 | 
			
		||||
			if (!startttisgmt)
 | 
			
		||||
				starttime = tadd(starttime, -gmtoff);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if (defaulttype < 0)
 | 
			
		||||
@@ -3295,22 +3330,31 @@ addtt(zic_t starttime, int type)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
addtype(zic_t gmtoff, char const *abbr, bool isdst, bool ttisstd, bool ttisgmt)
 | 
			
		||||
addtype(zic_t utoff, char const *abbr, bool isdst, bool ttisstd, bool ttisut)
 | 
			
		||||
{
 | 
			
		||||
	int			i,
 | 
			
		||||
				j;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * See if there's already an entry for this zone type. If so, just return
 | 
			
		||||
	 * its index.
 | 
			
		||||
	 */
 | 
			
		||||
	for (i = 0; i < typecnt; ++i)
 | 
			
		||||
	if (!(-1L - 2147483647L <= utoff && utoff <= 2147483647L))
 | 
			
		||||
	{
 | 
			
		||||
		if (gmtoff == gmtoffs[i] && isdst == isdsts[i] &&
 | 
			
		||||
			strcmp(abbr, &chars[abbrinds[i]]) == 0 &&
 | 
			
		||||
			ttisstd == ttisstds[i] &&
 | 
			
		||||
			ttisgmt == ttisgmts[i])
 | 
			
		||||
			return i;
 | 
			
		||||
		error(_("UT offset out of range"));
 | 
			
		||||
		exit(EXIT_FAILURE);
 | 
			
		||||
	}
 | 
			
		||||
	if (!want_bloat())
 | 
			
		||||
		ttisstd = ttisut = false;
 | 
			
		||||
 | 
			
		||||
	for (j = 0; j < charcnt; ++j)
 | 
			
		||||
		if (strcmp(&chars[j], abbr) == 0)
 | 
			
		||||
			break;
 | 
			
		||||
	if (j == charcnt)
 | 
			
		||||
		newabbr(abbr);
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		/* If there's already an entry, return its index.  */
 | 
			
		||||
		for (i = 0; i < typecnt; i++)
 | 
			
		||||
			if (utoff == utoffs[i] && isdst == isdsts[i] && j == desigidx[i]
 | 
			
		||||
				&& ttisstd == ttisstds[i] && ttisut == ttisuts[i])
 | 
			
		||||
				return i;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
@@ -3321,23 +3365,12 @@ addtype(zic_t gmtoff, char const *abbr, bool isdst, bool ttisstd, bool ttisgmt)
 | 
			
		||||
		error(_("too many local time types"));
 | 
			
		||||
		exit(EXIT_FAILURE);
 | 
			
		||||
	}
 | 
			
		||||
	if (!(-1L - 2147483647L <= gmtoff && gmtoff <= 2147483647L))
 | 
			
		||||
	{
 | 
			
		||||
		error(_("UT offset out of range"));
 | 
			
		||||
		exit(EXIT_FAILURE);
 | 
			
		||||
	}
 | 
			
		||||
	gmtoffs[i] = gmtoff;
 | 
			
		||||
	i = typecnt++;
 | 
			
		||||
	utoffs[i] = utoff;
 | 
			
		||||
	isdsts[i] = isdst;
 | 
			
		||||
	ttisstds[i] = ttisstd;
 | 
			
		||||
	ttisgmts[i] = ttisgmt;
 | 
			
		||||
 | 
			
		||||
	for (j = 0; j < charcnt; ++j)
 | 
			
		||||
		if (strcmp(&chars[j], abbr) == 0)
 | 
			
		||||
			break;
 | 
			
		||||
	if (j == charcnt)
 | 
			
		||||
		newabbr(abbr);
 | 
			
		||||
	abbrinds[i] = j;
 | 
			
		||||
	++typecnt;
 | 
			
		||||
	ttisuts[i] = ttisut;
 | 
			
		||||
	desigidx[i] = j;
 | 
			
		||||
	return i;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -3671,9 +3704,9 @@ byword(const char *word, const struct lookup *table)
 | 
			
		||||
				return NULL;	/* multiple inexact matches */
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	/* Warn about any backward-compatibility issue with pre-2017c zic.  */
 | 
			
		||||
	if (foundlp)
 | 
			
		||||
	if (foundlp && noise)
 | 
			
		||||
	{
 | 
			
		||||
		/* Warn about any backward-compatibility issue with pre-2017c zic.  */
 | 
			
		||||
		bool		pre_2017c_match = false;
 | 
			
		||||
 | 
			
		||||
		for (lp = table; lp->l_word; lp++)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user