@ -1,3 +1,5 @@
/* Compile .zi time zone data into TZif binary files. */
/*
* This file is in the public domain , so clarified as of
* 2006 - 07 - 17 by Arthur David Olson .
@ -130,8 +132,7 @@ static void adjleap(void);
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 ,
bool ) ;
static zic_t gethms ( const char * string , const char * errstring ) ;
static zic_t getstdoff ( char * , bool * ) ;
static void infile ( const char * filename ) ;
static void inleap ( char * * fields , int nfields ) ;
@ -162,7 +163,7 @@ enum
PERCENT_Z_LEN_BOUND = sizeof " +995959 " - 1 } ;
/* If true, work around a bug in Qt 5.6.1 and earlier, which mishandles
tz binary files whose POSIX - TZ - style strings contain ' < ' ; see
TZif files whose POSIX - TZ - style strings contain ' < ' ; see
QTBUG - 53071 < https : //bugreports.qt.io/browse/QTBUG-53071>. This
workaround will no longer be needed when Qt 5.6 .1 and earlier are
obsolete , say in the year 2021. */
@ -211,7 +212,7 @@ static int typecnt;
# define ZF_RULE 3
# define ZF_FORMAT 4
# define ZF_TILYEAR 5
# define ZF_TILMONTH 6
# define ZF_TILMONTH 6
# define ZF_TILDAY 7
# define ZF_TILTIME 8
# define ZONE_MINFIELDS 5
@ -224,12 +225,12 @@ static int typecnt;
# define ZFC_GMTOFF 0
# define ZFC_RULE 1
# define ZFC_FORMAT 2
# define ZFC_TILYEAR 3
# define ZFC_TILYEAR 3
# define ZFC_TILMONTH 4
# define ZFC_TILDAY 5
# define ZFC_TILTIME 6
# define ZONEC_MINFIELDS 3
# define ZONEC_MAXFIELDS 7
# define ZFC_TILTIME 6
# define ZONEC_MINFIELDS 3
# define ZONEC_MAXFIELDS 7
/*
* Which files are which on a Rule line .
@ -244,7 +245,7 @@ static int typecnt;
# define RF_TOD 7
# define RF_STDOFF 8
# define RF_ABBRVAR 9
# define RULE_FIELDS 10
# define RULE_FIELDS 10
/*
* Which fields are which on a Link line .
@ -252,7 +253,7 @@ static int typecnt;
# define LF_FROM 1
# define LF_TO 2
# define LINK_FIELDS 3
# define LINK_FIELDS 3
/*
* Which fields are which on a Leap line .
@ -264,7 +265,7 @@ static int typecnt;
# define LP_TIME 4
# define LP_CORR 5
# define LP_ROLL 6
# define LEAP_FIELDS 7
# define LEAP_FIELDS 7
/*
* Year synonyms .
@ -998,48 +999,6 @@ dolink(char const *fromfield, char const *tofield, bool staysymlink)
static zic_t const min_time = MINVAL ( zic_t , TIME_T_BITS_IN_FILE ) ;
static zic_t const max_time = MAXVAL ( zic_t , TIME_T_BITS_IN_FILE ) ;
/*
* Estimated time of the Big Bang , in seconds since the POSIX epoch .
* rounded downward to the negation of a power of two that is
* comfortably outside the error bounds .
*
* For the time of the Big Bang , see :
*
* Ade PAR , Aghanim N , Armitage - Caplan C et al . Planck 2013 results .
* I . Overview of products and scientific results .
* arXiv : 1303.5062 2013 - 03 - 20 20 : 10 : 01 UTC
* < https : //arxiv.org/pdf/1303.5062v1> [PDF]
*
* Page 36 , Table 9 , row Age / Gyr , column Planck + WP + highL + BAO 68 % limits
* gives the value 13.798 plus - or - minus 0.037 billion years .
* Multiplying this by 1000000000 and then by 31557600 ( the number of
* seconds in an astronomical year ) gives a value that is comfortably
* less than 2 * * 59 , so BIG_BANG is - 2 * * 59.
*
* BIG_BANG is approximate , and may change in future versions .
* Please do not rely on its exact value .
*/
# ifndef BIG_BANG
# define BIG_BANG (- (((zic_t) 1) << 59))
# endif
/* If true, work around GNOME bug 730332
< https : //bugzilla.gnome.org/show_bug.cgi?id=730332>
by refusing to output time stamps before BIG_BANG .
Such time stamps are physically suspect anyway .
The GNOME bug is scheduled to be fixed in GNOME 3.22 , and if so
this workaround will no longer be needed when GNOME 3.21 and
earlier are obsolete , say in the year 2021. */
enum
{
WORK_AROUND_GNOME_BUG_730332 = true } ;
static const zic_t early_time = ( WORK_AROUND_GNOME_BUG_730332
? BIG_BANG
: MINVAL ( zic_t , TIME_T_BITS_IN_FILE ) ) ;
/* Return true if NAME is a directory. */
static bool
itsdir ( char const * name )
@ -1281,8 +1240,9 @@ infile(const char *name)
* A null string maps to zero .
* Call error with errstring and return zero on errors .
*/
static zic_t
gethms ( char const * string , char const * errstring , bool signable )
gethms ( char const * string , char const * errstring )
{
/* PG: make hh be int not zic_t to avoid sscanf portability issues */
int hh ;
@ -1299,9 +1259,7 @@ gethms(char const *string, char const *errstring, bool signable)
if ( string = = NULL | | * string = = ' \0 ' )
return 0 ;
if ( ! signable )
sign = 1 ;
else if ( * string = = ' - ' )
if ( * string = = ' - ' )
{
sign = - 1 ;
+ + string ;
@ -1384,7 +1342,7 @@ getstdoff(char *field, bool *isdst)
break ;
}
}
stdoff = gethms ( field , _ ( " invalid saved time " ) , true ) ;
stdoff = gethms ( field , _ ( " invalid saved time " ) ) ;
* isdst = dst < 0 ? stdoff ! = 0 : dst ;
return stdoff ;
}
@ -1399,10 +1357,29 @@ inrule(char **fields, int nfields)
error ( _ ( " wrong number of fields on Rule line " ) ) ;
return ;
}
if ( * fields [ RF_NAME ] = = ' \0 ' )
switch ( * fields [ RF_NAME ] )
{
error ( _ ( " nameless rule " ) ) ;
return ;
case ' \0 ' :
case ' ' :
case ' \f ' :
case ' \n ' :
case ' \r ' :
case ' \t ' :
case ' \v ' :
case ' + ' :
case ' - ' :
case ' 0 ' :
case ' 1 ' :
case ' 2 ' :
case ' 3 ' :
case ' 4 ' :
case ' 5 ' :
case ' 6 ' :
case ' 7 ' :
case ' 8 ' :
case ' 9 ' :
error ( _ ( " Invalid rule name \" %s \" " ) , fields [ RF_NAME ] ) ;
return ;
}
r . r_filename = filename ;
r . r_linenum = linenum ;
@ -1507,7 +1484,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 " ) , true ) ;
z . z_gmtoff = gethms ( fields [ i_gmtoff ] , _ ( " invalid UT offset " ) ) ;
if ( ( cp = strchr ( fields [ i_format ] , ' % ' ) ) ! = NULL )
{
if ( ( * + + cp ! = ' s ' & & * cp ! = ' z ' ) | | strchr ( cp , ' % ' )
@ -1649,7 +1626,7 @@ inleap(char **fields, int nfields)
return ;
}
t = dayoff * SECSPERDAY ;
tod = gethms ( fields [ LP_TIME ] , _ ( " invalid time of day " ) , false ) ;
tod = gethms ( fields [ LP_TIME ] , _ ( " invalid time of day " ) ) ;
cp = fields [ LP_CORR ] ;
{
bool positive ;
@ -1757,7 +1734,7 @@ rulesub(struct rule *rp, const char *loyearp, const char *hiyearp,
break ;
}
}
rp - > r_tod = gethms ( dp , _ ( " invalid time of day " ) , false ) ;
rp - > r_tod = gethms ( dp , _ ( " invalid time of day " ) ) ;
free ( dp ) ;
/*
@ -1942,7 +1919,43 @@ is32(const zic_t x)
}
static void
writezone ( const char * const name , const char * const string , char version )
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 ;
}
}
static void
writezone ( const char * const name , const char * const string , char version ,
int defaulttype )
{
FILE * fp ;
ptrdiff_t i ,
@ -1977,14 +1990,12 @@ writezone(const char *const name, const char *const string, char version)
toi = 0 ;
fromi = 0 ;
while ( fromi < timecnt & & attypes [ fromi ] . at < early_time )
+ + fromi ;
for ( ; fromi < timecnt ; + + fromi )
{
if ( toi > 1 & & ( ( attypes [ fromi ] . at +
gmtoffs [ attypes [ toi - 1 ] . type ] ) < =
( attypes [ toi - 1 ] . at +
gmtoffs [ attypes [ toi - 2 ] . type ] ) ) )
if ( toi ! = 0 & & ( ( attypes [ fromi ] . at +
gmtoffs [ attypes [ toi - 1 ] . type ] ) < =
( attypes [ toi - 1 ] . at + gmtoffs [ toi = = 1 ? 0
: attypes [ toi - 2 ] . type ] ) ) )
{
attypes [ toi - 1 ] . type =
attypes [ fromi ] . type ;
@ -2019,8 +2030,8 @@ writezone(const char *const name, const char *const string, char version)
}
/*
* Work around QTBUG - 53071 for time stamps less than y2038_boundary - 1 ,
* by inserting a no - op transition at time y2038_boundary - 1. This works
* Work around QTBUG - 53071 for timestamps less than y2038_boundary - 1 , by
* inserting a no - op transition at time y2038_boundary - 1. This works
* only for timestamps before the boundary , which should be good enough in
* practice as QTBUG - 53071 should be long - dead by 2038.
*/
@ -2116,7 +2127,8 @@ writezone(const char *const name, const char *const string, char version)
int thisleapi ,
thisleapcnt ,
thisleaplim ;
int writetype [ TZ_MAX_TYPES ] ;
int old0 ;
char omittype [ TZ_MAX_TYPES ] ;
int typemap [ TZ_MAX_TYPES ] ;
int thistypecnt ;
char thischars [ TZ_MAX_CHARS ] ;
@ -2144,28 +2156,19 @@ writezone(const char *const name, const char *const string, char version)
error ( _ ( " too many transition times " ) ) ;
thistimelim = thistimei + thistimecnt ;
thisleaplim = thisleapi + thisleapcnt ;
for ( i = 0 ; i < typecnt ; + + i )
writetype [ i ] = thistimecnt = = timecnt ;
if ( thistimecnt = = 0 )
{
/*
* No transition times fall in the current ( 32 - or 64 - bit ) window .
*/
if ( typecnt ! = 0 )
writetype [ typecnt - 1 ] = true ;
}
else
{
for ( i = thistimei - 1 ; i < thistimelim ; + + i )
if ( i > = 0 )
writetype [ types [ i ] ] = true ;
memset ( omittype , true , typecnt ) ;
omittype [ defaulttype ] = false ;
for ( i = thistimei ; i < thistimelim ; i + + )
omittype [ types [ i ] ] = false ;
/*
* Reorder types to make DEFAULTTYPE type 0. Use TYPEMAP to swap OLD0
* and DEFAULTTYPE so that DEFAULTTYPE appears as type 0 in the output
* instead of OLD0 . TYPEMAP also omits unused types .
*/
old0 = strlen ( omittype ) ;
swaptypes ( old0 , defaulttype ) ;
/*
* For America / Godthab and Antarctica / Palmer
*/
if ( thistimei = = 0 )
writetype [ 0 ] = true ;
}
# ifndef LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH
/*
@ -2187,8 +2190,8 @@ writezone(const char *const name, const char *const string, char version)
mrudst = types [ i ] ;
else
mrustd = types [ i ] ;
for ( i = 0 ; i < typecnt ; + + i )
if ( write type[ i ] )
for ( i = old 0; i < typecnt ; i + + )
if ( ! omit type[ i ] )
{
if ( isdsts [ i ] )
hidst = i ;
@ -2205,7 +2208,7 @@ writezone(const char *const name, const char *const string, char version)
ttisstds [ mrudst ] ,
ttisgmts [ mrudst ] ) ;
isdsts [ mrudst ] = 1 ;
write type[ type ] = tru e;
omit type[ type ] = fals e;
}
if ( histd > = 0 & & mrustd > = 0 & & histd ! = mrustd & &
gmtoffs [ histd ] ! = gmtoffs [ mrustd ] )
@ -2217,22 +2220,26 @@ writezone(const char *const name, const char *const string, char version)
ttisstds [ mrustd ] ,
ttisgmts [ mrustd ] ) ;
isdsts [ mrustd ] = 0 ;
write type[ type ] = tru e;
omit type[ type ] = fals e;
}
}
# endif / * !defined
* LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH */
thistypecnt = 0 ;
for ( i = 0 ; i < typecnt ; + + i )
typemap [ i ] = writetype [ i ] ? thistypecnt + + : - 1 ;
for ( i = old0 ; i < typecnt ; i + + )
if ( ! omittype [ i ] )
typemap [ i = = old0 ? defaulttype
: i = = defaulttype ? old0 : i ]
= thistypecnt + + ;
for ( i = 0 ; i < sizeof indmap / sizeof indmap [ 0 ] ; + + i )
indmap [ i ] = - 1 ;
thischarcnt = 0 ;
for ( i = 0 ; i < typecnt ; + + i )
for ( i = old 0; i < typecnt ; i + + )
{
char * thisabbr ;
if ( ! write type[ i ] )
if ( omit type[ i ] )
continue ;
if ( indmap [ abbrinds [ i ] ] > = 0 )
continue ;
@ -2267,23 +2274,16 @@ writezone(const char *const name, const char *const string, char version)
DO ( tzh_typecnt ) ;
DO ( tzh_charcnt ) ;
# undef DO
for ( i = thistimei ; i < thistimelim ; + + i )
if ( pass = = 1 )
/*
* Output an INT32_MIN " transition " if appropriate ; see above .
*/
puttzcode ( ( ( ats [ i ] < PG_INT32_MIN ) ?
PG_INT32_MIN : ats [ i ] ) , fp ) ;
else
/* PG: print current timezone abbreviations if requested */
if ( print_abbrevs & & pass = = 2 )
{
/* Print "type" data for periods ending after print_cutoff */
for ( i = thistimei ; i < thistimelim ; + + i )
{
puttzcode64 ( ats [ i ] , fp ) ;
/* Print current timezone abbreviations if requested */
if ( print_abbrevs & &
( i = = thistimelim - 1 | | ats [ i + 1 ] > print_cutoff ) )
if ( i = = thistimelim - 1 | | ats [ i + 1 ] > print_cutoff )
{
unsigned char tm = typemap [ type s [ i ] ] ;
unsigned char tm = types [ i ] ;
char * thisabbrev = & thischars [ indmap [ abbrinds [ tm ] ] ] ;
/* filter out assorted junk entries */
@ -2295,6 +2295,32 @@ writezone(const char *const name, const char *const string, char version)
isdsts [ tm ] ? " \t D " : " " ) ;
}
}
/* Print the default type if we have no transitions at all */
if ( thistimei > = thistimelim )
{
unsigned char tm = defaulttype ;
char * thisabbrev = & thischars [ indmap [ abbrinds [ 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 ] ,
isdsts [ tm ] ? " \t D " : " " ) ;
}
}
for ( i = thistimei ; i < thistimelim ; + + i )
if ( pass = = 1 )
/*
* Output an INT32_MIN " transition " if appropriate ; see above .
*/
puttzcode ( ( ( ats [ i ] < PG_INT32_MIN ) ?
PG_INT32_MIN : ats [ i ] ) , fp ) ;
else
puttzcode64 ( ats [ i ] , fp ) ;
for ( i = thistimei ; i < thistimelim ; + + i )
{
unsigned char uc ;
@ -2302,8 +2328,8 @@ writezone(const char *const name, const char *const string, char version)
uc = typemap [ types [ i ] ] ;
fwrite ( & uc , sizeof uc , 1 , fp ) ;
}
for ( i = 0 ; i < typecnt ; + + i )
if ( write type[ i ] )
for ( i = old 0; i < typecnt ; i + + )
if ( ! omit type[ i ] )
{
puttzcode ( gmtoffs [ i ] , fp ) ;
putc ( isdsts [ i ] , fp ) ;
@ -2346,12 +2372,13 @@ writezone(const char *const name, const char *const string, char version)
puttzcode64 ( todo , fp ) ;
puttzcode ( corr [ i ] , fp ) ;
}
for ( i = 0 ; i < typecnt ; + + i )
if ( write type[ i ] )
for ( i = old 0; i < typecnt ; i + + )
if ( ! omit type[ i ] )
putc ( ttisstds [ i ] , fp ) ;
for ( i = 0 ; i < typecnt ; + + i )
if ( write type[ i ] )
for ( i = old 0; i < typecnt ; i + + )
if ( ! omit type[ i ] )
putc ( ttisgmts [ i ] , fp ) ;
swaptypes ( old0 , defaulttype ) ;
}
fprintf ( fp , " \n %s \n " , string ) ;
close_file ( fp , directory , name ) ;
@ -2757,6 +2784,7 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
zic_t one = 1 ;
zic_t y2038_boundary = one < < 31 ;
zic_t max_year0 ;
int defaulttype = - 1 ;
max_abbr_len = 2 + max_format_len + max_abbrvar_len ;
max_envvar_len = 2 * max_abbr_len + 5 * 9 ;
@ -2880,9 +2908,9 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
*/
stdoff = 0 ;
zp = & zpfirst [ i ] ;
usestart = i > 0 & & ( zp - 1 ) - > z_untiltime > early _time;
usestart = i > 0 & & ( zp - 1 ) - > z_untiltime > min _time;
useuntil = i < ( zonecount - 1 ) ;
if ( useuntil & & zp - > z_untiltime < = early _time)
if ( useuntil & & zp - > z_untiltime < = min _time)
continue ;
gmtoff = zp - > z_gmtoff ;
eat ( zp - > z_filename , zp - > z_linenum ) ;
@ -2901,7 +2929,7 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
usestart = false ;
}
else
addtt ( early_time , type ) ;
defaulttype = type ;
}
else
for ( year = min_year ; year < = max_year ; + + year )
@ -3032,6 +3060,8 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
offset = oadd ( zp - > z_gmtoff , rp - > r_stdoff ) ;
type = addtype ( offset , ab , rp - > r_isdst ,
rp - > r_todisstd , rp - > r_todisgmt ) ;
if ( defaulttype < 0 & & ! rp - > r_isdst )
defaulttype = type ;
if ( rp - > r_hiyear = = ZIC_MAX
& & ! ( 0 < = lastatmax
& & ktime < attypes [ lastatmax ] . at ) )
@ -3050,11 +3080,15 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
if ( * startbuf = = ' \0 ' )
error ( _ ( " cannot determine time zone abbreviation to use just after until time " ) ) ;
else
addtt ( starttime ,
addtype ( startoff , startbuf ,
startoff ! = zp - > z_gmtoff ,
startttisstd ,
startttisgmt ) ) ;
{
bool isdst = startoff ! = zp - > z_gmtoff ;
type = addtype ( startoff , startbuf , isdst ,
startttisstd , startttisgmt ) ;
if ( defaulttype < 0 & & ! isdst )
defaulttype = type ;
addtt ( starttime , type ) ;
}
}
/*
@ -3071,6 +3105,8 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
starttime = tadd ( starttime , - gmtoff ) ;
}
}
if ( defaulttype < 0 )
defaulttype = 0 ;
if ( 0 < = lastatmax )
attypes [ lastatmax ] . dontmerge = true ;
if ( do_extend )
@ -3100,7 +3136,7 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
attypes [ timecnt - 1 ] . dontmerge = true ;
}
}
writezone ( zpfirst - > z_name , envvar , version ) ;
writezone ( zpfirst - > z_name , envvar , version , defaulttype ) ;
free ( startbuf ) ;
free ( ab ) ;
free ( envvar ) ;
@ -3109,21 +3145,6 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
static void
addtt ( zic_t starttime , int type )
{
if ( starttime < = early_time
| | ( timecnt = = 1 & & attypes [ 0 ] . at < early_time ) )
{
gmtoffs [ 0 ] = gmtoffs [ type ] ;
isdsts [ 0 ] = isdsts [ type ] ;
ttisstds [ 0 ] = ttisstds [ type ] ;
ttisgmts [ 0 ] = ttisgmts [ type ] ;
if ( abbrinds [ type ] ! = 0 )
strcpy ( chars , & chars [ abbrinds [ type ] ] ) ;
abbrinds [ 0 ] = 0 ;
charcnt = strlen ( chars ) + 1 ;
typecnt = 1 ;
timecnt = 0 ;
type = 0 ;
}
attypes = growalloc ( attypes , sizeof * attypes , timecnt , & timecnt_alloc ) ;
attypes [ timecnt ] . at = starttime ;
attypes [ timecnt ] . dontmerge = false ;
@ -3361,7 +3382,7 @@ is_alpha(char a)
}
/* If A is an uppercase character in the C locale, return its lowercase
* counterpart . Otherwise , return A . */
counterpart . Otherwise , return A . */
static char
lowerit ( char a )
{
@ -3628,6 +3649,18 @@ rpytime(const struct rule *rp, zic_t wantedy)
dayoff = 0 ;
m = TM_JANUARY ;
y = EPOCH_YEAR ;
if ( y < wantedy )
{
wantedy - = y ;
dayoff = ( wantedy / YEARSPERREPEAT ) * ( SECSPERREPEAT / SECSPERDAY ) ;
wantedy % = YEARSPERREPEAT ;
wantedy + = y ;
}
else if ( wantedy < 0 )
{
dayoff = ( wantedy / YEARSPERREPEAT ) * ( SECSPERREPEAT / SECSPERDAY ) ;
wantedy % = YEARSPERREPEAT ;
}
while ( wantedy ! = y )
{
if ( wantedy > y )
@ -3706,7 +3739,6 @@ will not work with pre-2004 versions of zic"));
if ( dayoff > max_time / SECSPERDAY )
return max_time ;
t = ( zic_t ) dayoff * SECSPERDAY ;
return tadd ( t , rp - > r_tod ) ;
}