PostgreSQL Source Code  git master
zic.c File Reference
#include "postgres_fe.h"
#include <fcntl.h>
#include <sys/stat.h>
#include <time.h>
#include "pg_getopt.h"
#include "private.h"
#include "tzfile.h"
Include dependency graph for zic.c:

Go to the source code of this file.

Data Structures

struct  rule
 
struct  zone
 
struct  link
 
struct  lookup
 
struct  attype
 
struct  timerange
 

Macros

#define ZIC_VERSION_PRE_2013   '2'
 
#define ZIC_VERSION   '3'
 
#define ZIC_MIN   PG_INT64_MIN
 
#define ZIC_MAX   PG_INT64_MAX
 
#define ZIC_MAX_ABBR_LEN_WO_WARN   6
 
#define MKDIR_UMASK   0755
 
#define DC_DOM   0 /* 1..31 */ /* unused */
 
#define DC_DOWGEQ   1 /* 1..31 */ /* 0..6 (Sun..Sat) */
 
#define DC_DOWLEQ   2 /* 1..31 */ /* 0..6 (Sun..Sat) */
 
#define linkat(targetdir, target, linknamedir, linkname, flag)   (itssymlink(target) ? (errno = ENOTSUP, -1) : link(target, linkname))
 
#define LC_RULE   0
 
#define LC_ZONE   1
 
#define LC_LINK   2
 
#define LC_LEAP   3
 
#define LC_EXPIRES   4
 
#define ZF_NAME   1
 
#define ZF_STDOFF   2
 
#define ZF_RULE   3
 
#define ZF_FORMAT   4
 
#define ZF_TILYEAR   5
 
#define ZF_TILMONTH   6
 
#define ZF_TILDAY   7
 
#define ZF_TILTIME   8
 
#define ZONE_MINFIELDS   5
 
#define ZONE_MAXFIELDS   9
 
#define ZFC_STDOFF   0
 
#define ZFC_RULE   1
 
#define ZFC_FORMAT   2
 
#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 RF_NAME   1
 
#define RF_LOYEAR   2
 
#define RF_HIYEAR   3
 
#define RF_COMMAND   4
 
#define RF_MONTH   5
 
#define RF_DAY   6
 
#define RF_TOD   7
 
#define RF_SAVE   8
 
#define RF_ABBRVAR   9
 
#define RULE_FIELDS   10
 
#define LF_TARGET   1
 
#define LF_LINKNAME   2
 
#define LINK_FIELDS   3
 
#define LP_YEAR   1
 
#define LP_MONTH   2
 
#define LP_DAY   3
 
#define LP_TIME   4
 
#define LP_CORR   5
 
#define LP_ROLL   6
 
#define LEAP_FIELDS   7
 
#define EXPIRES_FIELDS   5
 
#define YR_MINIMUM   0
 
#define YR_MAXIMUM   1
 
#define YR_ONLY   2
 
#define TIME_T_BITS_IN_FILE   64
 
#define ZIC_BLOAT_DEFAULT   "slim"
 
#define DO(field)   fwrite(tzh.field, sizeof tzh.field, 1, fp)
 
#define LDAYSPERWEEK   ((zic_t) DAYSPERWEEK)
 

Typedefs

typedef int64 zic_t
 
typedef int lineno_t
 

Enumerations

enum  { PERCENT_Z_LEN_BOUND = sizeof "+995959" - 1 }
 
enum  { WORK_AROUND_QTBUG_53071 = true }
 

Functions

int link (const char *target, const char *linkname)
 
static void memory_exhausted (const char *msg) pg_attribute_noreturn()
 
static void verror (const char *string, va_list args) pg_attribute_printf(1
 
static void static void error (const char *string,...) pg_attribute_printf(1
 
static void static void static void warning (const char *string,...) pg_attribute_printf(1
 
static void static void static void static void usage (FILE *stream, int status) pg_attribute_noreturn()
 
static void addtt (zic_t starttime, int type)
 
static int addtype (zic_t, char const *, bool, bool, bool)
 
static void leapadd (zic_t, int, int)
 
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)
 
static zic_t getsave (char *, bool *)
 
static void inexpires (char **, int)
 
static void infile (const char *filename)
 
static void inleap (char **fields, int nfields)
 
static void inlink (char **fields, int nfields)
 
static void inrule (char **fields, int nfields)
 
static bool inzcont (char **fields, int nfields)
 
static bool inzone (char **fields, int nfields)
 
static bool inzsub (char **, int, bool)
 
static bool itsdir (char const *)
 
static bool itssymlink (char const *)
 
static bool is_alpha (char a)
 
static char lowerit (char)
 
static void mkdirs (char const *, bool)
 
static void newabbr (const char *abbr)
 
static zic_t oadd (zic_t t1, zic_t t2)
 
static void outzone (const struct zone *zp, ptrdiff_t ntzones)
 
static zic_t rpytime (const struct rule *rp, zic_t wantedy)
 
static void rulesub (struct rule *rp, const char *loyearp, const char *hiyearp, const char *typep, const char *monthp, const char *dayp, const char *timep)
 
static zic_t tadd (zic_t t1, zic_t t2)
 
static struct lookup const * byword (const char *string, const struct lookup *lp)
 
static size_t size_product (size_t nitems, size_t itemsize)
 
static void * memcheck (void *ptr)
 
static void * emalloc (size_t size)
 
static void * erealloc (void *ptr, size_t size)
 
static char * ecpyalloc (char const *str)
 
static void * growalloc (void *ptr, size_t itemsize, ptrdiff_t nitems, ptrdiff_t *nitems_alloc)
 
static void eats (char const *name, lineno_t num, char const *rname, lineno_t rnum)
 
static void eat (char const *name, lineno_t num)
 
static void close_file (FILE *stream, char const *dir, char const *name)
 
static void change_directory (char const *dir)
 
static bool timerange_option (char *timerange)
 
static bool want_bloat (void)
 
int main (int argc, char **argv)
 
static bool componentcheck (char const *name, char const *component, char const *component_end)
 
static bool namecheck (const char *name)
 
static int hardlinkerr (char const *target, char const *linkname)
 
static int rcomp (const void *cp1, const void *cp2)
 
static zic_t getleapdatetime (char **fields, int nfields, bool expire_line)
 
static void convert (const int32 val, char *const buf)
 
static void convert64 (const zic_t val, char *const buf)
 
static void puttzcode (const int32 val, FILE *const fp)
 
static void puttzcodepass (zic_t val, FILE *fp, int pass)
 
static int atcomp (const void *avp, const void *bvp)
 
static struct timerange limitrange (struct timerange r, zic_t lo, zic_t hi, zic_t const *ats, unsigned char const *types)
 
static void writezone (const char *const name, const char *const string, char version, int defaulttype)
 
static char const * abbroffset (char *buf, zic_t offset)
 
static size_t doabbr (char *abbr, struct zone const *zp, char const *letters, bool isdst, zic_t save, bool doquotes)
 
static void updateminmax (const zic_t x)
 
static int stringoffset (char *result, zic_t offset)
 
static int stringrule (char *result, struct rule *const rp, zic_t save, zic_t stdoff)
 
static int rule_cmp (struct rule const *a, struct rule const *b)
 
static int stringzone (char *result, struct zone const *zpfirst, ptrdiff_t zonecount)
 
static bool is_space (char a)
 
static bool ciequal (const char *ap, const char *bp)
 
static bool itsabbr (const char *abbr, const char *word)
 
static bool ciprefix (char const *abbr, char const *word)
 
static void time_overflow (void)
 

Variables

static ptrdiff_t const PTRDIFF_MAX = MAXVAL(ptrdiff_t, TYPE_BIT(ptrdiff_t))
 
static int charcnt
 
static bool errors
 
static bool warnings
 
static const char * filename
 
static int leapcnt
 
static bool leapseen
 
static zic_t leapminyear
 
static zic_t leapmaxyear
 
static lineno_t linenum
 
static int max_abbrvar_len = PERCENT_Z_LEN_BOUND
 
static int max_format_len
 
static zic_t max_year
 
static zic_t min_year
 
static bool noise
 
static bool print_abbrevs
 
static zic_t print_cutoff
 
static const char * rfilename
 
static lineno_t rlinenum
 
static const char * progname
 
static ptrdiff_t timecnt
 
static ptrdiff_t timecnt_alloc
 
static int typecnt
 
static struct rulerules
 
static ptrdiff_t nrules
 
static ptrdiff_t nrules_alloc
 
static struct zonezones
 
static ptrdiff_t nzones
 
static ptrdiff_t nzones_alloc
 
static struct linklinks
 
static ptrdiff_t nlinks
 
static ptrdiff_t nlinks_alloc
 
static struct lookup const zi_line_codes []
 
static struct lookup const leap_line_codes []
 
static struct lookup const mon_names []
 
static struct lookup const wday_names []
 
static struct lookup const lasts []
 
static struct lookup const begin_years []
 
static struct lookup const end_years []
 
static struct lookup const leap_types []
 
static const int len_months [2][MONSPERYEAR]
 
static const int len_years [2]
 
static struct attypeattypes
 
static zic_t utoffs [TZ_MAX_TYPES]
 
static char isdsts [TZ_MAX_TYPES]
 
static unsigned char desigidx [TZ_MAX_TYPES]
 
static bool ttisstds [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]
 
static char roll [TZ_MAX_LEAPS]
 
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)
 
static zic_t lo_time = MINVAL(zic_t, TIME_T_BITS_IN_FILE)
 
static zic_t hi_time = MAXVAL(zic_t, TIME_T_BITS_IN_FILE)
 
static zic_t leapexpires = -1
 
static zic_t comment_leapexpires = -1
 
static const char * psxrules
 
static const char * lcltime
 
static const char * directory
 
static const char * leapsec
 
static const char * tzdefault
 
static int bloat
 

Macro Definition Documentation

◆ DC_DOM

#define DC_DOM   0 /* 1..31 */ /* unused */

Definition at line 89 of file zic.c.

Referenced by outzone(), rulesub(), stringrule(), and stringzone().

◆ DC_DOWGEQ

#define DC_DOWGEQ   1 /* 1..31 */ /* 0..6 (Sun..Sat) */

Definition at line 90 of file zic.c.

Referenced by rpytime(), rulesub(), and stringrule().

◆ DC_DOWLEQ

#define DC_DOWLEQ   2 /* 1..31 */ /* 0..6 (Sun..Sat) */

Definition at line 91 of file zic.c.

Referenced by rpytime(), rulesub(), and stringrule().

◆ DO

#define DO (   field)    fwrite(tzh.field, sizeof tzh.field, 1, fp)

Referenced by writezone().

◆ EXPIRES_FIELDS

#define EXPIRES_FIELDS   5

Definition at line 271 of file zic.c.

Referenced by inexpires().

◆ LC_EXPIRES

#define LC_EXPIRES   4

Definition at line 204 of file zic.c.

Referenced by infile().

◆ LC_LEAP

#define LC_LEAP   3

Definition at line 203 of file zic.c.

Referenced by infile().

◆ LC_LINK

#define LC_LINK   2

Definition at line 202 of file zic.c.

Referenced by infile().

◆ LC_RULE

#define LC_RULE   0

Definition at line 200 of file zic.c.

Referenced by infile().

◆ LC_ZONE

#define LC_ZONE   1

Definition at line 201 of file zic.c.

Referenced by infile().

◆ LDAYSPERWEEK

#define LDAYSPERWEEK   ((zic_t) DAYSPERWEEK)

Referenced by rpytime().

◆ LEAP_FIELDS

#define LEAP_FIELDS   7

Definition at line 268 of file zic.c.

Referenced by inleap().

◆ LF_LINKNAME

#define LF_LINKNAME   2

Definition at line 255 of file zic.c.

Referenced by inlink().

◆ LF_TARGET

#define LF_TARGET   1

Definition at line 254 of file zic.c.

Referenced by inlink().

◆ LINK_FIELDS

#define LINK_FIELDS   3

Definition at line 256 of file zic.c.

Referenced by inlink().

◆ linkat

#define linkat (   targetdir,
  target,
  linknamedir,
  linkname,
  flag 
)    (itssymlink(target) ? (errno = ENOTSUP, -1) : link(target, linkname))

Definition at line 116 of file zic.c.

Referenced by hardlinkerr().

◆ LP_CORR

#define LP_CORR   5

Definition at line 266 of file zic.c.

Referenced by inleap().

◆ LP_DAY

#define LP_DAY   3

Definition at line 264 of file zic.c.

Referenced by getleapdatetime().

◆ LP_MONTH

#define LP_MONTH   2

Definition at line 263 of file zic.c.

Referenced by getleapdatetime().

◆ LP_ROLL

#define LP_ROLL   6

Definition at line 267 of file zic.c.

Referenced by inleap().

◆ LP_TIME

#define LP_TIME   4

Definition at line 265 of file zic.c.

Referenced by getleapdatetime().

◆ LP_YEAR

#define LP_YEAR   1

Definition at line 262 of file zic.c.

Referenced by getleapdatetime().

◆ MKDIR_UMASK

#define MKDIR_UMASK   0755

Definition at line 37 of file zic.c.

Referenced by mkdirs().

◆ RF_ABBRVAR

#define RF_ABBRVAR   9

Definition at line 247 of file zic.c.

Referenced by inrule().

◆ RF_COMMAND

#define RF_COMMAND   4

Definition at line 242 of file zic.c.

Referenced by inrule().

◆ RF_DAY

#define RF_DAY   6

Definition at line 244 of file zic.c.

Referenced by inrule().

◆ RF_HIYEAR

#define RF_HIYEAR   3

Definition at line 241 of file zic.c.

Referenced by inrule().

◆ RF_LOYEAR

#define RF_LOYEAR   2

Definition at line 240 of file zic.c.

Referenced by inrule().

◆ RF_MONTH

#define RF_MONTH   5

Definition at line 243 of file zic.c.

Referenced by inrule().

◆ RF_NAME

#define RF_NAME   1

Definition at line 239 of file zic.c.

Referenced by inrule().

◆ RF_SAVE

#define RF_SAVE   8

Definition at line 246 of file zic.c.

Referenced by inrule().

◆ RF_TOD

#define RF_TOD   7

Definition at line 245 of file zic.c.

Referenced by inrule().

◆ RULE_FIELDS

#define RULE_FIELDS   10

Definition at line 248 of file zic.c.

Referenced by inrule().

◆ TIME_T_BITS_IN_FILE

#define TIME_T_BITS_IN_FILE   64

Definition at line 580 of file zic.c.

◆ YR_MAXIMUM

#define YR_MAXIMUM   1

Definition at line 278 of file zic.c.

Referenced by rulesub().

◆ YR_MINIMUM

#define YR_MINIMUM   0

Definition at line 277 of file zic.c.

Referenced by rulesub().

◆ YR_ONLY

#define YR_ONLY   2

Definition at line 279 of file zic.c.

Referenced by rulesub().

◆ ZF_FORMAT

#define ZF_FORMAT   4

Definition at line 213 of file zic.c.

Referenced by inzsub().

◆ ZF_NAME

#define ZF_NAME   1

Definition at line 210 of file zic.c.

Referenced by inzone(), and inzsub().

◆ ZF_RULE

#define ZF_RULE   3

Definition at line 212 of file zic.c.

Referenced by inzsub().

◆ ZF_STDOFF

#define ZF_STDOFF   2

Definition at line 211 of file zic.c.

Referenced by inzsub().

◆ ZF_TILDAY

#define ZF_TILDAY   7

Definition at line 216 of file zic.c.

Referenced by inzsub().

◆ ZF_TILMONTH

#define ZF_TILMONTH   6

Definition at line 215 of file zic.c.

Referenced by inzsub().

◆ ZF_TILTIME

#define ZF_TILTIME   8

Definition at line 217 of file zic.c.

Referenced by inzsub().

◆ ZF_TILYEAR

#define ZF_TILYEAR   5

Definition at line 214 of file zic.c.

Referenced by inzsub().

◆ ZFC_FORMAT

#define ZFC_FORMAT   2

Definition at line 227 of file zic.c.

Referenced by inzsub().

◆ ZFC_RULE

#define ZFC_RULE   1

Definition at line 226 of file zic.c.

Referenced by inzsub().

◆ ZFC_STDOFF

#define ZFC_STDOFF   0

Definition at line 225 of file zic.c.

Referenced by inzsub().

◆ ZFC_TILDAY

#define ZFC_TILDAY   5

Definition at line 230 of file zic.c.

Referenced by inzsub().

◆ ZFC_TILMONTH

#define ZFC_TILMONTH   4

Definition at line 229 of file zic.c.

Referenced by inzsub().

◆ ZFC_TILTIME

#define ZFC_TILTIME   6

Definition at line 231 of file zic.c.

Referenced by inzsub().

◆ ZFC_TILYEAR

#define ZFC_TILYEAR   3

Definition at line 228 of file zic.c.

Referenced by inzsub().

◆ ZIC_BLOAT_DEFAULT

#define ZIC_BLOAT_DEFAULT   "slim"

Definition at line 648 of file zic.c.

Referenced by main().

◆ ZIC_MAX

#define ZIC_MAX   PG_INT64_MAX

Definition at line 27 of file zic.c.

Referenced by gethms(), limitrange(), oadd(), outzone(), rpytime(), rulesub(), stringzone(), and writezone().

◆ ZIC_MAX_ABBR_LEN_WO_WARN

#define ZIC_MAX_ABBR_LEN_WO_WARN   6

Definition at line 30 of file zic.c.

Referenced by newabbr().

◆ ZIC_MIN

#define ZIC_MIN   PG_INT64_MIN

Definition at line 26 of file zic.c.

Referenced by oadd(), outzone(), rpytime(), and rulesub().

◆ ZIC_VERSION

#define ZIC_VERSION   '3'

Definition at line 23 of file zic.c.

Referenced by outzone().

◆ ZIC_VERSION_PRE_2013

#define ZIC_VERSION_PRE_2013   '2'

Definition at line 22 of file zic.c.

Referenced by outzone().

◆ ZONE_MAXFIELDS

#define ZONE_MAXFIELDS   9

Definition at line 219 of file zic.c.

Referenced by inzone().

◆ ZONE_MINFIELDS

#define ZONE_MINFIELDS   5

Definition at line 218 of file zic.c.

◆ ZONEC_MAXFIELDS

#define ZONEC_MAXFIELDS   7

Definition at line 233 of file zic.c.

Referenced by inzcont().

◆ ZONEC_MINFIELDS

#define ZONEC_MINFIELDS   3

Definition at line 232 of file zic.c.

Typedef Documentation

◆ lineno_t

typedef int lineno_t

Definition at line 55 of file zic.c.

◆ zic_t

typedef int64 zic_t

Definition at line 25 of file zic.c.

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Enumerator
PERCENT_Z_LEN_BOUND 

Definition at line 158 of file zic.c.

159 {
160 PERCENT_Z_LEN_BOUND = sizeof "+995959" - 1};

◆ anonymous enum

anonymous enum
Enumerator
WORK_AROUND_QTBUG_53071 

Definition at line 168 of file zic.c.

Function Documentation

◆ abbroffset()

static char const* abbroffset ( char *  buf,
zic_t  offset 
)
static

Definition at line 2584 of file zic.c.

References _, buf, error(), MINSPERHOUR, SECSPERMIN, and sign.

Referenced by doabbr().

2585 {
2586  char sign = '+';
2587  int seconds,
2588  minutes;
2589 
2590  if (offset < 0)
2591  {
2592  offset = -offset;
2593  sign = '-';
2594  }
2595 
2596  seconds = offset % SECSPERMIN;
2597  offset /= SECSPERMIN;
2598  minutes = offset % MINSPERHOUR;
2599  offset /= MINSPERHOUR;
2600  if (100 <= offset)
2601  {
2602  error(_("%%z UT offset magnitude exceeds 99:59:59"));
2603  return "%z";
2604  }
2605  else
2606  {
2607  char *p = buf;
2608 
2609  *p++ = sign;
2610  *p++ = '0' + offset / 10;
2611  *p++ = '0' + offset % 10;
2612  if (minutes | seconds)
2613  {
2614  *p++ = '0' + minutes / 10;
2615  *p++ = '0' + minutes % 10;
2616  if (seconds)
2617  {
2618  *p++ = '0' + seconds / 10;
2619  *p++ = '0' + seconds % 10;
2620  }
2621  }
2622  *p = '\0';
2623  return buf;
2624  }
2625 }
#define SECSPERMIN
Definition: private.h:101
char sign
Definition: informix.c:668
static char * buf
Definition: pg_test_fsync.c:68
static void static void error(const char *string,...) pg_attribute_printf(1
Definition: zic.c:502
#define _(x)
Definition: elog.c:88
#define MINSPERHOUR
Definition: private.h:102

◆ addtt()

static void addtt ( zic_t  starttime,
int  type 
)
static

Definition at line 3346 of file zic.c.

References attype::at, attypes, attype::dontmerge, growalloc(), timecnt, generate_unaccent_rules::type, and attype::type.

Referenced by outzone().

3347 {
3349  attypes[timecnt].at = starttime;
3350  attypes[timecnt].dontmerge = false;
3351  attypes[timecnt].type = type;
3352  ++timecnt;
3353 }
unsigned char type
Definition: zic.c:392
static void * growalloc(void *ptr, size_t itemsize, ptrdiff_t nitems, ptrdiff_t *nitems_alloc)
Definition: zic.c:450
zic_t at
Definition: zic.c:390
static ptrdiff_t timecnt_alloc
Definition: zic.c:193
static struct attype * attypes
static ptrdiff_t timecnt
Definition: zic.c:192
bool dontmerge
Definition: zic.c:391

◆ addtype()

static int addtype ( zic_t  utoff,
char const *  abbr,
bool  isdst,
bool  ttisstd,
bool  ttisut 
)
static

Definition at line 3356 of file zic.c.

References _, charcnt, error(), EXIT_FAILURE, i, newabbr(), typecnt, TZ_MAX_TYPES, and want_bloat().

Referenced by outzone(), and writezone().

3357 {
3358  int i,
3359  j;
3360 
3361  if (!(-1L - 2147483647L <= utoff && utoff <= 2147483647L))
3362  {
3363  error(_("UT offset out of range"));
3364  exit(EXIT_FAILURE);
3365  }
3366  if (!want_bloat())
3367  ttisstd = ttisut = false;
3368 
3369  for (j = 0; j < charcnt; ++j)
3370  if (strcmp(&chars[j], abbr) == 0)
3371  break;
3372  if (j == charcnt)
3373  newabbr(abbr);
3374  else
3375  {
3376  /* If there's already an entry, return its index. */
3377  for (i = 0; i < typecnt; i++)
3378  if (utoff == utoffs[i] && isdst == isdsts[i] && j == desigidx[i]
3379  && ttisstd == ttisstds[i] && ttisut == ttisuts[i])
3380  return i;
3381  }
3382 
3383  /*
3384  * There isn't one; add a new one, unless there are already too many.
3385  */
3386  if (typecnt >= TZ_MAX_TYPES)
3387  {
3388  error(_("too many local time types"));
3389  exit(EXIT_FAILURE);
3390  }
3391  i = typecnt++;
3392  utoffs[i] = utoff;
3393  isdsts[i] = isdst;
3394  ttisstds[i] = ttisstd;
3395  ttisuts[i] = ttisut;
3396  desigidx[i] = j;
3397  return i;
3398 }
static bool ttisstds[TZ_MAX_TYPES]
Definition: zic.c:397
static int typecnt
Definition: zic.c:194
static char isdsts[TZ_MAX_TYPES]
Definition: zic.c:395
static zic_t utoffs[TZ_MAX_TYPES]
Definition: zic.c:394
static int charcnt
Definition: zic.c:173
#define TZ_MAX_TYPES
Definition: tzfile.h:103
static void newabbr(const char *abbr)
Definition: zic.c:3908
int i
#define EXIT_FAILURE
Definition: settings.h:161
static void static void error(const char *string,...) pg_attribute_printf(1
Definition: zic.c:502
static bool ttisuts[TZ_MAX_TYPES]
Definition: zic.c:398
static char chars[TZ_MAX_CHARS]
Definition: zic.c:399
#define _(x)
Definition: elog.c:88
static bool want_bloat(void)
Definition: zic.c:642
static unsigned char desigidx[TZ_MAX_TYPES]
Definition: zic.c:396

◆ adjleap()

static void adjleap ( void  )
static

Definition at line 3423 of file zic.c.

References _, comment_leapexpires, error(), EXIT_FAILURE, i, leapcnt, oadd(), SECSPERDAY, tadd(), and warning().

Referenced by main().

3424 {
3425  int i;
3426  zic_t last = 0;
3427  zic_t prevtrans = 0;
3428 
3429  /*
3430  * propagate leap seconds forward
3431  */
3432  for (i = 0; i < leapcnt; ++i)
3433  {
3434  if (trans[i] - prevtrans < 28 * SECSPERDAY)
3435  {
3436  error(_("Leap seconds too close together"));
3437  exit(EXIT_FAILURE);
3438  }
3439  prevtrans = trans[i];
3440  trans[i] = tadd(trans[i], last);
3441  last = corr[i] += last;
3442  }
3443 
3444  if (leapexpires < 0)
3445  {
3447  if (0 <= leapexpires)
3448  warning(_("\"#expires\" is obsolescent; use \"Expires\""));
3449  }
3450 
3451  if (0 <= leapexpires)
3452  {
3453  leapexpires = oadd(leapexpires, last);
3454  if (!(leapcnt == 0 || (trans[leapcnt - 1] < leapexpires)))
3455  {
3456  error(_("last Leap time does not precede Expires time"));
3457  exit(EXIT_FAILURE);
3458  }
3459  if (leapexpires <= hi_time)
3460  hi_time = leapexpires - 1;
3461  }
3462 }
static void static void static void warning(const char *string,...) pg_attribute_printf(1
Definition: zic.c:513
static zic_t corr[TZ_MAX_LEAPS]
Definition: zic.c:401
#define SECSPERDAY
Definition: private.h:108
static zic_t hi_time
Definition: zic.c:589
static zic_t tadd(zic_t t1, zic_t t2)
Definition: zic.c:3770
static zic_t comment_leapexpires
Definition: zic.c:595
static int leapcnt
Definition: zic.c:177
int64 zic_t
Definition: zic.c:25
static zic_t leapexpires
Definition: zic.c:592
static zic_t trans[TZ_MAX_LEAPS]
Definition: zic.c:400
int i
#define EXIT_FAILURE
Definition: settings.h:161
static void static void error(const char *string,...) pg_attribute_printf(1
Definition: zic.c:502
#define _(x)
Definition: elog.c:88
static zic_t oadd(zic_t t1, zic_t t2)
Definition: zic.c:3762

◆ associate()

static void associate ( void  )
static

Definition at line 1156 of file zic.c.

References _, eat(), error(), EXIT_FAILURE, getsave(), i, nrules, nzones, qsort, rule::r_filename, rule::r_linenum, rule::r_name, rcomp(), warning(), zone::z_filename, zone::z_format_specifier, zone::z_isdst, zone::z_linenum, zone::z_nrules, zone::z_rule, zone::z_rules, and zone::z_save.

Referenced by main().

1157 {
1158  struct zone *zp;
1159  struct rule *rp;
1160  ptrdiff_t i,
1161  j,
1162  base,
1163  out;
1164 
1165  if (nrules != 0)
1166  {
1167  qsort(rules, nrules, sizeof *rules, rcomp);
1168  for (i = 0; i < nrules - 1; ++i)
1169  {
1170  if (strcmp(rules[i].r_name,
1171  rules[i + 1].r_name) != 0)
1172  continue;
1173  if (strcmp(rules[i].r_filename,
1174  rules[i + 1].r_filename) == 0)
1175  continue;
1176  eat(rules[i].r_filename, rules[i].r_linenum);
1177  warning(_("same rule name in multiple files"));
1178  eat(rules[i + 1].r_filename, rules[i + 1].r_linenum);
1179  warning(_("same rule name in multiple files"));
1180  for (j = i + 2; j < nrules; ++j)
1181  {
1182  if (strcmp(rules[i].r_name,
1183  rules[j].r_name) != 0)
1184  break;
1185  if (strcmp(rules[i].r_filename,
1186  rules[j].r_filename) == 0)
1187  continue;
1188  if (strcmp(rules[i + 1].r_filename,
1189  rules[j].r_filename) == 0)
1190  continue;
1191  break;
1192  }
1193  i = j - 1;
1194  }
1195  }
1196  for (i = 0; i < nzones; ++i)
1197  {
1198  zp = &zones[i];
1199  zp->z_rules = NULL;
1200  zp->z_nrules = 0;
1201  }
1202  for (base = 0; base < nrules; base = out)
1203  {
1204  rp = &rules[base];
1205  for (out = base + 1; out < nrules; ++out)
1206  if (strcmp(rp->r_name, rules[out].r_name) != 0)
1207  break;
1208  for (i = 0; i < nzones; ++i)
1209  {
1210  zp = &zones[i];
1211  if (strcmp(zp->z_rule, rp->r_name) != 0)
1212  continue;
1213  zp->z_rules = rp;
1214  zp->z_nrules = out - base;
1215  }
1216  }
1217  for (i = 0; i < nzones; ++i)
1218  {
1219  zp = &zones[i];
1220  if (zp->z_nrules == 0)
1221  {
1222  /*
1223  * Maybe we have a local standard time offset.
1224  */
1225  eat(zp->z_filename, zp->z_linenum);
1226  zp->z_save = getsave(zp->z_rule, &zp->z_isdst);
1227 
1228  /*
1229  * Note, though, that if there's no rule, a '%s' in the format is
1230  * a bad thing.
1231  */
1232  if (zp->z_format_specifier == 's')
1233  error("%s", _("%s in ruleless zone"));
1234  }
1235  }
1236  if (errors)
1237  exit(EXIT_FAILURE);
1238 }
lineno_t r_linenum
Definition: zic.c:60
static int rcomp(const void *cp1, const void *cp2)
Definition: zic.c:1149
zic_t z_save
Definition: zic.c:105
static void static void static void warning(const char *string,...) pg_attribute_printf(1
Definition: zic.c:513
static bool errors
Definition: zic.c:174
static ptrdiff_t nzones
Definition: zic.c:286
bool z_isdst
Definition: zic.c:104
Definition: localtime.c:72
char z_format_specifier
Definition: zic.c:102
char * z_rule
Definition: zic.c:100
const char * r_name
Definition: zic.c:61
const char * z_filename
Definition: zic.c:95
static struct rule * rules
Definition: zic.c:281
const char * r_filename
Definition: zic.c:59
static void eat(char const *name, lineno_t num)
Definition: zic.c:480
ptrdiff_t z_nrules
Definition: zic.c:108
lineno_t z_linenum
Definition: zic.c:96
static zic_t getsave(char *, bool *)
Definition: zic.c:1441
static ptrdiff_t nrules
Definition: zic.c:282
static struct zone * zones
Definition: zic.c:285
struct rule * z_rules
Definition: zic.c:107
Definition: zic.c:93
int i
#define EXIT_FAILURE
Definition: settings.h:161
#define qsort(a, b, c, d)
Definition: port.h:497
static void static void error(const char *string,...) pg_attribute_printf(1
Definition: zic.c:502
#define _(x)
Definition: elog.c:88

◆ atcomp()

static int atcomp ( const void *  avp,
const void *  bvp 
)
static

Definition at line 2035 of file zic.c.

Referenced by writezone().

2036 {
2037  const zic_t a = ((const struct attype *) avp)->at;
2038  const zic_t b = ((const struct attype *) bvp)->at;
2039 
2040  return (a < b) ? -1 : (a > b);
2041 }
Definition: zic.c:388
int64 zic_t
Definition: zic.c:25

◆ byword()

static const struct lookup * byword ( const char *  string,
const struct lookup lp 
)
static

Definition at line 3649 of file zic.c.

References _, ciequal(), ciprefix(), itsabbr(), lookup::l_word, warning(), and wday_names.

Referenced by getleapdatetime(), infile(), inleap(), and rulesub().

3650 {
3651  const struct lookup *foundlp;
3652  const struct lookup *lp;
3653 
3654  if (word == NULL || table == NULL)
3655  return NULL;
3656 
3657  /*
3658  * If TABLE is LASTS and the word starts with "last" followed by a
3659  * non-'-', skip the "last" and look in WDAY_NAMES instead. Warn about any
3660  * usage of the undocumented prefix "last-".
3661  */
3662  if (table == lasts && ciprefix("last", word) && word[4])
3663  {
3664  if (word[4] == '-')
3665  warning(_("\"%s\" is undocumented; use \"last%s\" instead"),
3666  word, word + 5);
3667  else
3668  {
3669  word += 4;
3670  table = wday_names;
3671  }
3672  }
3673 
3674  /*
3675  * Look for exact match.
3676  */
3677  for (lp = table; lp->l_word != NULL; ++lp)
3678  if (ciequal(word, lp->l_word))
3679  return lp;
3680 
3681  /*
3682  * Look for inexact match.
3683  */
3684  foundlp = NULL;
3685  for (lp = table; lp->l_word != NULL; ++lp)
3686  if (ciprefix(word, lp->l_word))
3687  {
3688  if (foundlp == NULL)
3689  foundlp = lp;
3690  else
3691  return NULL; /* multiple inexact matches */
3692  }
3693 
3694  if (foundlp && noise)
3695  {
3696  /* Warn about any backward-compatibility issue with pre-2017c zic. */
3697  bool pre_2017c_match = false;
3698 
3699  for (lp = table; lp->l_word; lp++)
3700  if (itsabbr(word, lp->l_word))
3701  {
3702  if (pre_2017c_match)
3703  {
3704  warning(_("\"%s\" is ambiguous in pre-2017c zic"), word);
3705  break;
3706  }
3707  pre_2017c_match = true;
3708  }
3709  }
3710 
3711  return foundlp;
3712 }
static bool ciprefix(char const *abbr, char const *word)
Definition: zic.c:3638
static void static void static void warning(const char *string,...) pg_attribute_printf(1
Definition: zic.c:513
Definition: zic.c:301
static bool ciequal(const char *ap, const char *bp)
Definition: zic.c:3612
const char * l_word
Definition: zic.c:303
static bool noise
Definition: zic.c:186
static void word(struct vars *, int, struct state *, struct state *)
Definition: regcomp.c:1246
static struct lookup const lasts[]
Definition: zic.c:349
static struct lookup const wday_names[]
Definition: zic.c:338
#define _(x)
Definition: elog.c:88
static bool itsabbr(const char *abbr, const char *word)
Definition: zic.c:3621

◆ change_directory()

static void change_directory ( char const *  dir)
static

Definition at line 560 of file zic.c.

References _, EXIT_FAILURE, fprintf, mkdirs(), and strerror.

Referenced by main().

561 {
562  if (chdir(dir) != 0)
563  {
564  int chdir_errno = errno;
565 
566  if (chdir_errno == ENOENT)
567  {
568  mkdirs(dir, false);
569  chdir_errno = chdir(dir) == 0 ? 0 : errno;
570  }
571  if (chdir_errno != 0)
572  {
573  fprintf(stderr, _("%s: Can't chdir to %s: %s\n"),
574  progname, dir, strerror(chdir_errno));
575  exit(EXIT_FAILURE);
576  }
577  }
578 }
#define fprintf
Definition: port.h:219
static void mkdirs(char const *, bool)
Definition: zic.c:3946
static const char * progname
Definition: zic.c:191
#define strerror
Definition: port.h:228
#define EXIT_FAILURE
Definition: settings.h:161
#define _(x)
Definition: elog.c:88

◆ ciequal()

static bool ciequal ( const char *  ap,
const char *  bp 
)
static

Definition at line 3612 of file zic.c.

References lowerit().

Referenced by byword().

3613 {
3614  while (lowerit(*ap) == lowerit(*bp++))
3615  if (*ap++ == '\0')
3616  return true;
3617  return false;
3618 }
static char lowerit(char)
Definition: zic.c:3549

◆ ciprefix()

static bool ciprefix ( char const *  abbr,
char const *  word 
)
static

Definition at line 3638 of file zic.c.

References lowerit().

Referenced by byword().

3639 {
3640  do
3641  if (!*abbr)
3642  return true;
3643  while (lowerit(*abbr++) == lowerit(*word++));
3644 
3645  return false;
3646 }
static char lowerit(char)
Definition: zic.c:3549
static void word(struct vars *, int, struct state *, struct state *)
Definition: regcomp.c:1246

◆ close_file()

static void close_file ( FILE *  stream,
char const *  dir,
char const *  name 
)
static

Definition at line 525 of file zic.c.

References _, EXIT_FAILURE, fprintf, and strerror.

Referenced by dolink(), infile(), main(), usage(), and writezone().

526 {
527  char const *e = (ferror(stream) ? _("I/O error")
528  : fclose(stream) != 0 ? strerror(errno) : NULL);
529 
530  if (e)
531  {
532  fprintf(stderr, "%s: %s%s%s%s%s\n", progname,
533  dir ? dir : "", dir ? "/" : "",
534  name ? name : "", name ? ": " : "",
535  e);
536  exit(EXIT_FAILURE);
537  }
538 }
#define fprintf
Definition: port.h:219
static const char * progname
Definition: zic.c:191
#define strerror
Definition: port.h:228
const char * name
Definition: encode.c:561
e
Definition: preproc-init.c:82
#define EXIT_FAILURE
Definition: settings.h:161
#define _(x)
Definition: elog.c:88

◆ componentcheck()

static bool componentcheck ( char const *  name,
char const *  component,
char const *  component_end 
)
static

Definition at line 857 of file zic.c.

References _, error(), and warning().

Referenced by namecheck().

859 {
860  enum
861  {
862  component_len_max = 14};
863  ptrdiff_t component_len = component_end - component;
864 
865  if (component_len == 0)
866  {
867  if (!*name)
868  error(_("empty file name"));
869  else
870  error(_(component == name
871  ? "file name '%s' begins with '/'"
872  : *component_end
873  ? "file name '%s' contains '//'"
874  : "file name '%s' ends with '/'"),
875  name);
876  return false;
877  }
878  if (0 < component_len && component_len <= 2
879  && component[0] == '.' && component_end[-1] == '.')
880  {
881  int len = component_len;
882 
883  error(_("file name '%s' contains '%.*s' component"),
884  name, len, component);
885  return false;
886  }
887  if (noise)
888  {
889  if (0 < component_len && component[0] == '-')
890  warning(_("file name '%s' component contains leading '-'"),
891  name);
892  if (component_len_max < component_len)
893  warning(_("file name '%s' contains overlength component"
894  " '%.*s...'"),
895  name, component_len_max, component);
896  }
897  return true;
898 }
static void static void static void warning(const char *string,...) pg_attribute_printf(1
Definition: zic.c:513
static bool noise
Definition: zic.c:186
const char * name
Definition: encode.c:561
static void static void error(const char *string,...) pg_attribute_printf(1
Definition: zic.c:502
#define _(x)
Definition: elog.c:88

◆ convert()

static void convert ( const int32  val,
char *const  buf 
)
static

Definition at line 1990 of file zic.c.

References i.

Referenced by ExecEvalConvertRowtype(), ExecInitExprRec(), fmtfloat(), fmtint(), fmtptr(), get_rule_expr(), pg_strfromd(), print_double(), puttzcode(), and writezone().

1991 {
1992  int i;
1993  int shift;
1994  unsigned char *const b = (unsigned char *) buf;
1995 
1996  for (i = 0, shift = 24; i < 4; ++i, shift -= 8)
1997  b[i] = val >> shift;
1998 }
static char * buf
Definition: pg_test_fsync.c:68
int i
long val
Definition: informix.c:664

◆ convert64()

static void convert64 ( const zic_t  val,
char *const  buf 
)
static

Definition at line 2001 of file zic.c.

References i.

Referenced by puttzcodepass().

2002 {
2003  int i;
2004  int shift;
2005  unsigned char *const b = (unsigned char *) buf;
2006 
2007  for (i = 0, shift = 56; i < 8; ++i, shift -= 8)
2008  b[i] = val >> shift;
2009 }
static char * buf
Definition: pg_test_fsync.c:68
int i
long val
Definition: informix.c:664

◆ doabbr()

static size_t doabbr ( char *  abbr,
struct zone const *  zp,
char const *  letters,
bool  isdst,
zic_t  save,
bool  doquotes 
)
static

Definition at line 2628 of file zic.c.

References abbroffset(), format, is_alpha(), PERCENT_Z_LEN_BOUND, sprintf, zone::z_format, zone::z_format_specifier, and zone::z_stdoff.

Referenced by outzone(), and stringzone().

2630 {
2631  char *cp;
2632  char *slashp;
2633  size_t len;
2634  char const *format = zp->z_format;
2635 
2636  slashp = strchr(format, '/');
2637  if (slashp == NULL)
2638  {
2639  char letterbuf[PERCENT_Z_LEN_BOUND + 1];
2640 
2641  if (zp->z_format_specifier == 'z')
2642  letters = abbroffset(letterbuf, zp->z_stdoff + save);
2643  else if (!letters)
2644  letters = "%s";
2645  sprintf(abbr, format, letters);
2646  }
2647  else if (isdst)
2648  {
2649  strcpy(abbr, slashp + 1);
2650  }
2651  else
2652  {
2653  memcpy(abbr, format, slashp - format);
2654  abbr[slashp - format] = '\0';
2655  }
2656  len = strlen(abbr);
2657  if (!doquotes)
2658  return len;
2659  for (cp = abbr; is_alpha(*cp); cp++)
2660  continue;
2661  if (len > 0 && *cp == '\0')
2662  return len;
2663  abbr[len + 2] = '\0';
2664  abbr[len + 1] = '>';
2665  memmove(abbr + 1, abbr, len);
2666  abbr[0] = '<';
2667  return len + 2;
2668 }
static char const * abbroffset(char *buf, zic_t offset)
Definition: zic.c:2584
#define sprintf
Definition: port.h:217
static bool is_alpha(char a)
Definition: zic.c:3484
static char format

◆ dolink()

static void dolink ( const char *  target,
const char *  linkname,
bool  staysymlink 
)
static

Definition at line 1002 of file zic.c.

References _, close_file(), ENOTSUP, EXIT_FAILURE, fprintf, free, hardlinkerr(), itsdir(), itssymlink(), mkdirs(), relname, strerror, symlink, and warning().

Referenced by main().

1003 {
1004  bool remove_only = strcmp(target, "-") == 0;
1005  bool linkdirs_made = false;
1006  int link_errno;
1007 
1008  /*
1009  * We get to be careful here since there's a fair chance of root running
1010  * us.
1011  */
1012  if (!remove_only && itsdir(target))
1013  {
1014  fprintf(stderr, _("%s: linking target %s/%s failed: %s\n"),
1015  progname, directory, target, strerror(EPERM));
1016  exit(EXIT_FAILURE);
1017  }
1018  if (staysymlink)
1019  staysymlink = itssymlink(linkname);
1020  if (remove(linkname) == 0)
1021  linkdirs_made = true;
1022  else if (errno != ENOENT)
1023  {
1024  char const *e = strerror(errno);
1025 
1026  fprintf(stderr, _("%s: Can't remove %s/%s: %s\n"),
1027  progname, directory, linkname, e);
1028  exit(EXIT_FAILURE);
1029  }
1030  if (remove_only)
1031  return;
1032  link_errno = staysymlink ? ENOTSUP : hardlinkerr(target, linkname);
1033  if (link_errno == ENOENT && !linkdirs_made)
1034  {
1035  mkdirs(linkname, true);
1036  linkdirs_made = true;
1037  link_errno = hardlinkerr(target, linkname);
1038  }
1039  if (link_errno != 0)
1040  {
1041 #ifdef HAVE_SYMLINK
1042  bool absolute = *target == '/';
1043  char *linkalloc = absolute ? NULL : relname(target, linkname);
1044  char const *contents = absolute ? target : linkalloc;
1045  int symlink_errno = symlink(contents, linkname) == 0 ? 0 : errno;
1046 
1047  if (!linkdirs_made
1048  && (symlink_errno == ENOENT || symlink_errno == ENOTSUP))
1049  {
1050  mkdirs(linkname, true);
1051  if (symlink_errno == ENOENT)
1052  symlink_errno = symlink(contents, linkname) == 0 ? 0 : errno;
1053  }
1054  free(linkalloc);
1055  if (symlink_errno == 0)
1056  {
1057  if (link_errno != ENOTSUP)
1058  warning(_("symbolic link used because hard link failed: %s"),
1059  strerror(link_errno));
1060  }
1061  else
1062 #endif /* HAVE_SYMLINK */
1063  {
1064  FILE *fp,
1065  *tp;
1066  int c;
1067 
1068  fp = fopen(target, "rb");
1069  if (!fp)
1070  {
1071  char const *e = strerror(errno);
1072 
1073  fprintf(stderr, _("%s: Can't read %s/%s: %s\n"),
1074  progname, directory, target, e);
1075  exit(EXIT_FAILURE);
1076  }
1077  tp = fopen(linkname, "wb");
1078  if (!tp)
1079  {
1080  char const *e = strerror(errno);
1081 
1082  fprintf(stderr, _("%s: Can't create %s/%s: %s\n"),
1083  progname, directory, linkname, e);
1084  exit(EXIT_FAILURE);
1085  }
1086  while ((c = getc(fp)) != EOF)
1087  putc(c, tp);
1088  close_file(fp, directory, target);
1089  close_file(tp, directory, linkname);
1090  if (link_errno != ENOTSUP)
1091  warning(_("copy used because hard link failed: %s"),
1092  strerror(link_errno));
1093 #ifdef HAVE_SYMLINK
1094  else if (symlink_errno != ENOTSUP)
1095  warning(_("copy used because symbolic link failed: %s"),
1096  strerror(symlink_errno));
1097 #endif
1098  }
1099  }
1100 }
static void static void static void warning(const char *string,...) pg_attribute_printf(1
Definition: zic.c:513
#define ENOTSUP
Definition: private.h:38
NameData relname
Definition: pg_class.h:38
#define fprintf
Definition: port.h:219
static void mkdirs(char const *, bool)
Definition: zic.c:3946
static bool itsdir(char const *)
Definition: zic.c:1104
static int hardlinkerr(char const *target, char const *linkname)
Definition: zic.c:994
char * c
#define symlink(oldpath, newpath)
Definition: win32_port.h:227
static bool itssymlink(char const *)
Definition: zic.c:1129
static const char * progname
Definition: zic.c:191
#define free(a)
Definition: header.h:65
#define strerror
Definition: port.h:228
static const char * directory
Definition: zic.c:632
static void close_file(FILE *stream, char const *dir, char const *name)
Definition: zic.c:525
e
Definition: preproc-init.c:82
#define EXIT_FAILURE
Definition: settings.h:161
#define _(x)
Definition: elog.c:88

◆ eat()

static void eat ( char const *  name,
lineno_t  num 
)
static

Definition at line 480 of file zic.c.

References eats().

Referenced by associate(), infile(), main(), and outzone().

481 {
482  eats(name, num, NULL, -1);
483 }
const char * name
Definition: encode.c:561
static void eats(char const *name, lineno_t num, char const *rname, lineno_t rnum)
Definition: zic.c:471

◆ eats()

static void eats ( char const *  name,
lineno_t  num,
char const *  rname,
lineno_t  rnum 
)
static

Definition at line 471 of file zic.c.

References name.

Referenced by eat(), and outzone().

472 {
473  filename = name;
474  linenum = num;
475  rfilename = rname;
476  rlinenum = rnum;
477 }
static lineno_t rlinenum
Definition: zic.c:190
static const char * filename
Definition: zic.c:176
static lineno_t linenum
Definition: zic.c:181
static const char * rfilename
Definition: zic.c:189
const char * name
Definition: encode.c:561

◆ ecpyalloc()

static char* ecpyalloc ( char const *  str)
static

Definition at line 444 of file zic.c.

References memcheck().

Referenced by inlink(), inrule(), inzsub(), mkdirs(), and rulesub().

445 {
446  return memcheck(strdup(str));
447 }
static void * memcheck(void *ptr)
Definition: zic.c:424

◆ emalloc()

static void* emalloc ( size_t  size)
static

Definition at line 432 of file zic.c.

References malloc, and memcheck().

Referenced by getfields(), itsdir(), namecheck(), outzone(), and writezone().

433 {
434  return memcheck(malloc(size));
435 }
#define malloc(a)
Definition: header.h:50
static void * memcheck(void *ptr)
Definition: zic.c:424

◆ erealloc()

static void* erealloc ( void *  ptr,
size_t  size 
)
static

Definition at line 438 of file zic.c.

References memcheck(), and realloc.

Referenced by growalloc().

439 {
440  return memcheck(realloc(ptr, size));
441 }
#define realloc(a, b)
Definition: header.h:60
static void * memcheck(void *ptr)
Definition: zic.c:424

◆ error()

static void error ( const char *  string,
  ... 
)
static

Definition at line 502 of file zic.c.

References generate_unaccent_rules::args, and verror().

Referenced by abbroffset(), addtype(), adjleap(), associate(), componentcheck(), getfields(), gethms(), getleapdatetime(), inexpires(), infile(), inleap(), inlink(), inrule(), inzcont(), inzone(), inzsub(), leapadd(), main(), mkdirs(), newabbr(), outzone(), rpytime(), rulesub(), time_overflow(), and writezone().

503 {
504  va_list args;
505 
506  va_start(args, string);
507  verror(string, args);
508  va_end(args);
509  errors = true;
510 }
static bool errors
Definition: zic.c:174
static void verror(const char *string, va_list args) pg_attribute_printf(1
Definition: zic.c:486

◆ getfields()

static char ** getfields ( char *  buf)
static

Definition at line 3715 of file zic.c.

References _, emalloc(), error(), EXIT_FAILURE, is_space(), and size_product().

Referenced by infile().

3716 {
3717  char *dp;
3718  char **array;
3719  int nsubs;
3720 
3721  if (cp == NULL)
3722  return NULL;
3723  array = emalloc(size_product(strlen(cp) + 1, sizeof *array));
3724  nsubs = 0;
3725  for (;;)
3726  {
3727  while (is_space(*cp))
3728  ++cp;
3729  if (*cp == '\0' || *cp == '#')
3730  break;
3731  array[nsubs++] = dp = cp;
3732  do
3733  {
3734  if ((*dp = *cp++) != '"')
3735  ++dp;
3736  else
3737  while ((*dp = *cp++) != '"')
3738  if (*dp != '\0')
3739  ++dp;
3740  else
3741  {
3742  error(_("Odd number of quotation marks"));
3743  exit(EXIT_FAILURE);
3744  }
3745  } while (*cp && *cp != '#' && !is_space(*cp));
3746  if (is_space(*cp))
3747  ++cp;
3748  *dp = '\0';
3749  }
3750  array[nsubs] = NULL;
3751  return array;
3752 }
static bool is_space(char a)
Definition: zic.c:3466
#define EXIT_FAILURE
Definition: settings.h:161
static void static void error(const char *string,...) pg_attribute_printf(1
Definition: zic.c:502
#define _(x)
Definition: elog.c:88
static size_t size_product(size_t nitems, size_t itemsize)
Definition: zic.c:416
static void * emalloc(size_t size)
Definition: zic.c:432

◆ gethms()

static zic_t gethms ( const char *  string,
const char *  errstring 
)
static

Definition at line 1363 of file zic.c.

References _, error(), HOURSPERDAY, MINSPERHOUR, oadd(), SECSPERHOUR, SECSPERMIN, sign, warning(), and ZIC_MAX.

Referenced by getleapdatetime(), getsave(), inzsub(), and rulesub().

1364 {
1365  /* PG: make hh be int not zic_t to avoid sscanf portability issues */
1366  int hh;
1367  int sign,
1368  mm = 0,
1369  ss = 0;
1370  char hhx,
1371  mmx,
1372  ssx,
1373  xr = '0',
1374  xs;
1375  int tenths = 0;
1376  bool ok = true;
1377 
1378  if (string == NULL || *string == '\0')
1379  return 0;
1380  if (*string == '-')
1381  {
1382  sign = -1;
1383  ++string;
1384  }
1385  else
1386  sign = 1;
1387  switch (sscanf(string,
1388  "%d%c%d%c%d%c%1d%*[0]%c%*[0123456789]%c",
1389  &hh, &hhx, &mm, &mmx, &ss, &ssx, &tenths, &xr, &xs))
1390  {
1391  default:
1392  ok = false;
1393  break;
1394  case 8:
1395  ok = '0' <= xr && xr <= '9';
1396  /* fallthrough */
1397  case 7:
1398  ok &= ssx == '.';
1399  if (ok && noise)
1400  warning(_("fractional seconds rejected by"
1401  " pre-2018 versions of zic"));
1402  /* fallthrough */
1403  case 5:
1404  ok &= mmx == ':';
1405  /* fallthrough */
1406  case 3:
1407  ok &= hhx == ':';
1408  /* fallthrough */
1409  case 1:
1410  break;
1411  }
1412  if (!ok)
1413  {
1414  error("%s", errstring);
1415  return 0;
1416  }
1417  if (hh < 0 ||
1418  mm < 0 || mm >= MINSPERHOUR ||
1419  ss < 0 || ss > SECSPERMIN)
1420  {
1421  error("%s", errstring);
1422  return 0;
1423  }
1424  /* Some compilers warn that this test is unsatisfiable for 32-bit ints */
1425 #if INT_MAX > PG_INT32_MAX
1426  if (ZIC_MAX / SECSPERHOUR < hh)
1427  {
1428  error(_("time overflow"));
1429  return 0;
1430  }
1431 #endif
1432  ss += 5 + ((ss ^ 1) & (xr == '0')) <= tenths; /* Round to even. */
1433  if (noise && (hh > HOURSPERDAY ||
1434  (hh == HOURSPERDAY && (mm != 0 || ss != 0))))
1435  warning(_("values over 24 hours not handled by pre-2007 versions of zic"));
1436  return oadd(sign * (zic_t) hh * SECSPERHOUR,
1437  sign * (mm * SECSPERMIN + ss));
1438 }
#define SECSPERMIN
Definition: private.h:101
static void static void static void warning(const char *string,...) pg_attribute_printf(1
Definition: zic.c:513
#define SECSPERHOUR
Definition: private.h:107
#define HOURSPERDAY
Definition: private.h:103
#define ZIC_MAX
Definition: zic.c:27
char sign
Definition: informix.c:668
char string[11]
Definition: preproc-type.c:46
int64 zic_t
Definition: zic.c:25
static bool noise
Definition: zic.c:186
static void static void error(const char *string,...) pg_attribute_printf(1
Definition: zic.c:502
#define _(x)
Definition: elog.c:88
static zic_t oadd(zic_t t1, zic_t t2)
Definition: zic.c:3762
#define MINSPERHOUR
Definition: private.h:102

◆ getleapdatetime()

static zic_t getleapdatetime ( char **  fields,
int  nfields,
bool  expire_line 
)
static

Definition at line 1664 of file zic.c.

References _, byword(), EPOCH_YEAR, error(), gethms(), i, isleap, lookup::l_value, LP_DAY, LP_MONTH, LP_TIME, LP_YEAR, oadd(), SECSPERDAY, tadd(), and TM_JANUARY.

Referenced by inexpires(), and inleap().

1665 {
1666  const char *cp;
1667  const struct lookup *lp;
1668  zic_t i,
1669  j;
1670 
1671  /* PG: make year be int not zic_t to avoid sscanf portability issues */
1672  int year;
1673  int month,
1674  day;
1675  zic_t dayoff,
1676  tod;
1677  zic_t t;
1678  char xs;
1679 
1680  dayoff = 0;
1681  cp = fields[LP_YEAR];
1682  if (sscanf(cp, "%d%c", &year, &xs) != 1)
1683  {
1684  /*
1685  * Leapin' Lizards!
1686  */
1687  error(_("invalid leaping year"));
1688  return -1;
1689  }
1690  if (!expire_line)
1691  {
1692  if (!leapseen || leapmaxyear < year)
1693  leapmaxyear = year;
1694  if (!leapseen || leapminyear > year)
1695  leapminyear = year;
1696  leapseen = true;
1697  }
1698  j = EPOCH_YEAR;
1699  while (j != year)
1700  {
1701  if (year > j)
1702  {
1703  i = len_years[isleap(j)];
1704  ++j;
1705  }
1706  else
1707  {
1708  --j;
1709  i = -len_years[isleap(j)];
1710  }
1711  dayoff = oadd(dayoff, i);
1712  }
1713  if ((lp = byword(fields[LP_MONTH], mon_names)) == NULL)
1714  {
1715  error(_("invalid month name"));
1716  return -1;
1717  }
1718  month = lp->l_value;
1719  j = TM_JANUARY;
1720  while (j != month)
1721  {
1722  i = len_months[isleap(year)][j];
1723  dayoff = oadd(dayoff, i);
1724  ++j;
1725  }
1726  cp = fields[LP_DAY];
1727  if (sscanf(cp, "%d%c", &day, &xs) != 1 ||
1728  day <= 0 || day > len_months[isleap(year)][month])
1729  {
1730  error(_("invalid day of month"));
1731  return -1;
1732  }
1733  dayoff = oadd(dayoff, day - 1);
1734  if (dayoff < min_time / SECSPERDAY)
1735  {
1736  error(_("time too small"));
1737  return -1;
1738  }
1739  if (dayoff > max_time / SECSPERDAY)
1740  {
1741  error(_("time too large"));
1742  return -1;
1743  }
1744  t = dayoff * SECSPERDAY;
1745  tod = gethms(fields[LP_TIME], _("invalid time of day"));
1746  t = tadd(t, tod);
1747  if (t < 0)
1748  error(_("leap second precedes Epoch"));
1749  return t;
1750 }
static zic_t leapmaxyear
Definition: zic.c:180
#define SECSPERDAY
Definition: private.h:108
#define isleap(y)
Definition: datetime.h:271
static const int len_months[2][MONSPERYEAR]
Definition: zic.c:379
const int l_value
Definition: zic.c:304
static zic_t tadd(zic_t t1, zic_t t2)
Definition: zic.c:3770
static zic_t gethms(const char *string, const char *errstring)
Definition: zic.c:1363
static struct lookup const mon_names[]
Definition: zic.c:322
#define LP_DAY
Definition: zic.c:264
static bool leapseen
Definition: zic.c:178
int64 zic_t
Definition: zic.c:25
Definition: zic.c:301
#define EPOCH_YEAR
Definition: private.h:134
#define LP_TIME
Definition: zic.c:265
static zic_t const max_time
Definition: zic.c:584
#define TM_JANUARY
Definition: private.h:119
static struct lookup const * byword(const char *string, const struct lookup *lp)
Definition: zic.c:3649
static zic_t leapminyear
Definition: zic.c:179
#define LP_YEAR
Definition: zic.c:262
int i
static const int len_years[2]
Definition: zic.c:384
static void static void error(const char *string,...) pg_attribute_printf(1
Definition: zic.c:502
static zic_t const min_time
Definition: zic.c:583
#define LP_MONTH
Definition: zic.c:263
#define _(x)
Definition: elog.c:88
static zic_t oadd(zic_t t1, zic_t t2)
Definition: zic.c:3762

◆ getsave()

static zic_t getsave ( char *  field,
bool isdst 
)
static

Definition at line 1441 of file zic.c.

References _, and gethms().

Referenced by associate(), and inrule().

1442 {
1443  int dst = -1;
1444  zic_t save;
1445  size_t fieldlen = strlen(field);
1446 
1447  if (fieldlen != 0)
1448  {
1449  char *ep = field + fieldlen - 1;
1450 
1451  switch (*ep)
1452  {
1453  case 'd':
1454  dst = 1;
1455  *ep = '\0';
1456  break;
1457  case 's':
1458  dst = 0;
1459  *ep = '\0';
1460  break;
1461  }
1462  }
1463  save = gethms(field, _("invalid saved time"));
1464  *isdst = dst < 0 ? save != 0 : dst;
1465  return save;
1466 }
static zic_t gethms(const char *string, const char *errstring)
Definition: zic.c:1363
int64 zic_t
Definition: zic.c:25
#define _(x)
Definition: elog.c:88

◆ growalloc()

static void* growalloc ( void *  ptr,
size_t  itemsize,
ptrdiff_t  nitems,
ptrdiff_t *  nitems_alloc 
)
static

Definition at line 450 of file zic.c.

References _, erealloc(), memory_exhausted(), PTRDIFF_MAX, size_product(), and WORK_AROUND_QTBUG_53071.

Referenced by addtt(), inlink(), inrule(), and inzsub().

451 {
452  if (nitems < *nitems_alloc)
453  return ptr;
454  else
455  {
456  ptrdiff_t nitems_max = PTRDIFF_MAX - WORK_AROUND_QTBUG_53071;
457  ptrdiff_t amax = nitems_max < SIZE_MAX ? nitems_max : SIZE_MAX;
458 
459  if ((amax - 1) / 3 * 2 < *nitems_alloc)
460  memory_exhausted(_("integer overflow"));
461  *nitems_alloc += (*nitems_alloc >> 1) + 1;
462  return erealloc(ptr, size_product(*nitems_alloc, itemsize));
463  }
464 }
static ptrdiff_t const PTRDIFF_MAX
Definition: zic.c:47
static void memory_exhausted(const char *msg) pg_attribute_noreturn()
Definition: zic.c:409
#define _(x)
Definition: elog.c:88
static size_t size_product(size_t nitems, size_t itemsize)
Definition: zic.c:416
static void * erealloc(void *ptr, size_t size)
Definition: zic.c:438

◆ hardlinkerr()

static int hardlinkerr ( char const *  target,
char const *  linkname 
)
static

Definition at line 994 of file zic.c.

References linkat.

Referenced by dolink().

995 {
996  int r = linkat(AT_FDCWD, target, AT_FDCWD, linkname, AT_SYMLINK_FOLLOW);
997 
998  return r == 0 ? 0 : errno;
999 }
#define linkat(targetdir, target, linknamedir, linkname, flag)
Definition: zic.c:116

◆ inexpires()

static void inexpires ( char **  fields,
int  nfields 
)
static

Definition at line 1785 of file zic.c.

References _, error(), EXPIRES_FIELDS, and getleapdatetime().

Referenced by infile().

1786 {
1787  if (nfields != EXPIRES_FIELDS)
1788  error(_("wrong number of fields on Expires line"));
1789  else if (0 <= leapexpires)
1790  error(_("multiple Expires lines"));
1791  else
1792  leapexpires = getleapdatetime(fields, nfields, true);
1793 }
static zic_t getleapdatetime(char **fields, int nfields, bool expire_line)
Definition: zic.c:1664
static zic_t leapexpires
Definition: zic.c:592
#define EXPIRES_FIELDS
Definition: zic.c:271
static void static void error(const char *string,...) pg_attribute_printf(1
Definition: zic.c:502
#define _(x)
Definition: elog.c:88

◆ infile()

static void infile ( const char *  filename)
static

Definition at line 1241 of file zic.c.

References _, buf, byword(), close_file(), eat(), error(), EXIT_FAILURE, fprintf, free, getfields(), inexpires(), inleap(), inlink(), inrule(), inzcont(), inzone(), lookup::l_value, LC_EXPIRES, LC_LEAP, LC_LINK, LC_RULE, LC_ZONE, leap_line_codes, strerror, and zi_line_codes.

Referenced by AlterSystemSetConfigFile(), convert_sourcefiles_in(), isolation_start_test(), main(), psql_start_test(), and readfile().

1242 {
1243  FILE *fp;
1244  char **fields;
1245  char *cp;
1246  const struct lookup *lp;
1247  int nfields;
1248  bool wantcont;
1249  lineno_t num;
1250  char buf[BUFSIZ];
1251 
1252  if (strcmp(name, "-") == 0)
1253  {
1254  name = _("standard input");
1255  fp = stdin;
1256  }
1257  else if ((fp = fopen(name, "r")) == NULL)
1258  {
1259  const char *e = strerror(errno);
1260 
1261  fprintf(stderr, _("%s: Cannot open %s: %s\n"),
1262  progname, name, e);
1263  exit(EXIT_FAILURE);
1264  }
1265  wantcont = false;
1266  for (num = 1;; ++num)
1267  {
1268  eat(name, num);
1269  if (fgets(buf, sizeof buf, fp) != buf)
1270  break;
1271  cp = strchr(buf, '\n');
1272  if (cp == NULL)
1273  {
1274  error(_("line too long"));
1275  exit(EXIT_FAILURE);
1276  }
1277  *cp = '\0';
1278  fields = getfields(buf);
1279  nfields = 0;
1280  while (fields[nfields] != NULL)
1281  {
1282  static char nada;
1283 
1284  if (strcmp(fields[nfields], "-") == 0)
1285  fields[nfields] = &nada;
1286  ++nfields;
1287  }
1288  if (nfields == 0)
1289  {
1290  if (name == leapsec && *buf == '#')
1291  {
1292  /*
1293  * PG: INT64_FORMAT isn't portable for sscanf, so be content
1294  * with scanning a "long". Once we are requiring C99 in all
1295  * live branches, it'd be sensible to adopt upstream's
1296  * practice of using the <inttypes.h> macros. But for now, we
1297  * don't actually use this code, and it won't overflow before
1298  * 2038 anyway.
1299  */
1300  long cl_tmp;
1301 
1302  sscanf(buf, "#expires %ld", &cl_tmp);
1303  comment_leapexpires = cl_tmp;
1304  }
1305  }
1306  else if (wantcont)
1307  {
1308  wantcont = inzcont(fields, nfields);
1309  }
1310  else
1311  {
1312  struct lookup const *line_codes
1314 
1315  lp = byword(fields[0], line_codes);
1316  if (lp == NULL)
1317  error(_("input line of unknown type"));
1318  else
1319  switch (lp->l_value)
1320  {
1321  case LC_RULE:
1322  inrule(fields, nfields);
1323  wantcont = false;
1324  break;
1325  case LC_ZONE:
1326  wantcont = inzone(fields, nfields);
1327  break;
1328  case LC_LINK:
1329  inlink(fields, nfields);
1330  wantcont = false;
1331  break;
1332  case LC_LEAP:
1333  inleap(fields, nfields);
1334  wantcont = false;
1335  break;
1336  case LC_EXPIRES:
1337  inexpires(fields, nfields);
1338  wantcont = false;
1339  break;
1340  default: /* "cannot happen" */
1341  fprintf(stderr,
1342  _("%s: panic: Invalid l_value %d\n"),
1343  progname, lp->l_value);
1344  exit(EXIT_FAILURE);
1345  }
1346  }
1347  free(fields);
1348  }
1349  close_file(fp, NULL, filename);
1350  if (wantcont)
1351  error(_("expected continuation line not found"));
1352 }
static void inexpires(char **, int)
Definition: zic.c:1785
static struct lookup const zi_line_codes[]
Definition: zic.c:310
static struct lookup const leap_line_codes[]
Definition: zic.c:316
static void inrule(char **fields, int nfields)
Definition: zic.c:1469
#define LC_LEAP
Definition: zic.c:203
static const char * leapsec
Definition: zic.c:633
#define fprintf
Definition: port.h:219
const int l_value
Definition: zic.c:304
static const char * filename
Definition: zic.c:176
static void inleap(char **fields, int nfields)
Definition: zic.c:1753
static char ** getfields(char *buf)
Definition: zic.c:3715
static zic_t comment_leapexpires
Definition: zic.c:595
static bool inzcont(char **fields, int nfields)
Definition: zic.c:1554
static char * buf
Definition: pg_test_fsync.c:68
Definition: zic.c:301
#define LC_LINK
Definition: zic.c:202
static void eat(char const *name, lineno_t num)
Definition: zic.c:480
#define LC_ZONE
Definition: zic.c:201
static const char * progname
Definition: zic.c:191
#define free(a)
Definition: header.h:65
static bool inzone(char **fields, int nfields)
Definition: zic.c:1516
#define LC_EXPIRES
Definition: zic.c:204
static void inlink(char **fields, int nfields)
Definition: zic.c:1796
#define strerror
Definition: port.h:228
static void close_file(FILE *stream, char const *dir, char const *name)
Definition: zic.c:525
static struct lookup const * byword(const char *string, const struct lookup *lp)
Definition: zic.c:3649
const char * name
Definition: encode.c:561
e
Definition: preproc-init.c:82
#define EXIT_FAILURE
Definition: settings.h:161
int lineno_t
Definition: zic.c:55
static void static void error(const char *string,...) pg_attribute_printf(1
Definition: zic.c:502
#define LC_RULE
Definition: zic.c:200
#define _(x)
Definition: elog.c:88

◆ inleap()

static void inleap ( char **  fields,
int  nfields 
)
static

Definition at line 1753 of file zic.c.

References _, byword(), error(), getleapdatetime(), lookup::l_value, LEAP_FIELDS, leapadd(), LP_CORR, and LP_ROLL.

Referenced by infile().

1754 {
1755  if (nfields != LEAP_FIELDS)
1756  error(_("wrong number of fields on Leap line"));
1757  else
1758  {
1759  zic_t t = getleapdatetime(fields, nfields, false);
1760 
1761  if (0 <= t)
1762  {
1763  struct lookup const *lp = byword(fields[LP_ROLL], leap_types);
1764 
1765  if (!lp)
1766  error(_("invalid Rolling/Stationary field on Leap line"));
1767  else
1768  {
1769  int correction = 0;
1770 
1771  if (!fields[LP_CORR][0]) /* infile() turns "-" into "". */
1772  correction = -1;
1773  else if (strcmp(fields[LP_CORR], "+") == 0)
1774  correction = 1;
1775  else
1776  error(_("invalid CORRECTION field on Leap line"));
1777  if (correction)
1778  leapadd(t, correction, lp->l_value);
1779  }
1780  }
1781  }
1782 }
#define LP_CORR
Definition: zic.c:266
const int l_value
Definition: zic.c:304
#define LP_ROLL
Definition: zic.c:267
static void leapadd(zic_t, int, int)
Definition: zic.c:3401
#define LEAP_FIELDS
Definition: zic.c:268
int64 zic_t
Definition: zic.c:25
Definition: zic.c:301
static zic_t getleapdatetime(char **fields, int nfields, bool expire_line)
Definition: zic.c:1664
static struct lookup const * byword(const char *string, const struct lookup *lp)
Definition: zic.c:3649
static struct lookup const leap_types[]
Definition: zic.c:373
static void static void error(const char *string,...) pg_attribute_printf(1
Definition: zic.c:502
#define _(x)
Definition: elog.c:88

◆ inlink()

static void inlink ( char **  fields,
int  nfields 
)
static

Definition at line 1796 of file zic.c.

References _, ecpyalloc(), error(), filename, growalloc(), link::l_filename, link::l_linenum, link::l_linkname, link::l_target, LF_LINKNAME, LF_TARGET, linenum, LINK_FIELDS, and namecheck().

Referenced by infile().

1797 {
1798  struct link l;
1799 
1800  if (nfields != LINK_FIELDS)
1801  {
1802  error(_("wrong number of fields on Link line"));
1803  return;
1804  }
1805  if (*fields[LF_TARGET] == '\0')
1806  {
1807  error(_("blank TARGET field on Link line"));
1808  return;
1809  }
1810  if (!namecheck(fields[LF_LINKNAME]))
1811  return;
1812  l.l_filename = filename;
1813  l.l_linenum = linenum;
1814  l.l_target = ecpyalloc(fields[LF_TARGET]);
1815  l.l_linkname = ecpyalloc(fields[LF_LINKNAME]);
1816  links = growalloc(links, sizeof *links, nlinks, &nlinks_alloc);
1817  links[nlinks++] = l;
1818 }
static ptrdiff_t nlinks
Definition: zic.c:298
static char * ecpyalloc(char const *str)
Definition: zic.c:444
static const char * filename
Definition: zic.c:176
static lineno_t linenum
Definition: zic.c:181
#define LF_LINKNAME
Definition: zic.c:255
static void * growalloc(void *ptr, size_t itemsize, ptrdiff_t nitems, ptrdiff_t *nitems_alloc)
Definition: zic.c:450
static ptrdiff_t nlinks_alloc
Definition: zic.c:299
static struct link * links
Definition: zic.c:297
#define LINK_FIELDS
Definition: zic.c:256
#define LF_TARGET
Definition: zic.c:254
static void static void error(const char *string,...) pg_attribute_printf(1
Definition: zic.c:502
#define _(x)
Definition: elog.c:88
static bool namecheck(const char *name)
Definition: zic.c:901

◆ inrule()

static void inrule ( char **  fields,
int  nfields 
)
static

Definition at line 1469 of file zic.c.

References _, ecpyalloc(), error(), filename, getsave(), growalloc(), linenum, rule::r_abbrvar, rule::r_filename, rule::r_isdst, rule::r_linenum, rule::r_name, rule::r_save, RF_ABBRVAR, RF_COMMAND, RF_DAY, RF_HIYEAR, RF_LOYEAR, RF_MONTH, RF_NAME, RF_SAVE, RF_TOD, RULE_FIELDS, and rulesub().

Referenced by infile().

1470 {
1471  static struct rule r;
1472 
1473  if (nfields != RULE_FIELDS)
1474  {
1475  error(_("wrong number of fields on Rule line"));
1476  return;
1477  }
1478  switch (*fields[RF_NAME])
1479  {
1480  case '\0':
1481  case ' ':
1482  case '\f':
1483  case '\n':
1484  case '\r':
1485  case '\t':
1486  case '\v':
1487  case '+':
1488  case '-':
1489  case '0':
1490  case '1':
1491  case '2':
1492  case '3':
1493  case '4':
1494  case '5':
1495  case '6':
1496  case '7':
1497  case '8':
1498  case '9':
1499  error(_("Invalid rule name \"%s\""), fields[RF_NAME]);
1500  return;
1501  }
1502  r.r_filename = filename;
1503  r.r_linenum = linenum;
1504  r.r_save = getsave(fields[RF_SAVE], &r.r_isdst);
1505  rulesub(&r, fields[RF_LOYEAR], fields[RF_HIYEAR], fields[RF_COMMAND],
1506  fields[RF_MONTH], fields[RF_DAY], fields[RF_TOD]);
1507  r.r_name = ecpyalloc(fields[RF_NAME]);
1508  r.r_abbrvar = ecpyalloc(fields[RF_ABBRVAR]);
1509  if (max_abbrvar_len < strlen(r.r_abbrvar))
1510  max_abbrvar_len = strlen(r.r_abbrvar);
1511  rules = growalloc(rules, sizeof *rules, nrules, &nrules_alloc);
1512  rules[nrules++] = r;
1513 }
static char * ecpyalloc(char const *str)
Definition: zic.c:444
#define RF_COMMAND
Definition: zic.c:242
Definition: localtime.c:72
static const char * filename
Definition: zic.c:176
static lineno_t linenum
Definition: zic.c:181
static int max_abbrvar_len
Definition: zic.c:182
static struct rule * rules
Definition: zic.c:281
static void * growalloc(void *ptr, size_t itemsize, ptrdiff_t nitems, ptrdiff_t *nitems_alloc)
Definition: zic.c:450
#define RF_SAVE
Definition: zic.c:246
#define RF_HIYEAR
Definition: zic.c:241
#define RF_NAME
Definition: zic.c:239
static ptrdiff_t nrules_alloc
Definition: zic.c:283
static void rulesub(struct rule *rp, const char *loyearp, const char *hiyearp, const char *typep, const char *monthp, const char *dayp, const char *timep)
Definition: zic.c:1821
static zic_t getsave(char *, bool *)
Definition: zic.c:1441
static ptrdiff_t nrules
Definition: zic.c:282
#define RF_TOD
Definition: zic.c:245
#define RF_ABBRVAR
Definition: zic.c:247
static void static void error(const char *string,...) pg_attribute_printf(1
Definition: zic.c:502
#define RF_LOYEAR
Definition: zic.c:240
#define _(x)
Definition: elog.c:88
#define RULE_FIELDS
Definition: zic.c:248
#define RF_MONTH
Definition: zic.c:243
#define RF_DAY
Definition: zic.c:244

◆ inzcont()

static bool inzcont ( char **  fields,
int  nfields 
)
static

Definition at line 1554 of file zic.c.

References _, error(), inzsub(), and ZONEC_MAXFIELDS.

Referenced by infile().

1555 {
1556  if (nfields < ZONEC_MINFIELDS || nfields > ZONEC_MAXFIELDS)
1557  {
1558  error(_("wrong number of fields on Zone continuation line"));
1559  return false;
1560  }
1561  return inzsub(fields, nfields, true);
1562 }
#define ZONEC_MAXFIELDS
Definition: zic.c:233
static bool inzsub(char **, int, bool)
Definition: zic.c:1565
static void static void error(const char *string,...) pg_attribute_printf(1
Definition: zic.c:502
#define _(x)
Definition: elog.c:88

◆ inzone()

static bool inzone ( char **  fields,
int  nfields 
)
static

Definition at line 1516 of file zic.c.

References _, error(), i, inzsub(), nzones, TZDEFRULES, ZF_NAME, and ZONE_MAXFIELDS.

Referenced by infile().

1517 {
1518  ptrdiff_t i;
1519 
1520  if (nfields < ZONE_MINFIELDS || nfields > ZONE_MAXFIELDS)
1521  {
1522  error(_("wrong number of fields on Zone line"));
1523  return false;
1524  }
1525  if (lcltime != NULL && strcmp(fields[ZF_NAME], tzdefault) == 0)
1526  {
1527  error(
1528  _("\"Zone %s\" line and -l option are mutually exclusive"),
1529  tzdefault);
1530  return false;
1531  }
1532  if (strcmp(fields[ZF_NAME], TZDEFRULES) == 0 && psxrules != NULL)
1533  {
1534  error(
1535  _("\"Zone %s\" line and -p option are mutually exclusive"),
1536  TZDEFRULES);
1537  return false;
1538  }
1539  for (i = 0; i < nzones; ++i)
1540  if (zones[i].z_name != NULL &&
1541  strcmp(zones[i].z_name, fields[ZF_NAME]) == 0)
1542  {
1543  error(_("duplicate zone name %s"
1544  " (file \"%s\", line %d)"),
1545  fields[ZF_NAME],
1546  zones[i].z_filename,
1547  zones[i].z_linenum);
1548  return false;
1549  }
1550  return inzsub(fields, nfields, false);
1551 }
#define ZF_NAME
Definition: zic.c:210
static ptrdiff_t nzones
Definition: zic.c:286
static const char * psxrules
Definition: zic.c:630
static bool inzsub(char **, int, bool)
Definition: zic.c:1565
#define ZONE_MAXFIELDS
Definition: zic.c:219
static const char * lcltime
Definition: zic.c:631
#define TZDEFRULES
Definition: tzfile.h:28
static struct zone * zones
Definition: zic.c:285
int i
static const char * tzdefault
Definition: zic.c:634
static void static void error(const char *string,...) pg_attribute_printf(1
Definition: zic.c:502
#define _(x)
Definition: elog.c:88

◆ inzsub()

static bool inzsub ( char **  fields,
int  nfields,
bool  iscont 
)
static

Definition at line 1565 of file zic.c.

References _, ecpyalloc(), error(), filename, gethms(), growalloc(), linenum, namecheck(), rule::r_filename, rule::r_linenum, rule::r_loyear, rpytime(), rulesub(), warning(), zone::z_filename, zone::z_format, zone::z_format_specifier, zone::z_linenum, zone::z_name, zone::z_rule, zone::z_stdoff, zone::z_untilrule, zone::z_untiltime, ZF_FORMAT, ZF_NAME, ZF_RULE, ZF_STDOFF, ZF_TILDAY, ZF_TILMONTH, ZF_TILTIME, ZF_TILYEAR, ZFC_FORMAT, ZFC_RULE, ZFC_STDOFF, ZFC_TILDAY, ZFC_TILMONTH, ZFC_TILTIME, and ZFC_TILYEAR.

Referenced by inzcont(), and inzone().

1566 {
1567  char *cp;
1568  char *cp1;
1569  static struct zone z;
1570  int i_stdoff,
1571  i_rule,
1572  i_format;
1573  int i_untilyear,
1574  i_untilmonth;
1575  int i_untilday,
1576  i_untiltime;
1577  bool hasuntil;
1578 
1579  if (iscont)
1580  {
1581  i_stdoff = ZFC_STDOFF;
1582  i_rule = ZFC_RULE;
1583  i_format = ZFC_FORMAT;
1584  i_untilyear = ZFC_TILYEAR;
1585  i_untilmonth = ZFC_TILMONTH;
1586  i_untilday = ZFC_TILDAY;
1587  i_untiltime = ZFC_TILTIME;
1588  z.z_name = NULL;
1589  }
1590  else if (!namecheck(fields[ZF_NAME]))
1591  return false;
1592  else
1593  {
1594  i_stdoff = ZF_STDOFF;
1595  i_rule = ZF_RULE;
1596  i_format = ZF_FORMAT;
1597  i_untilyear = ZF_TILYEAR;
1598  i_untilmonth = ZF_TILMONTH;
1599  i_untilday = ZF_TILDAY;
1600  i_untiltime = ZF_TILTIME;
1601  z.z_name = ecpyalloc(fields[ZF_NAME]);
1602  }
1603  z.z_filename = filename;
1604  z.z_linenum = linenum;
1605  z.z_stdoff = gethms(fields[i_stdoff], _("invalid UT offset"));
1606  if ((cp = strchr(fields[i_format], '%')) != NULL)
1607  {
1608  if ((*++cp != 's' && *cp != 'z') || strchr(cp, '%')
1609  || strchr(fields[i_format], '/'))
1610  {
1611  error(_("invalid abbreviation format"));
1612  return false;
1613  }
1614  }
1615  z.z_rule = ecpyalloc(fields[i_rule]);
1616  z.z_format = cp1 = ecpyalloc(fields[i_format]);
1617  z.z_format_specifier = cp ? *cp : '\0';
1618  if (z.z_format_specifier == 'z')
1619  {
1620  if (noise)
1621  warning(_("format '%s' not handled by pre-2015 versions of zic"),
1622  z.z_format);
1623  cp1[cp - fields[i_format]] = 's';
1624  }
1625  if (max_format_len < strlen(z.z_format))
1626  max_format_len = strlen(z.z_format);
1627  hasuntil = nfields > i_untilyear;
1628  if (hasuntil)
1629  {
1630  z.z_untilrule.r_filename = filename;
1631  z.z_untilrule.r_linenum = linenum;
1632  rulesub(&z.z_untilrule,
1633  fields[i_untilyear],
1634  "only",
1635  "",
1636  (nfields > i_untilmonth) ?
1637  fields[i_untilmonth] : "Jan",
1638  (nfields > i_untilday) ? fields[i_untilday] : "1",
1639  (nfields > i_untiltime) ? fields[i_untiltime] : "0");
1640  z.z_untiltime = rpytime(&z.z_untilrule,
1641  z.z_untilrule.r_loyear);
1642  if (iscont && nzones > 0 &&
1643  z.z_untiltime > min_time &&
1644  z.z_untiltime < max_time &&
1645  zones[nzones - 1].z_untiltime > min_time &&
1646  zones[nzones - 1].z_untiltime < max_time &&
1647  zones[nzones - 1].z_untiltime >= z.z_untiltime)
1648  {
1649  error(_("Zone continuation line end time is not after end time of previous line"));
1650  return false;
1651  }
1652  }
1653  zones = growalloc(zones, sizeof *zones, nzones, &nzones_alloc);
1654  zones[nzones++] = z;
1655 
1656  /*
1657  * If there was an UNTIL field on this line, there's more information
1658  * about the zone on the next line.
1659  */
1660  return hasuntil;
1661 }
#define ZF_TILMONTH
Definition: zic.c:215
#define ZF_TILTIME
Definition: zic.c:217
#define ZF_TILYEAR
Definition: zic.c:214
#define ZF_NAME
Definition: zic.c:210
#define ZFC_TILMONTH
Definition: zic.c:229
static char * ecpyalloc(char const *str)
Definition: zic.c:444
#define ZF_RULE
Definition: zic.c:212
static void static void static void warning(const char *string,...) pg_attribute_printf(1
Definition: zic.c:513
#define ZF_STDOFF
Definition: zic.c:211
zic_t z_untiltime
Definition: zic.c:111
static ptrdiff_t nzones
Definition: zic.c:286
#define ZFC_FORMAT
Definition: zic.c:227
static int max_format_len
Definition: zic.c:183
static const char * filename
Definition: zic.c:176
#define ZF_FORMAT
Definition: zic.c:213
#define ZFC_STDOFF
Definition: zic.c:225
static zic_t gethms(const char *string, const char *errstring)
Definition: zic.c:1363
static lineno_t linenum
Definition: zic.c:181
static ptrdiff_t nzones_alloc
Definition: zic.c:287
#define ZFC_TILTIME
Definition: zic.c:231
static void * growalloc(void *ptr, size_t itemsize, ptrdiff_t nitems, ptrdiff_t *nitems_alloc)
Definition: zic.c:450
#define ZFC_RULE
Definition: zic.c:226
static zic_t rpytime(const struct rule *rp, zic_t wantedy)
Definition: zic.c:3799
#define ZF_TILDAY
Definition: zic.c:216
static zic_t const max_time
Definition: zic.c:584
static bool noise
Definition: zic.c:186
static void rulesub(struct rule *rp, const char *loyearp, const char *hiyearp, const char *typep, const char *monthp, const char *dayp, const char *timep)
Definition: zic.c:1821
static struct zone * zones
Definition: zic.c:285
Definition: zic.c:93
#define ZFC_TILDAY
Definition: zic.c:230
static void static void error(const char *string,...) pg_attribute_printf(1
Definition: zic.c:502
static zic_t const min_time
Definition: zic.c:583
#define ZFC_TILYEAR
Definition: zic.c:228
#define _(x)
Definition: elog.c:88
static bool namecheck(const char *name)
Definition: zic.c:901

◆ is_alpha()

static bool is_alpha ( char  a)
static

Definition at line 3484 of file zic.c.

Referenced by doabbr(), and newabbr().

3485 {
3486  switch (a)
3487  {
3488  default:
3489  return false;
3490  case 'A':
3491  case 'B':
3492  case 'C':
3493  case 'D':
3494  case 'E':
3495  case 'F':
3496  case 'G':
3497  case 'H':
3498  case 'I':
3499  case 'J':
3500  case 'K':
3501  case 'L':
3502  case 'M':
3503  case 'N':
3504  case 'O':
3505  case 'P':
3506  case 'Q':
3507  case 'R':
3508  case 'S':
3509  case 'T':
3510  case 'U':
3511  case 'V':
3512  case 'W':
3513  case 'X':
3514  case 'Y':
3515  case 'Z':
3516  case 'a':
3517  case 'b':
3518  case 'c':
3519  case 'd':
3520  case 'e':
3521  case 'f':
3522  case 'g':
3523  case 'h':
3524  case 'i':
3525  case 'j':
3526  case 'k':
3527  case 'l':
3528  case 'm':
3529  case 'n':
3530  case 'o':
3531  case 'p':
3532  case 'q':
3533  case 'r':
3534  case 's':
3535  case 't':
3536  case 'u':
3537  case 'v':
3538  case 'w':
3539  case 'x':
3540  case 'y':
3541  case 'z':
3542  return true;
3543  }
3544 }

◆ is_space()

static bool is_space ( char  a)
static

Definition at line 3466 of file zic.c.

Referenced by getfields().

3467 {
3468  switch (a)
3469  {
3470  default:
3471  return false;
3472  case ' ':
3473  case '\f':
3474  case '\n':
3475  case '\r':
3476  case '\t':
3477  case '\v':
3478  return true;
3479  }
3480 }

◆ itsabbr()

static bool itsabbr ( const char *  abbr,
const char *  word 
)
static

Definition at line 3621 of file zic.c.

References lowerit(), and word().

Referenced by byword().

3622 {
3623  if (lowerit(*abbr) != lowerit(*word))
3624  return false;
3625  ++word;
3626  while (*++abbr != '\0')
3627  do
3628  {
3629  if (*word == '\0')
3630  return false;
3631  } while (lowerit(*word++) != lowerit(*abbr));
3632  return true;
3633 }
static char lowerit(char)
Definition: zic.c:3549
static void word(struct vars *, int, struct state *, struct state *)
Definition: regcomp.c:1246

◆ itsdir()

static bool itsdir ( char const *  name)
static

Definition at line 1104 of file zic.c.

References emalloc(), EOVERFLOW, free, S_ISDIR, stat::st_mode, and stat.

Referenced by dolink(), and mkdirs().

1105 {
1106  struct stat st;
1107  int res = stat(name, &st);
1108 #ifdef S_ISDIR
1109  if (res == 0)
1110  return S_ISDIR(st.st_mode) != 0;
1111 #endif
1112  if (res == 0 || errno == EOVERFLOW)
1113  {
1114  size_t n = strlen(name);
1115  char *nameslashdot = emalloc(n + 3);
1116  bool dir;
1117 
1118  memcpy(nameslashdot, name, n);
1119  strcpy(&nameslashdot[n], &"/."[!(n && name[n - 1] != '/')]);
1120  dir = stat(nameslashdot, &st) == 0 || errno == EOVERFLOW;
1121  free(nameslashdot);
1122  return dir;
1123  }
1124  return false;
1125 }
#define free(a)
Definition: header.h:65
const char * name
Definition: encode.c:561
#define S_ISDIR(m)
Definition: win32_port.h:316
#define EOVERFLOW
Definition: private.h:41
#define stat
Definition: win32_port.h:275
static void * emalloc(size_t size)
Definition: zic.c:432

◆ itssymlink()

static bool itssymlink ( char const *  name)
static

Definition at line 1129 of file zic.c.

References readlink.

Referenced by dolink().

1130 {
1131 #ifdef HAVE_SYMLINK
1132  char c;
1133 
1134  return 0 <= readlink(name, &c, 1);
1135 #else
1136  return false;
1137 #endif
1138 }
char * c
#define readlink(path, buf, size)
Definition: win32_port.h:228
const char * name
Definition: encode.c:561

◆ leapadd()

static void leapadd ( zic_t  t,
int  correction,
int  rolling 
)
static

Definition at line 3401 of file zic.c.

References _, error(), EXIT_FAILURE, i, leapcnt, and TZ_MAX_LEAPS.

Referenced by inleap().

3402 {
3403  int i;
3404 
3405  if (TZ_MAX_LEAPS <= leapcnt)
3406  {
3407  error(_("too many leap seconds"));
3408  exit(EXIT_FAILURE);
3409  }
3410  for (i = 0; i < leapcnt; ++i)
3411  if (t <= trans[i])
3412  break;
3413  memmove(&trans[i + 1], &trans[i], (leapcnt - i) * sizeof *trans);
3414  memmove(&corr[i + 1], &corr[i], (leapcnt - i) * sizeof *corr);
3415  memmove(&roll[i + 1], &roll[i], (leapcnt - i) * sizeof *roll);
3416  trans[i] = t;
3417  corr[i] = correction;
3418  roll[i] = rolling;
3419  ++leapcnt;
3420 }
static zic_t corr[TZ_MAX_LEAPS]
Definition: zic.c:401
#define TZ_MAX_LEAPS
Definition: tzfile.h:108
static int leapcnt
Definition: zic.c:177
static zic_t trans[TZ_MAX_LEAPS]
Definition: zic.c:400
int i
#define EXIT_FAILURE
Definition: settings.h:161
static void static void error(const char *string,...) pg_attribute_printf(1
Definition: zic.c:502
#define _(x)
Definition: elog.c:88
static char roll[TZ_MAX_LEAPS]
Definition: zic.c:402

◆ limitrange()

static struct timerange limitrange ( struct timerange  r,
zic_t  lo,
zic_t  hi,
zic_t const *  ats,
unsigned char const *  types 
)
static

Definition at line 2053 of file zic.c.

References timerange::defaulttype, types, and ZIC_MAX.

Referenced by writezone().

2055 {
2056  while (0 < r.count && ats[r.base] < lo)
2057  {
2058  r.defaulttype = types[r.base];
2059  r.count--;
2060  r.base++;
2061  }
2062  while (0 < r.leapcount && trans[r.leapbase] < lo)
2063  {
2064  r.leapcount--;
2065  r.leapbase++;
2066  }
2067 
2068  if (hi < ZIC_MAX)
2069  {
2070  while (0 < r.count && hi + 1 < ats[r.base + r.count - 1])
2071  r.count--;
2072  while (0 < r.leapcount && hi + 1 < trans[r.leapbase + r.leapcount - 1])
2073  r.leapcount--;
2074  }
2075 
2076  return r;
2077 }
struct typedefs * types
Definition: ecpg.c:29
ptrdiff_t count
Definition: zic.c:2046
int leapbase
Definition: zic.c:2048
#define ZIC_MAX
Definition: zic.c:27
int defaulttype
Definition: zic.c:2045
int leapcount
Definition: zic.c:2048
ptrdiff_t base
Definition: zic.c:2046
static zic_t trans[TZ_MAX_LEAPS]
Definition: zic.c:400

◆ link()

int link ( const char *  target,
const char *  linkname 
)

Referenced by mkdirs().

◆ lowerit()

static char lowerit ( char  a)
static

Definition at line 3549 of file zic.c.

Referenced by ciequal(), ciprefix(), itsabbr(), and rulesub().

3550 {
3551  switch (a)
3552  {
3553  default:
3554  return a;
3555  case 'A':
3556  return 'a';
3557  case 'B':
3558  return 'b';
3559  case 'C':
3560  return 'c';
3561  case 'D':
3562  return 'd';
3563  case 'E':
3564  return 'e';
3565  case 'F':
3566  return 'f';
3567  case 'G':
3568  return 'g';
3569  case 'H':
3570  return 'h';
3571  case 'I':
3572  return 'i';
3573  case 'J':
3574  return 'j';
3575  case 'K':
3576  return 'k';
3577  case 'L':
3578  return 'l';
3579  case 'M':
3580  return 'm';
3581  case 'N':
3582  return 'n';
3583  case 'O':
3584  return 'o';
3585  case 'P':
3586  return 'p';
3587  case 'Q':
3588  return 'q';
3589  case 'R':
3590  return 'r';
3591  case 'S':
3592  return 's';
3593  case 'T':
3594  return 't';
3595  case 'U':
3596  return 'u';
3597  case 'V':
3598  return 'v';
3599  case 'W':
3600  return 'w';
3601  case 'X':
3602  return 'x';
3603  case 'Y':
3604  return 'y';
3605  case 'Z':
3606  return 'z';
3607  }
3608 }

◆ main()

int main ( int  argc,
char **  argv 
)

Definition at line 652 of file zic.c.

References _, adjleap(), associate(), change_directory(), close_file(), dolink(), eat(), error(), EXIT_FAILURE, EXIT_SUCCESS, fprintf, getopt(), i, infile(), nlinks, nzones, optarg, optind, outzone(), printf, S_IWGRP, S_IWOTH, generate_unaccent_rules::stdout, timerange_option(), TYPE_BIT, TZDEFAULT, TZDEFRULES, usage(), warning(), zone::z_name, and ZIC_BLOAT_DEFAULT.

653 {
654  int c,
655  k;
656  ptrdiff_t i,
657  j;
658  bool timerange_given = false;
659 
660 #ifndef WIN32
661  umask(umask(S_IWGRP | S_IWOTH) | (S_IWGRP | S_IWOTH));
662 #endif
663  progname = argv[0];
664  if (TYPE_BIT(zic_t) < 64)
665  {
666  fprintf(stderr, "%s: %s\n", progname,
667  _("wild compilation-time specification of zic_t"));
668  return EXIT_FAILURE;
669  }
670  for (k = 1; k < argc; k++)
671  if (strcmp(argv[k], "--version") == 0)
672  {
673  printf("zic %s\n", PG_VERSION);
674  close_file(stdout, NULL, NULL);
675  return EXIT_SUCCESS;
676  }
677  else if (strcmp(argv[k], "--help") == 0)
678  {
680  }
681  while ((c = getopt(argc, argv, "b:d:l:L:p:Pr:st:vy:")) != EOF && c != -1)
682  switch (c)
683  {
684  default:
685  usage(stderr, EXIT_FAILURE);
686  case 'b':
687  if (strcmp(optarg, "slim") == 0)
688  {
689  if (0 < bloat)
690  error(_("incompatible -b options"));
691  bloat = -1;
692  }
693  else if (strcmp(optarg, "fat") == 0)
694  {
695  if (bloat < 0)
696  error(_("incompatible -b options"));
697  bloat = 1;
698  }
699  else
700  error(_("invalid option: -b '%s'"), optarg);
701  break;
702  case 'd':
703  if (directory == NULL)
704  directory = strdup(optarg);
705  else
706  {
707  fprintf(stderr,
708  _("%s: More than one -d option specified\n"),
709  progname);
710  return EXIT_FAILURE;
711  }
712  break;
713  case 'l':
714  if (lcltime == NULL)
715  lcltime = strdup(optarg);
716  else
717  {
718  fprintf(stderr,
719  _("%s: More than one -l option specified\n"),
720  progname);
721  return EXIT_FAILURE;
722  }
723  break;
724  case 'p':
725  if (psxrules == NULL)
726  psxrules = strdup(optarg);
727  else
728  {
729  fprintf(stderr,
730  _("%s: More than one -p option specified\n"),
731  progname);
732  return EXIT_FAILURE;
733  }
734  break;
735  case 't':
736  if (tzdefault != NULL)
737  {
738  fprintf(stderr,
739  _("%s: More than one -t option"
740  " specified\n"),
741  progname);
742  return EXIT_FAILURE;
743  }
744  tzdefault = optarg;
745  break;
746  case 'y':
747  warning(_("-y ignored"));
748  break;
749  case 'L':
750  if (leapsec == NULL)
751  leapsec = strdup(optarg);
752  else
753  {
754  fprintf(stderr,
755  _("%s: More than one -L option specified\n"),
756  progname);
757  return EXIT_FAILURE;
758  }
759  break;
760  case 'v':
761  noise = true;
762  break;
763  case 'P':
764  print_abbrevs = true;
765  print_cutoff = time(NULL);
766  break;
767  case 'r':
768  if (timerange_given)
769  {
770  fprintf(stderr,
771  _("%s: More than one -r option specified\n"),
772  progname);
773  return EXIT_FAILURE;
774  }
775  if (!timerange_option(optarg))
776  {
777  fprintf(stderr,
778  _("%s: invalid time range: %s\n"),
779  progname, optarg);
780  return EXIT_FAILURE;
781  }
782  timerange_given = true;
783  break;
784  case 's':
785  warning(_("-s ignored"));
786  break;
787  }
788  if (optind == argc - 1 && strcmp(argv[optind], "=") == 0)
789  usage(stderr, EXIT_FAILURE); /* usage message by request */
790  if (bloat == 0)
791  {
792  static char const bloat_default[] = ZIC_BLOAT_DEFAULT;
793 
794  if (strcmp(bloat_default, "slim") == 0)
795  bloat = -1;
796  else if (strcmp(bloat_default, "fat") == 0)
797  bloat = 1;
798  else
799  abort(); /* Configuration error. */
800  }
801  if (directory == NULL)
802  directory = "data";
803  if (tzdefault == NULL)
805 
806  if (optind < argc && leapsec != NULL)
807  {
808  infile(leapsec);
809  adjleap();
810  }
811 
812  for (k = optind; k < argc; k++)
813  infile(argv[k]);
814  if (errors)
815  return EXIT_FAILURE;
816  associate();
818  for (i = 0; i < nzones; i = j)
819  {
820  /*
821  * Find the next non-continuation zone entry.
822  */
823  for (j = i + 1; j < nzones && zones[j].z_name == NULL; ++j)
824  continue;
825  outzone(&zones[i], j - i);
826  }
827 
828  /*
829  * Make links.
830  */
831  for (i = 0; i < nlinks; ++i)
832  {
833  eat(links[i].l_filename, links[i].l_linenum);
834  dolink(links[i].l_target, links[i].l_linkname, false);
835  if (noise)
836  for (j = 0; j < nlinks; ++j)
837  if (strcmp(links[i].l_linkname,
838  links[j].l_target) == 0)
839  warning(_("link to link"));
840  }
841  if (lcltime != NULL)
842  {
843  eat(_("command line"), 1);
844  dolink(lcltime, tzdefault, true);
845  }
846  if (psxrules != NULL)
847  {
848  eat(_("command line"), 1);
849  dolink(psxrules, TZDEFRULES, true);
850  }
851  if (warnings && (ferror(stderr) || fclose(stderr) != 0))
852  return EXIT_FAILURE;
853  return errors ? EXIT_FAILURE : EXIT_SUCCESS;
854 }
#define TZDEFAULT
Definition: tzfile.h:27
static ptrdiff_t nlinks
Definition: zic.c:298
static bool print_abbrevs
Definition: zic.c:187
static zic_t print_cutoff
Definition: zic.c:188
static void change_directory(char const *dir)
Definition: zic.c:560
#define EXIT_SUCCESS
Definition: settings.h:157
static int bloat
Definition: zic.c:639
static void static void static void warning(const char *string,...) pg_attribute_printf(1
Definition: zic.c:513
static bool errors
Definition: zic.c:174
static void associate(void)
Definition: zic.c:1156
#define S_IWOTH
Definition: win32_port.h:307
#define printf(...)
Definition: port.h:221
#define ZIC_BLOAT_DEFAULT
Definition: zic.c:648
static ptrdiff_t nzones
Definition: zic.c:286
static bool warnings
Definition: zic.c:175
static const char * leapsec
Definition: zic.c:633
#define fprintf
Definition: port.h:219
int getopt(int nargc, char *const *nargv, const char *ostr)
Definition: getopt.c:71
static const char * psxrules
Definition: zic.c:630
static void static void static void static void usage(FILE *stream, int status) pg_attribute_noreturn()
Definition: zic.c:541
static void dolink(const char *, const char *, bool)
Definition: zic.c:1002
int optind
Definition: getopt.c:50
char * c
static void adjleap(void)
Definition: zic.c:3423
static const char * lcltime
Definition: zic.c:631
int64 zic_t
Definition: zic.c:25
#define S_IWGRP
Definition: win32_port.h:295
static void eat(char const *name, lineno_t num)
Definition: zic.c:480
static bool noise
Definition: zic.c:186
static struct link * links
Definition: zic.c:297
static void infile(const char *filename)
Definition: zic.c:1241
static const char * progname
Definition: zic.c:191
#define TZDEFRULES
Definition: tzfile.h:28
static const char * directory
Definition: zic.c:632
const char * z_name
Definition: zic.c:98
static void close_file(FILE *stream, char const *dir, char const *name)
Definition: zic.c:525
static struct zone * zones
Definition: zic.c:285
static void outzone(const struct zone *zp, ptrdiff_t ntzones)
Definition: zic.c:2944
char * optarg
Definition: getopt.c:52
#define TYPE_BIT(type)
Definition: private.h:60
int i
#define EXIT_FAILURE
Definition: settings.h:161
static const char * tzdefault
Definition: zic.c:634
static bool timerange_option(char *timerange)
Definition: zic.c:600
static void static void error(const char *string,...) pg_attribute_printf(1
Definition: zic.c:502
#define _(x)
Definition: elog.c:88

◆ memcheck()

static void* memcheck ( void *  ptr)
static

Definition at line 424 of file zic.c.

References memory_exhausted(), and strerror.

Referenced by ecpyalloc(), emalloc(), and erealloc().

425 {
426  if (ptr == NULL)
427  memory_exhausted(strerror(errno));
428  return ptr;
429 }
#define strerror
Definition: port.h:228
static void memory_exhausted(const char *msg) pg_attribute_noreturn()
Definition: zic.c:409

◆ memory_exhausted()

static void memory_exhausted ( const char *  msg)
static

Definition at line 409 of file zic.c.

References _, EXIT_FAILURE, and fprintf.

Referenced by growalloc(), memcheck(), and size_product().

410 {
411  fprintf(stderr, _("%s: Memory exhausted: %s\n"), progname, msg);
412  exit(EXIT_FAILURE);
413 }
#define fprintf
Definition: port.h:219
static const char * progname
Definition: zic.c:191
#define EXIT_FAILURE
Definition: settings.h:161
#define _(x)
Definition: elog.c:88

◆ mkdirs()

static void mkdirs ( char const *  argname,
bool  ancestors 
)
static

Definition at line 3946 of file zic.c.

References _, _dosmaperr(), ecpyalloc(), error(), EXIT_FAILURE, free, itsdir(), link(), mkdir, MKDIR_UMASK, name, and strerror.

Referenced by change_directory(), dolink(), and writezone().

3947 {
3948  char *name;
3949  char *cp;
3950 
3951  cp = name = ecpyalloc(argname);
3952 
3953  /*
3954  * On MS-Windows systems, do not worry about drive letters or backslashes,
3955  * as this should suffice in practice. Time zone names do not use drive
3956  * letters and backslashes. If the -d option of zic does not name an
3957  * already-existing directory, it can use slashes to separate the
3958  * already-existing ancestor prefix from the to-be-created subdirectories.
3959  */
3960 
3961  /* Do not mkdir a root directory, as it must exist. */
3962  while (*cp == '/')
3963  cp++;
3964 
3965  while (cp && ((cp = strchr(cp, '/')) || !ancestors))
3966  {
3967  if (cp)
3968  *cp = '\0';
3969 
3970  /*
3971  * Try to create it. It's OK if creation fails because the directory
3972  * already exists, perhaps because some other process just created it.
3973  * For simplicity do not check first whether it already exists, as
3974  * that is checked anyway if the mkdir fails.
3975  */
3976  if (mkdir(name, MKDIR_UMASK) != 0)
3977  {
3978  /*
3979  * For speed, skip itsdir if errno == EEXIST. Since mkdirs is
3980  * called only after open fails with ENOENT on a subfile, EEXIST
3981  * implies itsdir here.
3982  */
3983  int err = errno;
3984 
3985  if (err != EEXIST && !itsdir(name))
3986  {
3987  error(_("%s: Cannot create directory %s: %s"),
3988  progname, name, strerror(err));
3989  exit(EXIT_FAILURE);
3990  }
3991  }
3992  if (cp)
3993  *cp++ = '/';
3994  }
3995  free(name);
3996 }
static char * ecpyalloc(char const *str)
Definition: zic.c:444
static bool itsdir(char const *)
Definition: zic.c:1104
static const char * progname
Definition: zic.c:191
#define free(a)
Definition: header.h:65
#define MKDIR_UMASK
Definition: zic.c:37
#define strerror
Definition: port.h:228
const char * name
Definition: encode.c:561
#define EXIT_FAILURE
Definition: settings.h:161
#define mkdir(a, b)
Definition: win32_port.h:63
static void static void error(const char *string,...) pg_attribute_printf(1
Definition: zic.c:502
#define _(x)
Definition: elog.c:88

◆ namecheck()

static bool namecheck ( const char *  name)
static

Definition at line 901 of file zic.c.

References _, componentcheck(), emalloc(), i, name, relname, and warning().

Referenced by inlink(), and inzsub().

902 {
903  char const *cp;
904 
905  /* Benign characters in a portable file name. */
906  static char const benign[] =
907  "-/_"
908  "abcdefghijklmnopqrstuvwxyz"
909  "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
910 
911  /*
912  * Non-control chars in the POSIX portable character set, excluding the
913  * benign characters.
914  */
915  static char const printable_and_not_benign[] =
916  " !\"#$%&'()*+,.0123456789:;<=>?@[\\]^`{|}~";
917 
918  char const *component = name;
919 
920  for (cp = name; *cp; cp++)
921  {
922  unsigned char c = *cp;
923 
924  if (noise && !strchr(benign, c))
925  {
926  warning((strchr(printable_and_not_benign, c)
927  ? _("file name '%s' contains byte '%c'")
928  : _("file name '%s' contains byte '\\%o'")),
929  name, c);
930  }
931  if (c == '/')
932  {
933  if (!componentcheck(name, component, cp))
934  return false;
935  component = cp + 1;
936  }
937  }
938  return componentcheck(name, component, cp);
939 }
static void static void static void warning(const char *string,...) pg_attribute_printf(1
Definition: zic.c:513
static bool componentcheck(char const *name, char const *component, char const *component_end)
Definition: zic.c:857
char * c
static bool noise
Definition: zic.c:186
const char * name
Definition: encode.c:561
#define _(x)
Definition: elog.c:88

◆ newabbr()

static void newabbr ( const char *  abbr)
static

Definition at line 3908 of file zic.c.

References _, error(), EXIT_FAILURE, GRANDPARENTED, i, is_alpha(), TZ_MAX_CHARS, warning(), and ZIC_MAX_ABBR_LEN_WO_WARN.

Referenced by addtype().

3909 {
3910  int i;
3911 
3912  if (strcmp(string, GRANDPARENTED) != 0)
3913  {
3914  const char *cp;
3915  const char *mp;
3916 
3917  cp = string;
3918  mp = NULL;
3919  while (is_alpha(*cp) || ('0' <= *cp && *cp <= '9')
3920  || *cp == '-' || *cp == '+')
3921  ++cp;
3922  if (noise && cp - string < 3)
3923  mp = _("time zone abbreviation has fewer than 3 characters");
3924  if (cp - string > ZIC_MAX_ABBR_LEN_WO_WARN)
3925  mp = _("time zone abbreviation has too many characters");
3926  if (*cp != '\0')
3927  mp = _("time zone abbreviation differs from POSIX standard");
3928  if (mp != NULL)
3929  warning("%s (%s)", mp, string);
3930  }
3931  i = strlen(string) + 1;
3932  if (charcnt + i > TZ_MAX_CHARS)
3933  {
3934  error(_("too many, or too long, time zone abbreviations"));
3935  exit(EXIT_FAILURE);
3936  }
3937  strcpy(&chars[charcnt], string);
3938  charcnt += i;
3939 }
static void static void static void warning(const char *string,...) pg_attribute_printf(1
Definition: zic.c:513
#define GRANDPARENTED
Definition: private.h:30
static bool is_alpha(char a)
Definition: zic.c:3484
char string[11]
Definition: preproc-type.c:46
#define ZIC_MAX_ABBR_LEN_WO_WARN
Definition: zic.c:30
#define TZ_MAX_CHARS
Definition: tzfile.h:105
static bool noise
Definition: zic.c:186
static int charcnt
Definition: zic.c:173
int i
#define EXIT_FAILURE
Definition: settings.h:161
static void static void error(const char *string,...) pg_attribute_printf(1
Definition: zic.c:502
static char chars[TZ_MAX_CHARS]
Definition: zic.c:399
#define _(x)
Definition: elog.c:88

◆ oadd()

static zic_t oadd ( zic_t  t1,
zic_t  t2 
)
static

Definition at line 3762 of file zic.c.

References time_overflow(), ZIC_MAX, and ZIC_MIN.

Referenced by adjleap(), gethms(), getleapdatetime(), outzone(), and rpytime().

3763 {
3764  if (t1 < 0 ? t2 < ZIC_MIN - t1 : ZIC_MAX - t1 < t2)
3765  time_overflow();
3766  return t1 + t2;
3767 }
#define ZIC_MAX
Definition: zic.c:27
#define ZIC_MIN
Definition: zic.c:26
static void time_overflow(void)
Definition: zic.c:3755

◆ outzone()

static void outzone ( const struct zone zp,
ptrdiff_t  ntzones 
)
static

Definition at line 2944 of file zic.c.

References _, addtt(), addtype(), attype::at, attypes, compat, DC_DOM, doabbr(), attype::dontmerge, eat(), eats(), emalloc(), EPOCH_YEAR, error(), free, i, INITIALIZE, max_abbrvar_len, max_year, oadd(), rule::r_abbrvar, rule::r_dayofmonth, rule::r_dycode, rule::r_filename, rule::r_hiwasnum, rule::r_hiyear, rule::r_isdst, rule::r_linenum, rule::r_lowasnum, rule::r_loyear, rule::r_month, rule::r_save, rule::r_temp, rule::r_tod, rule::r_todisstd, rule::r_todisut, rule::r_todo, rpytime(), stringzone(), tadd(), timecnt, TM_JANUARY, generate_unaccent_rules::type, attype::type, updateminmax(), want_bloat(), warning(), writezone(), YEARSPERREPEAT, zone::z_filename, zone::z_format, zone::z_isdst, zone::z_linenum, zone::z_name, zone::z_nrules, zone::z_rules, zone::z_save, zone::z_stdoff, zone::z_untilrule, zone::z_untiltime, ZIC_MAX, ZIC_MIN, ZIC_VERSION, and ZIC_VERSION_PRE_2013.

Referenced by main().

2945 {
2946  const struct zone *zp;
2947  struct rule *rp;
2948  ptrdiff_t i,
2949  j;
2950  bool usestart,
2951  useuntil;
2952  zic_t starttime,
2953  untiltime;
2954  zic_t stdoff;
2955  zic_t save;
2956  zic_t year;
2957  zic_t startoff;
2958  bool startttisstd;
2959  bool startttisut;
2960  int type;
2961  char *startbuf;
2962  char *ab;
2963  char *envvar;
2964  int max_abbr_len;
2965  int max_envvar_len;
2966  bool prodstic; /* all rules are min to max */
2967  int compat;
2968  bool do_extend;
2969  char version;
2970  ptrdiff_t lastatmax = -1;
2971  zic_t one = 1;
2972  zic_t y2038_boundary = one << 31;
2973  zic_t max_year0;
2974  int defaulttype = -1;
2975 
2976  max_abbr_len = 2 + max_format_len + max_abbrvar_len;
2977  max_envvar_len = 2 * max_abbr_len + 5 * 9;
2978  startbuf = emalloc(max_abbr_len + 1);
2979  ab = emalloc(max_abbr_len + 1);
2980  envvar = emalloc(max_envvar_len + 1);
2981  INITIALIZE(untiltime);
2982  INITIALIZE(starttime);
2983 
2984  /*
2985  * Now. . .finally. . .generate some useful data!
2986  */
2987  timecnt = 0;
2988  typecnt = 0;
2989  charcnt = 0;
2990  prodstic = zonecount == 1;
2991 
2992  /*
2993  * Thanks to Earl Chew for noting the need to unconditionally initialize
2994  * startttisstd.
2995  */
2996  startttisstd = false;
2997  startttisut = false;
2999  if (leapseen)
3000  {
3003  }
3004  for (i = 0; i < zonecount; ++i)
3005  {
3006  zp = &zpfirst[i];
3007  if (i < zonecount - 1)
3009  for (j = 0; j < zp->z_nrules; ++j)
3010  {
3011  rp = &zp->z_rules[j];
3012  if (rp->r_lowasnum)
3013  updateminmax(rp->r_loyear);
3014  if (rp->r_hiwasnum)
3015  updateminmax(rp->r_hiyear);
3016  if (rp->r_lowasnum || rp->r_hiwasnum)
3017  prodstic = false;
3018  }
3019  }
3020 
3021  /*
3022  * Generate lots of data if a rule can't cover all future times.
3023  */
3024  compat = stringzone(envvar, zpfirst, zonecount);
3025  version = compat < 2013 ? ZIC_VERSION_PRE_2013 : ZIC_VERSION;
3026  do_extend = compat < 0;
3027  if (noise)
3028  {
3029  if (!*envvar)
3030  warning("%s %s",
3031  _("no POSIX environment variable for zone"),
3032  zpfirst->z_name);
3033  else if (compat != 0)
3034  {
3035  /*
3036  * Circa-COMPAT clients, and earlier clients, might not work for
3037  * this zone when given dates before 1970 or after 2038.
3038  */
3039  warning(_("%s: pre-%d clients may mishandle"
3040  " distant timestamps"),
3041  zpfirst->z_name, compat);
3042  }
3043  }
3044  if (do_extend)
3045  {
3046  /*
3047  * Search through a couple of extra years past the obvious 400, to
3048  * avoid edge cases. For example, suppose a non-POSIX rule applies
3049  * from 2012 onwards and has transitions in March and September, plus
3050  * some one-off transitions in November 2013. If zic looked only at
3051  * the last 400 years, it would set max_year=2413, with the intent
3052  * that the 400 years 2014 through 2413 will be repeated. The last
3053  * transition listed in the tzfile would be in 2413-09, less than 400
3054  * years after the last one-off transition in 2013-11. Two years
3055  * might be overkill, but with the kind of edge cases available we're
3056  * not sure that one year would suffice.
3057  */
3058  enum
3059  {
3060  years_of_observations = YEARSPERREPEAT + 2};
3061 
3062  if (min_year >= ZIC_MIN + years_of_observations)
3063  min_year -= years_of_observations;
3064  else
3065  min_year = ZIC_MIN;
3066  if (max_year <= ZIC_MAX - years_of_observations)
3067  max_year += years_of_observations;
3068  else
3069  max_year = ZIC_MAX;
3070 
3071  /*
3072  * Regardless of any of the above, for a "proDSTic" zone which
3073  * specifies that its rules always have and always will be in effect,
3074  * we only need one cycle to define the zone.
3075  */
3076  if (prodstic)
3077  {
3078  min_year = 1900;
3079  max_year = min_year + years_of_observations;
3080  }
3081  }
3082  max_year0 = max_year;
3083  if (want_bloat())
3084  {
3085  /*
3086  * For the benefit of older systems, generate data from 1900 through
3087  * 2038.
3088  */
3089  if (min_year > 1900)
3090  min_year = 1900;
3091  if (max_year < 2038)
3092  max_year = 2038;
3093  }
3094 
3095  for (i = 0; i < zonecount; ++i)
3096  {
3097  struct rule *prevrp = NULL;
3098 
3099  /*
3100  * A guess that may well be corrected later.
3101  */
3102  save = 0;
3103  zp = &zpfirst[i];
3104  usestart = i > 0 && (zp - 1)->z_untiltime > min_time;
3105  useuntil = i < (zonecount - 1);
3106  if (useuntil && zp->z_untiltime <= min_time)
3107  continue;
3108  stdoff = zp->z_stdoff;
3109  eat(zp->z_filename, zp->z_linenum);
3110  *startbuf = '\0';
3111  startoff = zp->z_stdoff;
3112  if (zp->z_nrules == 0)
3113  {
3114  save = zp->z_save;
3115  doabbr(startbuf, zp, NULL, zp->z_isdst, save, false);
3116  type = addtype(oadd(zp->z_stdoff, save),
3117  startbuf, zp->z_isdst, startttisstd,
3118  startttisut);
3119  if (usestart)
3120  {
3121  addtt(starttime, type);
3122  usestart = false;
3123  }
3124  else
3125  defaulttype = type;
3126  }
3127  else
3128  for (year = min_year; year <= max_year; ++year)
3129  {
3130  if (useuntil && year > zp->z_untilrule.r_hiyear)
3131  break;
3132 
3133  /*
3134  * Mark which rules to do in the current year. For those to
3135  * do, calculate rpytime(rp, year); The former TYPE field was
3136  * also considered here.
3137  */
3138  for (j = 0; j < zp->z_nrules; ++j)
3139  {
3140  rp = &zp->z_rules[j];
3141  eats(zp->z_filename, zp->z_linenum,
3142  rp->r_filename, rp->r_linenum);
3143  rp->r_todo = year >= rp->r_loyear &&
3144  year <= rp->r_hiyear;
3145  if (rp->r_todo)
3146  {
3147  rp->r_temp = rpytime(rp, year);
3148  rp->r_todo
3149  = (rp->r_temp < y2038_boundary
3150  || year <= max_year0);
3151  }
3152  }
3153  for (;;)
3154  {
3155  ptrdiff_t k;
3156  zic_t jtime,
3157  ktime;
3158  zic_t offset;
3159 
3160  INITIALIZE(ktime);
3161  if (useuntil)
3162  {
3163  /*
3164  * Turn untiltime into UT assuming the current stdoff
3165  * and save values.
3166  */
3167  untiltime = zp->z_untiltime;
3168  if (!zp->z_untilrule.r_todisut)
3169  untiltime = tadd(untiltime,
3170  -stdoff);
3171  if (!zp->z_untilrule.r_todisstd)
3172  untiltime = tadd(untiltime,
3173  -save);
3174  }
3175 
3176  /*
3177  * Find the rule (of those to do, if any) that takes
3178  * effect earliest in the year.
3179  */
3180  k = -1;
3181  for (j = 0; j < zp->z_nrules; ++j)
3182  {
3183  rp = &zp->z_rules[j];
3184  if (!rp->r_todo)
3185  continue;
3186  eats(zp->z_filename, zp->z_linenum,
3187  rp->r_filename, rp->r_linenum);
3188  offset = rp->r_todisut ? 0 : stdoff;
3189  if (!rp->r_todisstd)
3190  offset = oadd(offset, save);
3191  jtime = rp->r_temp;
3192  if (jtime == min_time ||
3193  jtime == max_time)
3194  continue;
3195  jtime = tadd(jtime, -offset);
3196  if (k < 0 || jtime < ktime)
3197  {
3198  k = j;
3199  ktime = jtime;
3200  }
3201  else if (jtime == ktime)
3202  {
3203  char const *dup_rules_msg =
3204  _("two rules for same instant");
3205 
3206  eats(zp->z_filename, zp->z_linenum,
3207  rp->r_filename, rp->r_linenum);
3208  warning("%s", dup_rules_msg);
3209  rp = &zp->z_rules[k];
3210  eats(zp->z_filename, zp->z_linenum,
3211  rp->r_filename, rp->r_linenum);
3212  error("%s", dup_rules_msg);
3213  }
3214  }
3215  if (k < 0)
3216  break; /* go on to next year */
3217  rp = &zp->z_rules[k];
3218  rp->r_todo = false;
3219  if (useuntil && ktime >= untiltime)
3220  break;
3221  save = rp->r_save;
3222  if (usestart && ktime == starttime)
3223  usestart = false;
3224  if (usestart)
3225  {
3226  if (ktime < starttime)
3227  {
3228  startoff = oadd(zp->z_stdoff,
3229  save);
3230  doabbr(startbuf, zp,
3231  rp->r_abbrvar,
3232  rp->r_isdst,
3233  rp->r_save,
3234  false);
3235  continue;
3236  }
3237  if (*startbuf == '\0'
3238  && startoff == oadd(zp->z_stdoff,
3239  save))
3240  {
3241  doabbr(startbuf,
3242  zp,
3243  rp->r_abbrvar,
3244  rp->r_isdst,
3245  rp->r_save,
3246  false);
3247  }
3248  }
3249  eats(zp->z_filename, zp->z_linenum,
3250  rp->r_filename, rp->r_linenum);
3251  doabbr(ab, zp, rp->r_abbrvar,
3252  rp->r_isdst, rp->r_save, false);
3253  offset = oadd(zp->z_stdoff, rp->r_save);
3254  if (!want_bloat() && !useuntil && !do_extend
3255  && prevrp
3256  && rp->r_hiyear == ZIC_MAX
3257  && prevrp->r_hiyear == ZIC_MAX)
3258  break;
3259  type = addtype(offset, ab, rp->r_isdst,
3260  rp->r_todisstd, rp->r_todisut);
3261  if (defaulttype < 0 && !rp->r_isdst)
3262  defaulttype = type;
3263  if (rp->r_hiyear == ZIC_MAX
3264  && !(0 <= lastatmax
3265  && ktime < attypes[lastatmax].at))
3266  lastatmax = timecnt;
3267  addtt(ktime, type);
3268  prevrp = rp;
3269  }
3270  }
3271  if (usestart)
3272  {
3273  if (*startbuf == '\0' &&
3274  zp->z_format != NULL &&
3275  strchr(zp->z_format, '%') == NULL &&
3276  strchr(zp->z_format, '/') == NULL)
3277  strcpy(startbuf, zp->z_format);
3278  eat(zp->z_filename, zp->z_linenum);
3279  if (*startbuf == '\0')
3280  error(_("cannot determine time zone abbreviation to use just after until time"));
3281  else
3282  {
3283  bool isdst = startoff != zp->z_stdoff;
3284 
3285  type = addtype(startoff, startbuf, isdst,
3286  startttisstd, startttisut);
3287  if (defaulttype < 0 && !isdst)
3288  defaulttype = type;
3289  addtt(starttime, type);
3290  }
3291  }
3292 
3293  /*
3294  * Now we may get to set starttime for the next zone line.
3295  */
3296  if (useuntil)
3297  {
3298  startttisstd = zp->z_untilrule.r_todisstd;
3299  startttisut = zp->z_untilrule.r_todisut;
3300  starttime = zp->z_untiltime;
3301  if (!startttisstd)
3302  starttime = tadd(starttime, -save);
3303  if (!startttisut)
3304  starttime = tadd(starttime, -stdoff);
3305  }
3306  }
3307  if (defaulttype < 0)
3308  defaulttype = 0;
3309  if (0 <= lastatmax)
3310  attypes[lastatmax].dontmerge = true;
3311  if (do_extend)
3312  {
3313  /*
3314  * If we're extending the explicitly listed observations for 400 years
3315  * because we can't fill the POSIX-TZ field, check whether we actually
3316  * ended up explicitly listing observations through that period. If
3317  * there aren't any near the end of the 400-year period, add a
3318  * redundant one at the end of the final year, to make it clear that
3319  * we are claiming to have definite knowledge of the lack of
3320  * transitions up to that point.
3321  */
3322  struct rule xr;
3323  struct attype *lastat;
3324 
3325  xr.r_month = TM_JANUARY;
3326  xr.r_dycode = DC_DOM;
3327  xr.r_dayofmonth = 1;
3328  xr.r_tod = 0;
3329  for (lastat = attypes, i = 1; i < timecnt; i++)
3330  if (attypes[i].at > lastat->at)
3331  lastat = &attypes[i];
3332  if (!lastat || lastat->at < rpytime(&xr, max_year - 1))
3333  {
3334  addtt(rpytime(&xr, max_year + 1),
3335  lastat ? lastat->type : defaulttype);
3336  attypes[timecnt - 1].dontmerge = true;
3337  }
3338  }
3339  writezone(zpfirst->z_name, envvar, version, defaulttype);
3340  free(startbuf);
3341  free(ab);
3342  free(envvar);
3343 }
static zic_t leapmaxyear
Definition: zic.c:180
lineno_t r_linenum
Definition: zic.c:60
static int typecnt
Definition: zic.c:194
zic_t z_save
Definition: zic.c:105
static int stringzone(char *result, struct zone const *zpfirst, ptrdiff_t zonecount)
Definition: zic.c:2809
Definition: zic.c:388
unsigned char type
Definition: zic.c:392
bool r_todisstd
Definition: zic.c:75
static void static void static void warning(const char *string,...) pg_attribute_printf(1
Definition: zic.c:513
static void addtt(zic_t starttime, int type)
Definition: zic.c:3346
#define INITIALIZE(x)
Definition: private.h:92
const char * z_format
Definition: zic.c:101
zic_t r_save
Definition: zic.c:78
#define DC_DOM
Definition: zic.c:89
zic_t z_untiltime
Definition: zic.c:111
struct rule z_untilrule
Definition: zic.c:110
static zic_t min_year
Definition: zic.c:185
static void updateminmax(const zic_t x)
Definition: zic.c:2671
static int max_format_len
Definition: zic.c:183
bool z_isdst
Definition: zic.c:104
Definition: localtime.c:72
bool r_lowasnum
Definition: zic.c:65
#define ZIC_MAX
Definition: zic.c:27
const char * z_filename
Definition: zic.c:95
static zic_t tadd(zic_t t1, zic_t t2)
Definition: zic.c:3770
static int addtype(zic_t, char const *, bool, bool, bool)
Definition: zic.c:3356
bool r_todo
Definition: zic.c:81
static void writezone(const char *const name, const char *const string, char version, int defaulttype)
Definition: zic.c:2080
static size_t doabbr(char *abbr, struct zone const *zp, char const *letters, bool isdst, zic_t save, bool doquotes)
Definition: zic.c:2628
#define ZIC_VERSION_PRE_2013
Definition: zic.c:22
bool r_isdst
Definition: zic.c:77
static bool leapseen
Definition: zic.c:178
#define ZIC_VERSION
Definition: zic.c:23
static int max_abbrvar_len
Definition: zic.c:182
int64 zic_t
Definition: zic.c:25
zic_t r_hiyear
Definition: zic.c:64
zic_t r_temp
Definition: zic.c:82
#define ZIC_MIN
Definition: zic.c:26
bool r_todisut
Definition: zic.c:76
const char * r_filename
Definition: zic.c:59
enum COMPAT_MODE compat
Definition: ecpg.c:25
zic_t at
Definition: zic.c:390
#define EPOCH_YEAR
Definition: private.h:134
static zic_t rpytime(const struct rule *rp, zic_t wantedy)
Definition: zic.c:3799
static void eat(char const *name, lineno_t num)
Definition: zic.c:480
const char * r_abbrvar
Definition: zic.c:79
static struct attype * attypes
static zic_t const max_time
Definition: zic.c:584
static bool noise
Definition: zic.c:186
ptrdiff_t z_nrules
Definition: zic.c:108
#define TM_JANUARY
Definition: private.h:119
lineno_t z_linenum
Definition: zic.c:96
static zic_t max_year
Definition: zic.c:184
#define free(a)
Definition: header.h:65
static ptrdiff_t timecnt
Definition: zic.c:192
static int charcnt
Definition: zic.c:173
static zic_t leapminyear
Definition: zic.c:179
#define YEARSPERREPEAT
Definition: private.h:99
struct rule * z_rules
Definition: zic.c:107
Definition: zic.c:93
bool r_hiwasnum
Definition: zic.c:66
int i
static void static void error(const char *string,...) pg_attribute_printf(1
Definition: zic.c:502
zic_t r_loyear
Definition: zic.c:63
static zic_t const min_time
Definition: zic.c:583
bool dontmerge
Definition: zic.c:391
static void eats(char const *name, lineno_t num, char const *rname, lineno_t rnum)
Definition: zic.c:471
#define _(x)
Definition: elog.c:88
static zic_t oadd(zic_t t1, zic_t t2)
Definition: zic.c:3762
static bool want_bloat(void)
Definition: zic.c:642
zic_t z_stdoff
Definition: zic.c:99
static void * emalloc(size_t size)
Definition: zic.c:432

◆ puttzcode()

static void puttzcode ( const int32  val,
FILE *const  fp 
)
static

Definition at line 2012 of file zic.c.

References buf, and convert().

Referenced by puttzcodepass(), and writezone().

2013 {
2014  char buf[4];
2015 
2016  convert(val, buf);
2017  fwrite(buf, sizeof buf, 1, fp);
2018 }
static void convert(const int32 val, char *const buf)
Definition: zic.c:1990
static char * buf
Definition: pg_test_fsync.c:68
long val
Definition: informix.c:664

◆ puttzcodepass()

static void puttzcodepass ( zic_t  val,
FILE *  fp,
int  pass 
)
static

Definition at line 2021 of file zic.c.

References buf, convert64(), and puttzcode().

Referenced by writezone().

2022 {
2023  if (pass == 1)
2024  puttzcode(val, fp);
2025  else
2026  {
2027  char buf[8];
2028 
2029  convert64(val, buf);
2030  fwrite(buf, sizeof buf, 1, fp);
2031  }
2032 }
static char * buf
Definition: pg_test_fsync.c:68
long val
Definition: informix.c:664
static void puttzcode(const int32 val, FILE *const fp)
Definition: zic.c:2012
static void convert64(const zic_t val, char *const buf)
Definition: zic.c:2001

◆ rcomp()

static int rcomp ( const void *  cp1,
const void *  cp2 
)
static

Definition at line 1149 of file zic.c.

References rule::r_name.

Referenced by associate().

1150 {
1151  return strcmp(((const struct rule *) cp1)->r_name,
1152  ((const struct rule *) cp2)->r_name);
1153 }
Definition: localtime.c:72

◆ rpytime()

static zic_t rpytime ( const struct rule rp,
zic_t  wantedy 
)
static

Definition at line 3799 of file zic.c.

References _, DC_DOWGEQ, DC_DOWLEQ, EPOCH_WDAY, EPOCH_YEAR, error(), EXIT_FAILURE, i, isleap, LDAYSPERWEEK, max_time, min_time, oadd(), rule::r_dayofmonth, rule::r_dycode, rule::r_month, rule::r_tod, rule::r_wday, SECSPERDAY, SECSPERREPEAT, tadd(), TM_FEBRUARY, TM_JANUARY, warning(), YEARSPERREPEAT, ZIC_MAX, and ZIC_MIN.

Referenced by inzsub(), and outzone().

3800 {
3801  int m,
3802  i;
3803  zic_t dayoff; /* with a nod to Margaret O. */
3804  zic_t t,
3805  y;
3806 
3807  if (wantedy == ZIC_MIN)
3808  return min_time;
3809  if (wantedy == ZIC_MAX)
3810  return max_time;
3811  dayoff = 0;
3812  m = TM_JANUARY;
3813  y = EPOCH_YEAR;
3814  if (y < wantedy)
3815  {
3816  wantedy -= y;
3817  dayoff = (wantedy / YEARSPERREPEAT) * (SECSPERREPEAT / SECSPERDAY);
3818  wantedy %= YEARSPERREPEAT;
3819  wantedy += y;
3820  }
3821  else if (wantedy < 0)
3822  {
3823  dayoff = (wantedy / YEARSPERREPEAT) * (SECSPERREPEAT / SECSPERDAY);
3824  wantedy %= YEARSPERREPEAT;
3825  }
3826  while (wantedy != y)
3827  {
3828  if (wantedy > y)
3829  {
3830  i = len_years[isleap(y)];
3831  ++y;
3832  }
3833  else
3834  {
3835  --y;
3836  i = -len_years[isleap(y)];
3837  }
3838  dayoff = oadd(dayoff, i);
3839  }
3840  while (m != rp->r_month)
3841  {
3842  i = len_months[isleap(y)][m];
3843  dayoff = oadd(dayoff, i);
3844  ++m;
3845  }
3846  i = rp->r_dayofmonth;
3847  if (m == TM_FEBRUARY && i == 29 && !isleap(y))
3848  {
3849  if (rp->r_dycode == DC_DOWLEQ)
3850  --i;
3851  else
3852  {
3853  error(_("use of 2/29 in non leap-year"));
3854  exit(EXIT_FAILURE);
3855  }
3856  }
3857  --i;
3858  dayoff = oadd(dayoff, i);
3859  if (rp->r_dycode == DC_DOWGEQ || rp->r_dycode == DC_DOWLEQ)
3860  {
3861  zic_t wday;
3862 
3863 #define LDAYSPERWEEK ((zic_t) DAYSPERWEEK)
3864  wday = EPOCH_WDAY;
3865 
3866  /*
3867  * Don't trust mod of negative numbers.
3868  */
3869  if (dayoff >= 0)
3870  wday = (wday + dayoff) % LDAYSPERWEEK;
3871  else
3872  {
3873  wday -= ((-dayoff) % LDAYSPERWEEK);
3874  if (wday < 0)
3875  wday += LDAYSPERWEEK;
3876  }
3877  while (wday != rp->r_wday)
3878  if (rp->r_dycode == DC_DOWGEQ)
3879  {
3880  dayoff = oadd(dayoff, 1);
3881  if (++wday >= LDAYSPERWEEK)
3882  wday = 0;
3883  ++i;
3884  }
3885  else
3886  {
3887  dayoff = oadd(dayoff, -1);
3888  if (--wday < 0)
3889  wday = LDAYSPERWEEK - 1;
3890  --i;
3891  }
3892  if (i < 0 || i >= len_months[isleap(y)][m])
3893  {
3894  if (noise)
3895  warning(_("rule goes past start/end of month; \
3896 will not work with pre-2004 versions of zic"));
3897  }
3898  }
3899  if (dayoff < min_time / SECSPERDAY)
3900  return min_time;
3901  if (dayoff > max_time / SECSPERDAY)
3902  return max_time;
3903  t = (zic_t) dayoff * SECSPERDAY;
3904  return tadd(t, rp->r_tod);
3905 }
zic_t r_tod
Definition: zic.c:74
static void static void static void warning(const char *string,...) pg_attribute_printf(1
Definition: zic.c:513
int r_month
Definition: zic.c:68
#define DC_DOWGEQ
Definition: zic.c:90
#define SECSPERDAY
Definition: private.h:108
#define isleap(y)
Definition: datetime.h:271
static const int len_months[2][MONSPERYEAR]
Definition: zic.c:379
#define ZIC_MAX
Definition: zic.c:27
#define LDAYSPERWEEK
static zic_t tadd(zic_t t1, zic_t t2)
Definition: zic.c:3770
int64 zic_t
Definition: zic.c:25
#define ZIC_MIN
Definition: zic.c:26
int r_dycode
Definition: zic.c:70
#define EPOCH_YEAR
Definition: private.h:134
#define DC_DOWLEQ
Definition: zic.c:91
static zic_t const max_time
Definition: zic.c:584
static bool noise
Definition: zic.c:186
#define TM_JANUARY
Definition: private.h:119
#define TM_FEBRUARY
Definition: private.h:120
int r_dayofmonth
Definition: zic.c:71
int r_wday
Definition: zic.c:72
#define EPOCH_WDAY
Definition: private.h:135
#define YEARSPERREPEAT
Definition: private.h:99
int i
#define EXIT_FAILURE
Definition: settings.h:161
static const int len_years[2]
Definition: zic.c:384
#define SECSPERREPEAT
Definition: private.h:159
static void static void error(const char *string,...) pg_attribute_printf(1
Definition: zic.c:502
static zic_t const min_time
Definition: zic.c:583
#define _(x)
Definition: elog.c:88
static zic_t oadd(zic_t t1, zic_t t2)
Definition: zic.c:3762

◆ rule_cmp()

static int rule_cmp ( struct rule const *  a,
struct rule const *  b 
)
static

Definition at line 2795 of file zic.c.

References rule::r_dayofmonth, rule::r_hiyear, and rule::r_month.

Referenced by stringzone().

2796 {
2797  if (!a)
2798  return -!!b;
2799  if (!b)
2800  return 1;
2801  if (a->r_hiyear != b->r_hiyear)
2802  return a->r_hiyear < b->r_hiyear ? -1 : 1;
2803  if (a->r_month - b->r_month != 0)
2804  return a->r_month - b->r_month;
2805  return a->r_dayofmonth - b->r_dayofmonth;
2806 }

◆ rulesub()

static void rulesub ( struct rule rp,
const char *  loyearp,
const char *  hiyearp,
const char *  typep,
const char *  monthp,
const char *  dayp,
const char *  timep 
)
static

Definition at line 1821 of file zic.c.

References _, byword(), DC_DOM, DC_DOWGEQ, DC_DOWLEQ, ecpyalloc(), error(), EXIT_FAILURE, fprintf, free, gethms(), lookup::l_value, lowerit(), rule::r_dayofmonth, rule::r_dycode, rule::r_hiwasnum, rule::r_hiyear, rule::r_lowasnum, rule::r_loyear, rule::r_month, rule::r_tod, rule::r_todisstd, rule::r_todisut, rule::r_wday, YR_MAXIMUM, YR_MINIMUM, YR_ONLY, ZIC_MAX, and ZIC_MIN.

Referenced by inrule(), and inzsub().

1824 {
1825  const struct lookup *lp;
1826  const char *cp;
1827  char *dp;
1828  char *ep;
1829  char xs;
1830 
1831  /* PG: year_tmp is to avoid sscanf portability issues */
1832  int year_tmp;
1833 
1834  if ((lp = byword(monthp, mon_names)) == NULL)
1835  {
1836  error(_("invalid month name"));
1837  return;
1838  }
1839  rp->r_month = lp->l_value;
1840  rp->r_todisstd = false;
1841  rp->r_todisut = false;
1842  dp = ecpyalloc(timep);
1843  if (*dp != '\0')
1844  {
1845  ep = dp + strlen(dp) - 1;
1846  switch (lowerit(*ep))
1847  {
1848  case 's': /* Standard */
1849  rp->r_todisstd = true;
1850  rp->r_todisut = false;
1851  *ep = '\0';
1852  break;
1853  case 'w': /* Wall */
1854  rp->r_todisstd = false;
1855  rp->r_todisut = false;
1856  *ep = '\0';
1857  break;
1858  case 'g': /* Greenwich */
1859  case 'u': /* Universal */
1860  case 'z': /* Zulu */
1861  rp->r_todisstd = true;
1862  rp->r_todisut = true;
1863  *ep = '\0';
1864  break;
1865  }
1866  }
1867  rp->r_tod = gethms(dp, _("invalid time of day"));
1868  free(dp);
1869 
1870  /*
1871  * Year work.
1872  */
1873  cp = loyearp;
1874  lp = byword(cp, begin_years);
1875  rp->r_lowasnum = lp == NULL;
1876  if (!rp->r_lowasnum)
1877  switch (lp->l_value)
1878  {
1879  case YR_MINIMUM:
1880  rp->r_loyear = ZIC_MIN;
1881  break;
1882  case YR_MAXIMUM:
1883  rp->r_loyear = ZIC_MAX;
1884  break;
1885  default: /* "cannot happen" */
1886  fprintf(stderr,
1887  _("%s: panic: Invalid l_value %d\n"),
1888  progname, lp->l_value);
1889  exit(EXIT_FAILURE);
1890  }
1891  else if (sscanf(cp, "%d%c", &year_tmp, &xs) == 1)
1892  rp->r_loyear = year_tmp;
1893  else
1894  {
1895  error(_("invalid starting year"));
1896  return;
1897  }
1898  cp = hiyearp;
1899  lp = byword(cp, end_years);
1900  rp->r_hiwasnum = lp == NULL;
1901  if (!rp->r_hiwasnum)
1902  switch (lp->l_value)
1903  {
1904  case YR_MINIMUM:
1905  rp->r_hiyear = ZIC_MIN;
1906  break;
1907  case YR_MAXIMUM:
1908  rp->r_hiyear = ZIC_MAX;
1909  break;
1910  case YR_ONLY:
1911  rp->r_hiyear = rp->r_loyear;
1912  break;
1913  default: /* "cannot happen" */
1914  fprintf(stderr,
1915  _("%s: panic: Invalid l_value %d\n"),
1916  progname, lp->l_value);
1917  exit(EXIT_FAILURE);
1918  }
1919  else if (sscanf(cp, "%d%c", &year_tmp, &xs) == 1)
1920  rp->r_hiyear = year_tmp;
1921  else
1922  {
1923  error(_("invalid ending year"));
1924  return;
1925  }
1926  if (rp->r_loyear > rp->r_hiyear)
1927  {
1928  error(_("starting year greater than ending year"));
1929  return;
1930  }
1931  if (*typep != '\0')
1932  {
1933  error(_("year type \"%s\" is unsupported; use \"-\" instead"),
1934  typep);
1935  return;
1936  }
1937 
1938  /*
1939  * Day work. Accept things such as: 1 lastSunday last-Sunday
1940  * (undocumented; warn about this) Sun<=20 Sun>=7
1941  */
1942  dp = ecpyalloc(dayp);
1943  if ((lp = byword(dp, lasts)) != NULL)
1944  {
1945  rp->r_dycode = DC_DOWLEQ;
1946  rp->r_wday = lp->l_value;
1947  rp->r_dayofmonth = len_months[1][rp->r_month];
1948  }
1949  else
1950  {
1951  if ((ep = strchr(dp, '<')) != NULL)
1952  rp->r_dycode = DC_DOWLEQ;
1953  else if ((ep = strchr(dp, '>')) != NULL)
1954  rp->r_dycode = DC_DOWGEQ;
1955  else
1956  {
1957  ep = dp;
1958  rp->r_dycode = DC_DOM;
1959  }
1960  if (rp->r_dycode != DC_DOM)
1961  {
1962  *ep++ = 0;
1963  if (*ep++ != '=')
1964  {
1965  error(_("invalid day of month"));
1966  free(dp);
1967  return;
1968  }
1969  if ((lp = byword(dp, wday_names)) == NULL)
1970  {
1971  error(_("invalid weekday name"));
1972  free(dp);
1973  return;
1974  }
1975  rp->r_wday = lp->l_value;
1976  }
1977  if (sscanf(ep, "%d%c", &rp->r_dayofmonth, &xs) != 1 ||
1978  rp->r_dayofmonth <= 0 ||
1979  (rp->r_dayofmonth > len_months[1][rp->r_month]))
1980  {
1981  error(_("invalid day of month"));
1982  free(dp);
1983  return;
1984  }
1985  }
1986  free(dp);
1987 }
#define YR_MINIMUM
Definition: zic.c:277
zic_t r_tod
Definition: zic.c:74
bool r_todisstd
Definition: zic.c:75
static char * ecpyalloc(char const *str)
Definition: zic.c:444
int r_month
Definition: zic.c:68
#define DC_DOWGEQ
Definition: zic.c:90
static struct lookup const begin_years[]
Definition: zic.c:360
#define DC_DOM
Definition: zic.c:89
static const int len_months[2][MONSPERYEAR]
Definition: zic.c:379
#define fprintf
Definition: port.h:219
const int l_value
Definition: zic.c:304
bool r_lowasnum
Definition: zic.c:65
#define ZIC_MAX
Definition: zic.c:27
#define YR_ONLY
Definition: zic.c:279
static zic_t gethms(const char *string, const char *errstring)
Definition: zic.c:1363
static struct lookup const mon_names[]
Definition: zic.c:322
Definition: zic.c:301
zic_t r_hiyear
Definition: zic.c:64
#define ZIC_MIN
Definition: zic.c:26
bool r_todisut
Definition: zic.c:76
static struct lookup const end_years[]
Definition: zic.c:366
int r_dycode
Definition: zic.c:70
#define DC_DOWLEQ
Definition: zic.c:91
static const char * progname
Definition: zic.c:191
#define free(a)
Definition: header.h:65
int r_dayofmonth
Definition: zic.c:71
int r_wday
Definition: zic.c:72
static struct lookup const * byword(const char *string, const struct lookup *lp)
Definition: zic.c:3649
static char lowerit(char)
Definition: zic.c:3549
#define YR_MAXIMUM
Definition: zic.c:278
static struct lookup const lasts[]
Definition: zic.c:349
bool r_hiwasnum
Definition: zic.c:66
static struct lookup const wday_names[]
Definition: zic.c:338
#define EXIT_FAILURE
Definition: settings.h:161
static void static void error(const char *string,...) pg_attribute_printf(1
Definition: zic.c:502
zic_t r_loyear
Definition: zic.c:63
#define _(x)
Definition: elog.c:88

◆ size_product()

static size_t size_product ( size_t  nitems,
size_t  itemsize 
)
static

Definition at line 416 of file zic.c.

References _, and memory_exhausted().

Referenced by getfields(), growalloc(), and writezone().

417 {
418  if (SIZE_MAX / itemsize < nitems)
419  memory_exhausted(_("size overflow"));
420  return nitems * itemsize;
421 }
static void memory_exhausted(const char *msg) pg_attribute_noreturn()
Definition: zic.c:409
#define _(x)
Definition: elog.c:88

◆ stringoffset()

static int stringoffset ( char *  result,
zic_t  offset 
)
static

Definition at line 2680 of file zic.c.

References DAYSPERWEEK, HOURSPERDAY, MINSPERHOUR, SECSPERMIN, and sprintf.

Referenced by stringrule(), and stringzone().

2681 {
2682  int hours;
2683  int minutes;
2684  int seconds;
2685  bool negative = offset < 0;
2686  int len = negative;
2687 
2688  if (negative)
2689  {
2690  offset = -offset;
2691  result[0] = '-';
2692  }
2693  seconds = offset % SECSPERMIN;
2694  offset /= SECSPERMIN;
2695  minutes = offset % MINSPERHOUR;
2696  offset /= MINSPERHOUR;
2697  hours = offset;
2698  if (hours >= HOURSPERDAY * DAYSPERWEEK)
2699  {
2700  result[0] = '\0';
2701  return 0;
2702  }
2703  len += sprintf(result + len, "%d", hours);
2704  if (minutes != 0 || seconds != 0)
2705  {
2706  len += sprintf(result + len, ":%02d", minutes);
2707  if (seconds != 0)
2708  len += sprintf(result + len, ":%02d", seconds);
2709  }
2710  return len;
2711 }
#define SECSPERMIN
Definition: private.h:101
#define HOURSPERDAY
Definition: private.h:103
#define sprintf
Definition: port.h:217
#define DAYSPERWEEK
Definition: private.h:104
#define MINSPERHOUR
Definition: private.h:102

◆ stringrule()

static int stringrule ( char *  result,
struct rule *const  rp,
zic_t  save,
zic_t  stdoff 
)
static

Definition at line 2714 of file zic.c.

References compat, DAYSPERWEEK, DC_DOM, DC_DOWGEQ, DC_DOWLEQ, MINSPERHOUR, rule::r_dayofmonth, rule::r_dycode, rule::r_isdst, rule::r_month, rule::r_tod, rule::r_todisstd, rule::r_todisut, rule::r_wday, SECSPERDAY, SECSPERMIN, sprintf, stringoffset(), and TM_FEBRUARY.

Referenced by stringzone().

2715 {
2716  zic_t tod = rp->r_tod;
2717  int compat = 0;
2718 
2719  if (rp->r_dycode == DC_DOM)
2720  {
2721  int month,
2722  total;
2723 
2724  if (rp->r_dayofmonth == 29 && rp->r_month == TM_FEBRUARY)
2725  return -1;
2726  total = 0;
2727  for (month = 0; month < rp->r_month; ++month)
2728  total += len_months[0][month];
2729  /* Omit the "J" in Jan and Feb, as that's shorter. */
2730  if (rp->r_month <= 1)
2731  result += sprintf(result, "%d", total + rp->r_dayofmonth - 1);
2732  else
2733  result += sprintf(result, "J%d", total + rp->r_dayofmonth);
2734  }
2735  else
2736  {
2737  int week;
2738  int wday = rp->r_wday;
2739  int wdayoff;
2740 
2741  if (rp->r_dycode == DC_DOWGEQ)
2742  {
2743  wdayoff = (rp->r_dayofmonth - 1) % DAYSPERWEEK;
2744  if (wdayoff)
2745  compat = 2013;
2746  wday -= wdayoff;
2747  tod += wdayoff * SECSPERDAY;
2748  week = 1 + (rp->r_dayofmonth - 1) / DAYSPERWEEK;
2749  }
2750  else if (rp->r_dycode == DC_DOWLEQ)
2751  {
2752  if (rp->r_dayofmonth == len_months[1][rp->r_month])
2753  week = 5;
2754  else
2755  {
2756  wdayoff = rp->r_dayofmonth % DAYSPERWEEK;
2757  if (wdayoff)
2758  compat = 2013;
2759  wday -= wdayoff;
2760  tod += wdayoff * SECSPERDAY;
2761  week = rp->r_dayofmonth / DAYSPERWEEK;
2762  }
2763  }
2764  else
2765  return -1; /* "cannot happen" */
2766  if (wday < 0)
2767  wday += DAYSPERWEEK;
2768  result += sprintf(result, "M%d.%d.%d",
2769  rp->r_month + 1, week, wday);
2770  }
2771  if (rp->r_todisut)
2772  tod += stdoff;
2773  if (rp->r_todisstd && !rp->r_isdst)
2774  tod += save;
2775  if (tod != 2 * SECSPERMIN * MINSPERHOUR)
2776  {
2777  *result++ = '/';
2778  if (!stringoffset(result, tod))
2779  return -1;
2780  if (tod < 0)
2781  {
2782  if (compat < 2013)
2783  compat = 2013;
2784  }
2785  else if (SECSPERDAY <= tod)
2786  {
2787  if (compat < 1994)
2788  compat = 1994;
2789  }
2790  }
2791  return compat;
2792 }
#define SECSPERMIN
Definition: private.h:101
zic_t r_tod
Definition: zic.c:74
bool r_todisstd
Definition: zic.c:75
int r_month
Definition: zic.c:68
#define DC_DOWGEQ
Definition: zic.c:90
#define SECSPERDAY
Definition: private.h:108
#define DC_DOM
Definition: zic.c:89
static const int len_months[2][MONSPERYEAR]
Definition: zic.c:379
static int stringoffset(char *result, zic_t offset)
Definition: zic.c:2680
#define sprintf
Definition: port.h:217
#define DAYSPERWEEK
Definition: private.h:104
bool r_isdst
Definition: zic.c:77
int64 zic_t
Definition: zic.c:25
bool r_todisut
Definition: zic.c:76
enum COMPAT_MODE compat
Definition: ecpg.c:25
int r_dycode
Definition: zic.c:70
#define DC_DOWLEQ
Definition: zic.c:91
#define TM_FEBRUARY
Definition: private.h:120
int r_dayofmonth
Definition: zic.c:71
int r_wday
Definition: zic.c:72
#define MINSPERHOUR
Definition: private.h:102

◆ stringzone()

static int stringzone ( char *  result,
struct zone const *  zpfirst,
ptrdiff_t  zonecount 
)
static

Definition at line 2809 of file zic.c.

References compat, DC_DOM, doabbr(), i, MINSPERHOUR, rule::r_abbrvar, rule::r_dayofmonth, rule::r_dycode, rule::r_hiwasnum, rule::r_hiyear, rule::r_isdst, rule::r_month, rule::r_save, rule::r_tod, rule::r_todisstd, rule::r_todisut, rule_cmp(), SECSPERDAY, SECSPERMIN, stringoffset(), stringrule(), TM_DECEMBER, TM_JANUARY, zone::z_isdst, zone::z_nrules, zone::z_rules, zone::z_stdoff, and ZIC_MAX.

Referenced by outzone().

2810 {
2811  const struct zone *zp;
2812  struct rule *rp;
2813  struct rule *stdrp;
2814  struct rule *dstrp;
2815  ptrdiff_t i;
2816  const char *abbrvar;
2817  int compat = 0;
2818  int c;
2819  size_t len;
2820  int offsetlen;
2821  struct rule stdr,
2822  dstr;
2823 
2824  result[0] = '\0';
2825 
2826  /*
2827  * Internet RFC 8536 section 5.1 says to use an empty TZ string if future
2828  * timestamps are truncated.
2829  */
2830  if (hi_time < max_time)
2831  return -1;
2832 
2833  zp = zpfirst + zonecount - 1;
2834  stdrp = dstrp = NULL;
2835  for (i = 0; i < zp->z_nrules; ++i)
2836  {
2837  rp = &zp->z_rules[i];
2838  if (rp->r_hiwasnum || rp->r_hiyear != ZIC_MAX)
2839  continue;
2840  if (!rp->r_isdst)
2841  {
2842  if (stdrp == NULL)
2843  stdrp = rp;
2844  else
2845  return -1;
2846  }
2847  else
2848  {
2849  if (dstrp == NULL)
2850  dstrp = rp;
2851  else
2852  return -1;
2853  }
2854  }
2855  if (stdrp == NULL && dstrp == NULL)
2856  {
2857  /*
2858  * There are no rules running through "max". Find the latest std rule
2859  * in stdabbrrp and latest rule of any type in stdrp.
2860  */
2861  struct rule *stdabbrrp = NULL;
2862 
2863  for (i = 0; i < zp->z_nrules; ++i)
2864  {
2865  rp = &zp->z_rules[i];
2866  if (!rp->r_isdst && rule_cmp(stdabbrrp, rp) < 0)
2867  stdabbrrp = rp;
2868  if (rule_cmp(stdrp, rp) < 0)
2869  stdrp = rp;
2870  }
2871  if (stdrp != NULL && stdrp->r_isdst)
2872  {
2873  /* Perpetual DST. */
2874  dstr.r_month = TM_JANUARY;
2875  dstr.r_dycode = DC_DOM;
2876  dstr.r_dayofmonth = 1;
2877  dstr.r_tod = 0;
2878  dstr.r_todisstd = dstr.r_todisut = false;
2879  dstr.r_isdst = stdrp->r_isdst;
2880  dstr.r_save = stdrp->r_save;
2881  dstr.r_abbrvar = stdrp->r_abbrvar;
2882  stdr.r_month = TM_DECEMBER;
2883  stdr.r_dycode = DC_DOM;
2884  stdr.r_dayofmonth = 31;
2885  stdr.r_tod = SECSPERDAY + stdrp->r_save;
2886  stdr.r_todisstd = stdr.r_todisut = false;
2887  stdr.r_isdst = false;
2888  stdr.r_save = 0;
2889  stdr.r_abbrvar
2890  = (stdabbrrp ? stdabbrrp->r_abbrvar : "");
2891  dstrp = &dstr;
2892  stdrp = &stdr;
2893  }
2894  }
2895  if (stdrp == NULL && (zp->z_nrules != 0 || zp->z_isdst))
2896  return -1;
2897  abbrvar = (stdrp == NULL) ? "" : stdrp->r_abbrvar;
2898  len = doabbr(result, zp, abbrvar, false, 0, true);
2899  offsetlen = stringoffset(result + len, -zp->z_stdoff);
2900  if (!offsetlen)
2901  {
2902  result[0] = '\0';
2903  return -1;
2904  }
2905  len += offsetlen;
2906  if (dstrp == NULL)
2907  return compat;
2908  len += doabbr(result + len, zp, dstrp->r_abbrvar,
2909  dstrp->r_isdst, dstrp->r_save, true);
2910  if (dstrp->r_save != SECSPERMIN * MINSPERHOUR)
2911  {
2912  offsetlen = stringoffset(result + len,
2913  -(zp->z_stdoff + dstrp->r_save));
2914  if (!offsetlen)
2915  {
2916  result[0] = '\0';
2917  return -1;
2918  }
2919  len += offsetlen;
2920  }
2921  result[len++] = ',';
2922  c = stringrule(result + len, dstrp, dstrp->r_save, zp->z_stdoff);
2923  if (c < 0)
2924  {
2925  result[0] = '\0';
2926  return -1;
2927  }
2928  if (compat < c)
2929  compat = c;
2930  len += strlen(result + len);
2931  result[len++] = ',';
2932  c = stringrule(result + len, stdrp, dstrp->r_save, zp->z_stdoff);
2933  if (c < 0)
2934  {
2935  result[0] = '\0';
2936  return -1;
2937  }
2938  if (compat < c)
2939  compat = c;
2940  return compat;
2941 }
#define SECSPERMIN
Definition: private.h:101
int r_month
Definition: zic.c:68
#define SECSPERDAY
Definition: private.h:108
zic_t r_save
Definition: zic.c:78
#define TM_DECEMBER
Definition: private.h:130
static int rule_cmp(struct rule const *a, struct rule const *b)
Definition: zic.c:2795
#define DC_DOM
Definition: zic.c:89
static zic_t hi_time
Definition: zic.c:589
static int stringoffset(char *result, zic_t offset)
Definition: zic.c:2680
bool z_isdst
Definition: zic.c:104
Definition: localtime.c:72
#define ZIC_MAX
Definition: zic.c:27
static size_t doabbr(char *abbr, struct zone const *zp, char const *letters, bool isdst, zic_t save, bool doquotes)
Definition: zic.c:2628
bool r_isdst
Definition: zic.c:77
char * c
static int stringrule(char *result, struct rule *const rp, zic_t save, zic_t stdoff)
Definition: zic.c:2714
zic_t r_hiyear
Definition: zic.c:64
enum COMPAT_MODE compat
Definition: ecpg.c:25
const char * r_abbrvar
Definition: zic.c:79
static zic_t const max_time
Definition: zic.c:584
ptrdiff_t z_nrules
Definition: zic.c:108
#define TM_JANUARY
Definition: private.h:119
struct rule * z_rules
Definition: zic.c:107
Definition: zic.c:93
bool r_hiwasnum
Definition: zic.c:66
int i
#define MINSPERHOUR
Definition: private.h:102
zic_t z_stdoff
Definition: zic.c:99

◆ tadd()

static zic_t tadd ( zic_t  t1,
zic_t  t2 
)
static

Definition at line 3770 of file zic.c.

References max_time, min_time, and time_overflow().

Referenced by adjleap(), getleapdatetime(), outzone(), rpytime(), and writezone().

3771 {
3772  if (t1 < 0)
3773  {
3774  if (t2 < min_time - t1)
3775  {
3776  if (t1 != min_time)
3777  time_overflow();
3778  return min_time;
3779  }
3780  }
3781  else
3782  {
3783  if (max_time - t1 < t2)
3784  {
3785  if (t1 != max_time)
3786  time_overflow();
3787  return max_time;
3788  }
3789  }
3790  return t1 + t2;
3791 }
static void time_overflow(void)
Definition: zic.c:3755
static zic_t const max_time
Definition: zic.c:584
static zic_t const min_time
Definition: zic.c:583

◆ time_overflow()

static void time_overflow ( void  )
static

Definition at line 3755 of file zic.c.

References _, error(), and EXIT_FAILURE.

Referenced by oadd(), and tadd().

3756 {
3757  error(_("time overflow"));
3758  exit(EXIT_FAILURE);
3759 }
#define EXIT_FAILURE
Definition: settings.h:161
static void static void error(const char *string,...) pg_attribute_printf(1
Definition: zic.c:502
#define _(x)
Definition: elog.c:88

◆ timerange_option()

static bool timerange_option ( char *  timerange)
static

Definition at line 600 of file zic.c.

References max_time, min_time, PG_INT64_MAX, PG_INT64_MIN, and strtoimax.

Referenced by main().

601 {
602  int64 lo = min_time,
603  hi = max_time;
604  char *lo_end = timerange,
605  *hi_end;
606 
607  if (*timerange == '@')
608  {
609  errno = 0;
610  lo = strtoimax(timerange + 1, &lo_end, 10);
611  if (lo_end == timerange + 1 || (lo == PG_INT64_MAX && errno == ERANGE))
612  return false;
613  }
614  hi_end = lo_end;
615  if (lo_end[0] == '/' && lo_end[1] == '@')
616  {
617  errno = 0;
618  hi = strtoimax(lo_end + 2, &hi_end, 10);
619  if (hi_end == lo_end + 2 || hi == PG_INT64_MIN)
620  return false;
621  hi -= !(hi == PG_INT64_MAX && errno == ERANGE);
622  }
623  if (*hi_end || hi < lo || max_time < lo || hi < min_time)
624  return false;
625  lo_time = lo < min_time ? min_time : lo;
626  hi_time = max_time < hi ? max_time : hi;
627  return true;
628 }
#define PG_INT64_MAX
Definition: c.h:461
static zic_t lo_time
Definition: zic.c:588
static zic_t hi_time
Definition: zic.c:589
#define PG_INT64_MIN
Definition: c.h:460
#define strtoimax
Definition: private.h:52
static zic_t const max_time
Definition: zic.c:584
static zic_t const min_time
Definition: zic.c:583

◆ updateminmax()

static void updateminmax ( const zic_t  x)
static

Definition at line 2671 of file zic.c.

Referenced by outzone().

2672 {
2673  if (min_year > x)
2674  min_year = x;
2675  if (max_year < x)
2676  max_year = x;
2677 }
static zic_t min_year
Definition: zic.c:185
static zic_t max_year
Definition: zic.c:184

◆ usage()

static void usage ( FILE *  stream,
int  status 
)
static

Definition at line 541 of file zic.c.

References _, close_file(), EXIT_SUCCESS, and fprintf.

Referenced by main().

542 {
543  fprintf(stream,
544  _("%s: usage is %s [ --version ] [ --help ] [ -v ] [ -P ] \\\n"
545  "\t[ -b {slim|fat} ] [ -d directory ] [ -l localtime ]"
546  " [ -L leapseconds ] \\\n"
547  "\t[ -p posixrules ] [ -r '[@lo][/@hi]' ] [ -t localtime-link ] \\\n"
548  "\t[ filename ... ]\n\n"
549  "Report bugs to %s.\n"),
550  progname, progname, PACKAGE_BUGREPORT);
551  if (status == EXIT_SUCCESS)
552  close_file(stream, NULL, NULL);
553  exit(status);
554 }
#define EXIT_SUCCESS
Definition: settings.h:157
#define fprintf
Definition: port.h:219
static const char * progname
Definition: zic.c:191
static void close_file(FILE *stream, char const *dir, char const *name)
Definition: zic.c:525
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227
#define _(x)
Definition: elog.c:88

◆ verror()

static void verror ( const char *  string,
va_list  args 
)
static

Definition at line 486 of file zic.c.

References _, fprintf, and vfprintf.

Referenced by error(), and warning().

487 {
488  /*
489  * Match the format of "cc" to allow sh users to zic ... 2>&1 | error -t
490  * "*" -v on BSD systems.
491  */
492  if (filename)
493  fprintf(stderr, _("\"%s\", line %d: "), filename, linenum);
494  vfprintf(stderr, string, args);
495  if (rfilename != NULL)
496  fprintf(stderr, _(" (rule from \"%s\", line %d)"),
498  fprintf(stderr, "\n");
499 }
#define fprintf
Definition: port.h:219
static lineno_t rlinenum
Definition: zic.c:190
static const char * filename
Definition: zic.c:176
static lineno_t linenum
Definition: zic.c:181
static const char * rfilename
Definition: zic.c:189
#define vfprintf
Definition: port.h:218
#define _(x)
Definition: elog.c:88

◆ want_bloat()

static bool want_bloat ( void  )
static

Definition at line 642 of file zic.c.

References bloat.

Referenced by addtype(), outzone(), and writezone().

643 {
644  return 0 <= bloat;
645 }
static int bloat
Definition: zic.c:639

◆ warning()

static void warning ( const char *  string,
  ... 
)
static

Definition at line 513 of file zic.c.

References _, generate_unaccent_rules::args, fprintf, and verror().

Referenced by adjleap(), associate(), byword(), componentcheck(), dolink(), gethms(), inzsub(), main(), namecheck(), newabbr(), outzone(), rpytime(), and writezone().

514 {
515  va_list args;
516 
517  fprintf(stderr, _("warning: "));
518  va_start(args, string);
519  verror(string, args);
520  va_end(args);
521  warnings = true;
522 }
static bool warnings
Definition: zic.c:175
#define fprintf
Definition: port.h:219
static void verror(const char *string, va_list args) pg_attribute_printf(1
Definition: zic.c:486
#define _(x)
Definition: elog.c:88

◆ writezone()

static void writezone ( const char *const  name,
const char *const  string,
char  version,
int  defaulttype 
)
static

Definition at line 2080 of file zic.c.

References _, addtype(), attype::at, atcomp(), attypes, timerange::base, close_file(), convert(), timerange::count, timerange::defaulttype, DO, emalloc(), error(), EXIT_FAILURE, fprintf, free, i, INT64_FORMAT, timerange::leapbase, leapcnt, timerange::leapcount, limitrange(), lo_time, max_time, MAXALIGN, mkdirs(), PG_INT32_MAX, PG_INT32_MIN, puttzcode(), puttzcodepass(), qsort, size_product(), generate_unaccent_rules::stdout, strerror, tadd(), timecnt, tm, generate_unaccent_rules::type, attype::type, typecnt, types, TZ_MAGIC, TZ_MAX_CHARS, TZ_MAX_TIMES, TZ_MAX_TYPES, tzhead::tzh_charcnt, tzhead::tzh_leapcnt, tzhead::tzh_magic, tzhead::tzh_timecnt, tzhead::tzh_ttisstdcnt, tzhead::tzh_ttisutcnt, tzhead::tzh_typecnt, tzhead::tzh_version, want_bloat(), warning(), WORK_AROUND_QTBUG_53071, and ZIC_MAX.

Referenced by outzone().

2082 {
2083  FILE *fp;
2084  ptrdiff_t i,
2085  j;
2086  int pass;
2087  static const struct tzhead tzh0;
2088  static struct tzhead tzh;
2089  bool dir_checked = false;
2090  zic_t one = 1;
2091  zic_t y2038_boundary = one << 31;
2092  ptrdiff_t nats = timecnt + WORK_AROUND_QTBUG_53071;
2093 
2094  /*
2095  * Allocate the ATS and TYPES arrays via a single malloc, as this is a bit
2096  * faster.
2097  */
2098  zic_t *ats = emalloc(MAXALIGN(size_product(nats, sizeof *ats + 1)));
2099  void *typesptr = ats + nats;
2100  unsigned char *types = typesptr;
2101  struct timerange rangeall,
2102  range32,
2103  range64;
2104 
2105  /*
2106  * Sort.
2107  */
2108  if (timecnt > 1)
2109  qsort(attypes, timecnt, sizeof *attypes, atcomp);
2110 
2111  /*
2112  * Optimize.
2113  */
2114  {
2115  ptrdiff_t fromi,
2116  toi;
2117 
2118  toi = 0;
2119  fromi = 0;
2120  for (; fromi < timecnt; ++fromi)
2121  {
2122  if (toi != 0
2123  && ((attypes[fromi].at
2124  + utoffs[attypes[toi - 1].type])
2125  <= (attypes[toi - 1].at
2126  + utoffs[toi == 1 ? 0
2127  : attypes[toi - 2].type])))
2128  {
2129  attypes[toi - 1].type =
2130  attypes[fromi].type;
2131  continue;
2132  }
2133  if (toi == 0
2134  || attypes[fromi].dontmerge
2135  || (utoffs[attypes[toi - 1].type]
2136  != utoffs[attypes[fromi].type])
2137  || (isdsts[attypes[toi - 1].type]
2138  != isdsts[attypes[fromi].type])
2139  || (desigidx[attypes[toi - 1].type]
2140  != desigidx[attypes[fromi].type]))
2141  attypes[toi++] = attypes[fromi];
2142  }
2143  timecnt = toi;
2144  }
2145 
2146  if (noise && timecnt > 1200)
2147  {
2148  if (timecnt > TZ_MAX_TIMES)
2149  warning(_("reference clients mishandle"
2150  " more than %d transition times"),
2151  TZ_MAX_TIMES);
2152  else
2153  warning(_("pre-2014 clients may mishandle"
2154  " more than 1200 transition times"));
2155  }
2156 
2157  /*
2158  * Transfer.
2159  */
2160  for (i = 0; i < timecnt; ++i)
2161  {
2162  ats[i] = attypes[i].at;
2163  types[i] = attypes[i].type;
2164  }
2165 
2166  /*
2167  * Correct for leap seconds.
2168  */
2169  for (i = 0; i < timecnt; ++i)
2170  {
2171  j = leapcnt;
2172  while (--j >= 0)
2173  if (ats[i] > trans[j] - corr[j])
2174  {
2175  ats[i] = tadd(ats[i], corr[j]);
2176  break;
2177  }
2178  }
2179 
2180  /*
2181  * Work around QTBUG-53071 for timestamps less than y2038_boundary - 1, by
2182  * inserting a no-op transition at time y2038_boundary - 1. This works
2183  * only for timestamps before the boundary, which should be good enough in
2184  * practice as QTBUG-53071 should be long-dead by 2038. Do this after
2185  * correcting for leap seconds, as the idea is to insert a transition just
2186  * before 32-bit pg_time_t rolls around, and this occurs at a slightly
2187  * different moment if transitions are leap-second corrected.
2188  */
2189  if (WORK_AROUND_QTBUG_53071 && timecnt != 0 && want_bloat()
2190  && ats[timecnt - 1] < y2038_boundary - 1 && strchr(string, '<'))
2191  {
2192  ats[timecnt] = y2038_boundary - 1;
2193  types[timecnt] = types[timecnt - 1];
2194  timecnt++;
2195  }
2196 
2197  rangeall.defaulttype = defaulttype;
2198  rangeall.base = rangeall.leapbase = 0;
2199  rangeall.count = timecnt;
2200  rangeall.leapcount = leapcnt;
2201  range64 = limitrange(rangeall, lo_time, hi_time, ats, types);
2202  range32 = limitrange(range64, PG_INT32_MIN, PG_INT32_MAX, ats, types);
2203 
2204  /*
2205  * Remove old file, if any, to snap links.
2206  */
2207  if (remove(name) == 0)
2208  dir_checked = true;
2209  else if (errno != ENOENT)
2210  {
2211  const char *e = strerror(errno);
2212 
2213  fprintf(stderr, _("%s: Cannot remove %s/%s: %s\n"),
2214  progname, directory, name, e);
2215  exit(EXIT_FAILURE);
2216  }
2217  fp = fopen(name, "wb");
2218  if (!fp)
2219  {
2220  int fopen_errno = errno;
2221 
2222  if (fopen_errno == ENOENT && !dir_checked)
2223  {
2224  mkdirs(name, true);
2225  fp = fopen(name, "wb");
2226  fopen_errno = errno;
2227  }
2228  if (!fp)
2229  {
2230  fprintf(stderr, _("%s: Cannot create %s/%s: %s\n"),
2231  progname, directory, name, strerror(fopen_errno));
2232  exit(EXIT_FAILURE);
2233  }
2234  }
2235  for (pass = 1; pass <= 2; ++pass)
2236  {
2237  ptrdiff_t thistimei,
2238  thistimecnt,
2239  thistimelim;
2240  int thisleapi,
2241  thisleapcnt,
2242  thisleaplim;
2243  int currenttype,
2244  thisdefaulttype;
2245  bool locut,
2246  hicut;
2247  zic_t lo;
2248  int old0;
2249  char omittype[TZ_MAX_TYPES];
2250  int typemap[TZ_MAX_TYPES];
2251  int thistypecnt,
2252  stdcnt,
2253  utcnt;
2254  char thischars[TZ_MAX_CHARS];
2255  int thischarcnt;
2256  bool toomanytimes;
2257  int indmap[TZ_MAX_CHARS];
2258 
2259  if (pass == 1)
2260  {
2261  /*
2262  * Arguably the default time type in the 32-bit data should be
2263  * range32.defaulttype, which is suited for timestamps just before
2264  * PG_INT32_MIN. However, zic traditionally used the time type of
2265  * the indefinite past instead. Internet RFC 8532 says readers
2266  * should ignore 32-bit data, so this discrepancy matters only to
2267  * obsolete readers where the traditional type might be more
2268  * appropriate even if it's "wrong". So, use the historical zic
2269  * value, unless -r specifies a low cutoff that excludes some
2270  * 32-bit timestamps.
2271  */
2272  thisdefaulttype = (lo_time <= PG_INT32_MIN
2273  ? range64.defaulttype
2274  : range32.defaulttype);
2275 
2276  thistimei = range32.base;
2277  thistimecnt = range32.count;
2278  toomanytimes = thistimecnt >> 31 >> 1 != 0;
2279  thisleapi = range32.leapbase;
2280  thisleapcnt = range32.leapcount;
2281  locut = PG_INT32_MIN < lo_time;
2282  hicut = hi_time < PG_INT32_MAX;
2283  }
2284  else
2285  {
2286  thisdefaulttype = range64.defaulttype;
2287  thistimei = range64.base;
2288  thistimecnt = range64.count;
2289  toomanytimes = thistimecnt >> 31 >> 31 >> 2 != 0;
2290  thisleapi = range64.leapbase;
2291  thisleapcnt = range64.leapcount;
2292  locut = min_time < lo_time;
2293  hicut = hi_time < max_time;
2294  }
2295  if (toomanytimes)
2296  error(_("too many transition times"));
2297 
2298  /*
2299  * Keep the last too-low transition if no transition is exactly at LO.
2300  * The kept transition will be output as a LO "transition"; see
2301  * "Output a LO_TIME transition" below. This is needed when the
2302  * output is truncated at the start, and is also useful when catering
2303  * to buggy 32-bit clients that do not use time type 0 for timestamps
2304  * before the first transition.
2305  */
2306  if (0 < thistimei && ats[thistimei] != lo_time)
2307  {
2308  thistimei--;
2309  thistimecnt++;
2310  locut = false;
2311  }
2312 
2313  thistimelim = thistimei + thistimecnt;
2314  thisleaplim = thisleapi + thisleapcnt;
2315  if (thistimecnt != 0)
2316  {
2317  if (ats[thistimei] == lo_time)
2318  locut = false;
2319  if (hi_time < ZIC_MAX && ats[thistimelim - 1] == hi_time + 1)
2320  hicut = false;
2321  }
2322  memset(omittype, true, typecnt);
2323  omittype[thisdefaulttype] = false;
2324  for (i = thistimei; i < thistimelim; i++)
2325  omittype[types[i]] = false;
2326 
2327  /*
2328  * Reorder types to make THISDEFAULTTYPE type 0. Use TYPEMAP to swap
2329  * OLD0 and THISDEFAULTTYPE so that THISDEFAULTTYPE appears as type 0
2330  * in the output instead of OLD0. TYPEMAP also omits unused types.
2331  */
2332  old0 = strlen(omittype);
2333 
2334 #ifndef LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH
2335 
2336  /*
2337  * For some pre-2011 systems: if the last-to-be-written standard (or
2338  * daylight) type has an offset different from the most recently used
2339  * offset, append an (unused) copy of the most recently used type (to
2340  * help get global "altzone" and "timezone" variables set correctly).
2341  */
2342  if (want_bloat())
2343  {
2344  int mrudst,
2345  mrustd,
2346  hidst,
2347  histd,
2348  type;
2349 
2350  hidst = histd = mrudst = mrustd = -1;
2351  for (i = thistimei; i < thistimelim; ++i)
2352  if (isdsts[types[i]])
2353  mrudst = types[i];
2354  else
2355  mrustd = types[i];
2356  for (i = old0; i < typecnt; i++)
2357  {
2358  int h = (i == old0 ? thisdefaulttype
2359  : i == thisdefaulttype ? old0 : i);
2360 
2361  if (!omittype[h])
2362  {
2363  if (isdsts[h])
2364  hidst = i;
2365  else
2366  histd = i;
2367  }
2368  }
2369  if (hidst >= 0 && mrudst >= 0 && hidst != mrudst &&
2370  utoffs[hidst] !=