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 linkat(fromdir, from, todir, to, flag)   (itssymlink(from) ? (errno = ENOTSUP, -1) : link(from, to))
 
#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 LC_RULE   0
 
#define LC_ZONE   1
 
#define LC_LINK   2
 
#define LC_LEAP   3
 
#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_FROM   1
 
#define LF_TO   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 YR_MINIMUM   0
 
#define YR_MAXIMUM   1
 
#define YR_ONLY   2
 
#define TIME_T_BITS_IN_FILE   64
 
#define ZIC_BLOAT_DEFAULT   "fat"
 
#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 *fromname, const char *toname)
 
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, bool, 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 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 bool yearistype (zic_t year, const char *type)
 
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 *from, char const *to)
 
static int rcomp (const void *cp1, const void *cp2)
 
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 char * shellquote (char *b, char const *s)
 
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 const char * psxrules
 
static const char * lcltime
 
static const char * directory
 
static const char * leapsec
 
static const char * tzdefault
 
static const char * yitcommand
 
static int bloat
 

Macro Definition Documentation

◆ DC_DOM

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

Definition at line 94 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 95 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 96 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().

◆ LC_LEAP

#define LC_LEAP   3

Definition at line 204 of file zic.c.

Referenced by infile().

◆ LC_LINK

#define LC_LINK   2

Definition at line 203 of file zic.c.

Referenced by infile().

◆ LC_RULE

#define LC_RULE   0

Definition at line 201 of file zic.c.

Referenced by infile().

◆ LC_ZONE

#define LC_ZONE   1

Definition at line 202 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_FROM

#define LF_FROM   1

Definition at line 254 of file zic.c.

Referenced by inlink().

◆ LF_TO

#define LF_TO   2

Definition at line 255 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 (   fromdir,
  from,
  todir,
  to,
  flag 
)    (itssymlink(from) ? (errno = ENOTSUP, -1) : link(from, to))

Definition at line 41 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 inleap().

◆ LP_MONTH

#define LP_MONTH   2

Definition at line 263 of file zic.c.

Referenced by inleap().

◆ 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 inleap().

◆ LP_YEAR

#define LP_YEAR   1

Definition at line 262 of file zic.c.

Referenced by inleap().

◆ 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 576 of file zic.c.

◆ YR_MAXIMUM

#define YR_MAXIMUM   1

Definition at line 275 of file zic.c.

Referenced by rulesub().

◆ YR_MINIMUM

#define YR_MINIMUM   0

Definition at line 274 of file zic.c.

Referenced by rulesub().

◆ YR_ONLY

#define YR_ONLY   2

Definition at line 276 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   "fat"

Definition at line 639 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 59 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 159 of file zic.c.

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

◆ anonymous enum

anonymous enum
Enumerator
WORK_AROUND_QTBUG_53071 

Definition at line 169 of file zic.c.

Function Documentation

◆ abbroffset()

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

Definition at line 2553 of file zic.c.

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

Referenced by doabbr().

2554 {
2555  char sign = '+';
2556  int seconds,
2557  minutes;
2558 
2559  if (offset < 0)
2560  {
2561  offset = -offset;
2562  sign = '-';
2563  }
2564 
2565  seconds = offset % SECSPERMIN;
2566  offset /= SECSPERMIN;
2567  minutes = offset % MINSPERHOUR;
2568  offset /= MINSPERHOUR;
2569  if (100 <= offset)
2570  {
2571  error(_("%%z UT offset magnitude exceeds 99:59:59"));
2572  return "%z";
2573  }
2574  else
2575  {
2576  char *p = buf;
2577 
2578  *p++ = sign;
2579  *p++ = '0' + offset / 10;
2580  *p++ = '0' + offset % 10;
2581  if (minutes | seconds)
2582  {
2583  *p++ = '0' + minutes / 10;
2584  *p++ = '0' + minutes % 10;
2585  if (seconds)
2586  {
2587  *p++ = '0' + seconds / 10;
2588  *p++ = '0' + seconds % 10;
2589  }
2590  }
2591  *p = '\0';
2592  return buf;
2593  }
2594 }
#define SECSPERMIN
Definition: private.h:101
char sign
Definition: informix.c:668
static char * buf
Definition: pg_test_fsync.c:67
static void static void error(const char *string,...) pg_attribute_printf(1
Definition: zic.c:498
#define _(x)
Definition: elog.c:87
#define MINSPERHOUR
Definition: private.h:102

◆ addtt()

static void addtt ( zic_t  starttime,
int  type 
)
static

Definition at line 3317 of file zic.c.

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

Referenced by outzone().

3318 {
3320  attypes[timecnt].at = starttime;
3321  attypes[timecnt].dontmerge = false;
3322  attypes[timecnt].type = type;
3323  ++timecnt;
3324 }
unsigned char type
Definition: zic.c:388
static void * growalloc(void *ptr, size_t itemsize, ptrdiff_t nitems, ptrdiff_t *nitems_alloc)
Definition: zic.c:446
zic_t at
Definition: zic.c:386
static ptrdiff_t timecnt_alloc
Definition: zic.c:194
static struct attype * attypes
static ptrdiff_t timecnt
Definition: zic.c:193
bool dontmerge
Definition: zic.c:387

◆ addtype()

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

Definition at line 3327 of file zic.c.

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

Referenced by outzone(), and writezone().

3328 {
3329  int i,
3330  j;
3331 
3332  if (!(-1L - 2147483647L <= utoff && utoff <= 2147483647L))
3333  {
3334  error(_("UT offset out of range"));
3335  exit(EXIT_FAILURE);
3336  }
3337  if (!want_bloat())
3338  ttisstd = ttisut = false;
3339 
3340  for (j = 0; j < charcnt; ++j)
3341  if (strcmp(&chars[j], abbr) == 0)
3342  break;
3343  if (j == charcnt)
3344  newabbr(abbr);
3345  else
3346  {
3347  /* If there's already an entry, return its index. */
3348  for (i = 0; i < typecnt; i++)
3349  if (utoff == utoffs[i] && isdst == isdsts[i] && j == desigidx[i]
3350  && ttisstd == ttisstds[i] && ttisut == ttisuts[i])
3351  return i;
3352  }
3353 
3354  /*
3355  * There isn't one; add a new one, unless there are already too many.
3356  */
3357  if (typecnt >= TZ_MAX_TYPES)
3358  {
3359  error(_("too many local time types"));
3360  exit(EXIT_FAILURE);
3361  }
3362  i = typecnt++;
3363  utoffs[i] = utoff;
3364  isdsts[i] = isdst;
3365  ttisstds[i] = ttisstd;
3366  ttisuts[i] = ttisut;
3367  desigidx[i] = j;
3368  return i;
3369 }
static bool ttisstds[TZ_MAX_TYPES]
Definition: zic.c:393
static int typecnt
Definition: zic.c:195
static char isdsts[TZ_MAX_TYPES]
Definition: zic.c:391
static zic_t utoffs[TZ_MAX_TYPES]
Definition: zic.c:390
static int charcnt
Definition: zic.c:174
#define TZ_MAX_TYPES
Definition: tzfile.h:103
static void newabbr(const char *abbr)
Definition: zic.c:3915
int i
#define EXIT_FAILURE
Definition: settings.h:153
static void static void error(const char *string,...) pg_attribute_printf(1
Definition: zic.c:498
static bool ttisuts[TZ_MAX_TYPES]
Definition: zic.c:394
static char chars[TZ_MAX_CHARS]
Definition: zic.c:395
#define _(x)
Definition: elog.c:87
static bool want_bloat(void)
Definition: zic.c:633
static unsigned char desigidx[TZ_MAX_TYPES]
Definition: zic.c:392

◆ adjleap()

static void adjleap ( void  )
static

Definition at line 3401 of file zic.c.

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

Referenced by main().

3402 {
3403  int i;
3404  zic_t last = 0;
3405  zic_t prevtrans = 0;
3406 
3407  /*
3408  * propagate leap seconds forward
3409  */
3410  for (i = 0; i < leapcnt; ++i)
3411  {
3412  if (trans[i] - prevtrans < 28 * SECSPERDAY)
3413  {
3414  error(_("Leap seconds too close together"));
3415  exit(EXIT_FAILURE);
3416  }
3417  prevtrans = trans[i];
3418  trans[i] = tadd(trans[i], last);
3419  last = corr[i] += last;
3420  }
3421 }
static zic_t corr[TZ_MAX_LEAPS]
Definition: zic.c:397
#define SECSPERDAY
Definition: private.h:108
static zic_t tadd(zic_t t1, zic_t t2)
Definition: zic.c:3777
static int leapcnt
Definition: zic.c:178
int64 zic_t
Definition: zic.c:25
static zic_t trans[TZ_MAX_LEAPS]
Definition: zic.c:396
int i
#define EXIT_FAILURE
Definition: settings.h:153
static void static void error(const char *string,...) pg_attribute_printf(1
Definition: zic.c:498
#define _(x)
Definition: elog.c:87

◆ associate()

static void associate ( void  )
static

Definition at line 1148 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().

1149 {
1150  struct zone *zp;
1151  struct rule *rp;
1152  ptrdiff_t i,
1153  j,
1154  base,
1155  out;
1156 
1157  if (nrules != 0)
1158  {
1159  qsort(rules, nrules, sizeof *rules, rcomp);
1160  for (i = 0; i < nrules - 1; ++i)
1161  {
1162  if (strcmp(rules[i].r_name,
1163  rules[i + 1].r_name) != 0)
1164  continue;
1165  if (strcmp(rules[i].r_filename,
1166  rules[i + 1].r_filename) == 0)
1167  continue;
1168  eat(rules[i].r_filename, rules[i].r_linenum);
1169  warning(_("same rule name in multiple files"));
1170  eat(rules[i + 1].r_filename, rules[i + 1].r_linenum);
1171  warning(_("same rule name in multiple files"));
1172  for (j = i + 2; j < nrules; ++j)
1173  {
1174  if (strcmp(rules[i].r_name,
1175  rules[j].r_name) != 0)
1176  break;
1177  if (strcmp(rules[i].r_filename,
1178  rules[j].r_filename) == 0)
1179  continue;
1180  if (strcmp(rules[i + 1].r_filename,
1181  rules[j].r_filename) == 0)
1182  continue;
1183  break;
1184  }
1185  i = j - 1;
1186  }
1187  }
1188  for (i = 0; i < nzones; ++i)
1189  {
1190  zp = &zones[i];
1191  zp->z_rules = NULL;
1192  zp->z_nrules = 0;
1193  }
1194  for (base = 0; base < nrules; base = out)
1195  {
1196  rp = &rules[base];
1197  for (out = base + 1; out < nrules; ++out)
1198  if (strcmp(rp->r_name, rules[out].r_name) != 0)
1199  break;
1200  for (i = 0; i < nzones; ++i)
1201  {
1202  zp = &zones[i];
1203  if (strcmp(zp->z_rule, rp->r_name) != 0)
1204  continue;
1205  zp->z_rules = rp;
1206  zp->z_nrules = out - base;
1207  }
1208  }
1209  for (i = 0; i < nzones; ++i)
1210  {
1211  zp = &zones[i];
1212  if (zp->z_nrules == 0)
1213  {
1214  /*
1215  * Maybe we have a local standard time offset.
1216  */
1217  eat(zp->z_filename, zp->z_linenum);
1218  zp->z_save = getsave(zp->z_rule, &zp->z_isdst);
1219 
1220  /*
1221  * Note, though, that if there's no rule, a '%s' in the format is
1222  * a bad thing.
1223  */
1224  if (zp->z_format_specifier == 's')
1225  error("%s", _("%s in ruleless zone"));
1226  }
1227  }
1228  if (errors)
1229  exit(EXIT_FAILURE);
1230 }
lineno_t r_linenum
Definition: zic.c:64
static int rcomp(const void *cp1, const void *cp2)
Definition: zic.c:1141
zic_t z_save
Definition: zic.c:110
static void static void static void warning(const char *string,...) pg_attribute_printf(1
Definition: zic.c:509
static bool errors
Definition: zic.c:175
static ptrdiff_t nzones
Definition: zic.c:283
bool z_isdst
Definition: zic.c:109
Definition: localtime.c:79
char z_format_specifier
Definition: zic.c:107
char * z_rule
Definition: zic.c:105
const char * r_name
Definition: zic.c:65
const char * z_filename
Definition: zic.c:100
static struct rule * rules
Definition: zic.c:278
const char * r_filename
Definition: zic.c:63
static void eat(char const *name, lineno_t num)
Definition: zic.c:476
ptrdiff_t z_nrules
Definition: zic.c:113
lineno_t z_linenum
Definition: zic.c:101
static zic_t getsave(char *, bool *)
Definition: zic.c:1415
static ptrdiff_t nrules
Definition: zic.c:279
static struct zone * zones
Definition: zic.c:282
struct rule * z_rules
Definition: zic.c:112
Definition: zic.c:98
int i
#define EXIT_FAILURE
Definition: settings.h:153
#define qsort(a, b, c, d)
Definition: port.h:488
static void static void error(const char *string,...) pg_attribute_printf(1
Definition: zic.c:498
#define _(x)
Definition: elog.c:87

◆ atcomp()

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

Definition at line 2004 of file zic.c.

Referenced by writezone().

2005 {
2006  const zic_t a = ((const struct attype *) avp)->at;
2007  const zic_t b = ((const struct attype *) bvp)->at;
2008 
2009  return (a < b) ? -1 : (a > b);
2010 }
Definition: zic.c:384
int64 zic_t
Definition: zic.c:25

◆ byword()

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

Definition at line 3656 of file zic.c.

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

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

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

◆ change_directory()

static void change_directory ( char const *  dir)
static

Definition at line 556 of file zic.c.

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

Referenced by main().

557 {
558  if (chdir(dir) != 0)
559  {
560  int chdir_errno = errno;
561 
562  if (chdir_errno == ENOENT)
563  {
564  mkdirs(dir, false);
565  chdir_errno = chdir(dir) == 0 ? 0 : errno;
566  }
567  if (chdir_errno != 0)
568  {
569  fprintf(stderr, _("%s: Can't chdir to %s: %s\n"),
570  progname, dir, strerror(chdir_errno));
571  exit(EXIT_FAILURE);
572  }
573  }
574 }
#define fprintf
Definition: port.h:196
static void mkdirs(char const *, bool)
Definition: zic.c:3953
static const char * progname
Definition: zic.c:192
#define strerror
Definition: port.h:205
#define EXIT_FAILURE
Definition: settings.h:153
#define _(x)
Definition: elog.c:87

◆ ciequal()

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

Definition at line 3619 of file zic.c.

References lowerit().

Referenced by byword().

3620 {
3621  while (lowerit(*ap) == lowerit(*bp++))
3622  if (*ap++ == '\0')
3623  return true;
3624  return false;
3625 }
static char lowerit(char)
Definition: zic.c:3556

◆ ciprefix()

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

Definition at line 3645 of file zic.c.

References lowerit().

Referenced by byword().

3646 {
3647  do
3648  if (!*abbr)
3649  return true;
3650  while (lowerit(*abbr++) == lowerit(*word++));
3651 
3652  return false;
3653 }
static char lowerit(char)
Definition: zic.c:3556
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 521 of file zic.c.

References _, EXIT_FAILURE, fprintf, and strerror.

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

522 {
523  char const *e = (ferror(stream) ? _("I/O error")
524  : fclose(stream) != 0 ? strerror(errno) : NULL);
525 
526  if (e)
527  {
528  fprintf(stderr, "%s: %s%s%s%s%s\n", progname,
529  dir ? dir : "", dir ? "/" : "",
530  name ? name : "", name ? ": " : "",
531  e);
532  exit(EXIT_FAILURE);
533  }
534 }
#define fprintf
Definition: port.h:196
static const char * progname
Definition: zic.c:192
#define strerror
Definition: port.h:205
const char * name
Definition: encode.c:521
e
Definition: preproc-init.c:82
#define EXIT_FAILURE
Definition: settings.h:153
#define _(x)
Definition: elog.c:87

◆ componentcheck()

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

Definition at line 852 of file zic.c.

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

Referenced by namecheck().

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

◆ convert()

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

Definition at line 1959 of file zic.c.

References i.

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

1960 {
1961  int i;
1962  int shift;
1963  unsigned char *const b = (unsigned char *) buf;
1964 
1965  for (i = 0, shift = 24; i < 4; ++i, shift -= 8)
1966  b[i] = val >> shift;
1967 }
static char * buf
Definition: pg_test_fsync.c:67
int i
long val
Definition: informix.c:664

◆ convert64()

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

Definition at line 1970 of file zic.c.

References i.

Referenced by puttzcodepass().

1971 {
1972  int i;
1973  int shift;
1974  unsigned char *const b = (unsigned char *) buf;
1975 
1976  for (i = 0, shift = 56; i < 8; ++i, shift -= 8)
1977  b[i] = val >> shift;
1978 }
static char * buf
Definition: pg_test_fsync.c:67
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 2597 of file zic.c.

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

Referenced by outzone(), and stringzone().

2599 {
2600  char *cp;
2601  char *slashp;
2602  size_t len;
2603  char const *format = zp->z_format;
2604 
2605  slashp = strchr(format, '/');
2606  if (slashp == NULL)
2607  {
2608  char letterbuf[PERCENT_Z_LEN_BOUND + 1];
2609 
2610  if (zp->z_format_specifier == 'z')
2611  letters = abbroffset(letterbuf, zp->z_stdoff + save);
2612  else if (!letters)
2613  letters = "%s";
2614  sprintf(abbr, format, letters);
2615  }
2616  else if (isdst)
2617  {
2618  strcpy(abbr, slashp + 1);
2619  }
2620  else
2621  {
2622  memcpy(abbr, format, slashp - format);
2623  abbr[slashp - format] = '\0';
2624  }
2625  len = strlen(abbr);
2626  if (!doquotes)
2627  return len;
2628  for (cp = abbr; is_alpha(*cp); cp++)
2629  continue;
2630  if (len > 0 && *cp == '\0')
2631  return len;
2632  abbr[len + 2] = '\0';
2633  abbr[len + 1] = '>';
2634  memmove(abbr + 1, abbr, len);
2635  abbr[0] = '<';
2636  return len + 2;
2637 }
static char const * abbroffset(char *buf, zic_t offset)
Definition: zic.c:2553
#define sprintf
Definition: port.h:194
static bool is_alpha(char a)
Definition: zic.c:3491
#define memmove(d, s, c)
Definition: c.h:1267
static char format

◆ dolink()

static void dolink ( const char *  fromfield,
const char *  tofield,
bool  staysymlink 
)
static

Definition at line 997 of file zic.c.

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

Referenced by main().

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

◆ eat()

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

Definition at line 476 of file zic.c.

References eats().

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

477 {
478  eats(name, num, NULL, -1);
479 }
const char * name
Definition: encode.c:521
static void eats(char const *name, lineno_t num, char const *rname, lineno_t rnum)
Definition: zic.c:467

◆ eats()

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

Definition at line 467 of file zic.c.

References name.

Referenced by eat(), and outzone().

468 {
469  filename = name;
470  linenum = num;
471  rfilename = rname;
472  rlinenum = rnum;
473 }
static lineno_t rlinenum
Definition: zic.c:191
static const char * filename
Definition: zic.c:177
static lineno_t linenum
Definition: zic.c:182
static const char * rfilename
Definition: zic.c:190
const char * name
Definition: encode.c:521

◆ ecpyalloc()

static char* ecpyalloc ( char const *  str)
static

Definition at line 440 of file zic.c.

References memcheck().

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

441 {
442  return memcheck(strdup(str));
443 }
static void * memcheck(void *ptr)
Definition: zic.c:420

◆ emalloc()

static void* emalloc ( size_t  size)
static

Definition at line 428 of file zic.c.

References malloc, and memcheck().

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

429 {
430  return memcheck(malloc(size));
431 }
#define malloc(a)
Definition: header.h:50
static void * memcheck(void *ptr)
Definition: zic.c:420

◆ erealloc()

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

Definition at line 434 of file zic.c.

References memcheck(), and realloc.

Referenced by growalloc().

435 {
436  return memcheck(realloc(ptr, size));
437 }
#define realloc(a, b)
Definition: header.h:60
static void * memcheck(void *ptr)
Definition: zic.c:420

◆ error()

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

Definition at line 498 of file zic.c.

References generate_unaccent_rules::args, and verror().

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

499 {
500  va_list args;
501 
502  va_start(args, string);
503  verror(string, args);
504  va_end(args);
505  errors = true;
506 }
static bool errors
Definition: zic.c:175
static void verror(const char *string, va_list args) pg_attribute_printf(1
Definition: zic.c:482

◆ getfields()

static char ** getfields ( char *  buf)
static

Definition at line 3722 of file zic.c.

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

Referenced by infile().

3723 {
3724  char *dp;
3725  char **array;
3726  int nsubs;
3727 
3728  if (cp == NULL)
3729  return NULL;
3730  array = emalloc(size_product(strlen(cp) + 1, sizeof *array));
3731  nsubs = 0;
3732  for (;;)
3733  {
3734  while (is_space(*cp))
3735  ++cp;
3736  if (*cp == '\0' || *cp == '#')
3737  break;
3738  array[nsubs++] = dp = cp;
3739  do
3740  {
3741  if ((*dp = *cp++) != '"')
3742  ++dp;
3743  else
3744  while ((*dp = *cp++) != '"')
3745  if (*dp != '\0')
3746  ++dp;
3747  else
3748  {
3749  error(_("Odd number of quotation marks"));
3750  exit(EXIT_FAILURE);
3751  }
3752  } while (*cp && *cp != '#' && !is_space(*cp));
3753  if (is_space(*cp))
3754  ++cp;
3755  *dp = '\0';
3756  }
3757  array[nsubs] = NULL;
3758  return array;
3759 }
static bool is_space(char a)
Definition: zic.c:3473
#define EXIT_FAILURE
Definition: settings.h:153
static void static void error(const char *string,...) pg_attribute_printf(1
Definition: zic.c:498
#define _(x)
Definition: elog.c:87
static size_t size_product(size_t nitems, size_t itemsize)
Definition: zic.c:412
static void * emalloc(size_t size)
Definition: zic.c:428

◆ gethms()

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

Definition at line 1337 of file zic.c.

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

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

1338 {
1339  /* PG: make hh be int not zic_t to avoid sscanf portability issues */
1340  int hh;
1341  int sign,
1342  mm = 0,
1343  ss = 0;
1344  char hhx,
1345  mmx,
1346  ssx,
1347  xr = '0',
1348  xs;
1349  int tenths = 0;
1350  bool ok = true;
1351 
1352  if (string == NULL || *string == '\0')
1353  return 0;
1354  if (*string == '-')
1355  {
1356  sign = -1;
1357  ++string;
1358  }
1359  else
1360  sign = 1;
1361  switch (sscanf(string,
1362  "%d%c%d%c%d%c%1d%*[0]%c%*[0123456789]%c",
1363  &hh, &hhx, &mm, &mmx, &ss, &ssx, &tenths, &xr, &xs))
1364  {
1365  default:
1366  ok = false;
1367  break;
1368  case 8:
1369  ok = '0' <= xr && xr <= '9';
1370  /* fallthrough */
1371  case 7:
1372  ok &= ssx == '.';
1373  if (ok && noise)
1374  warning(_("fractional seconds rejected by"
1375  " pre-2018 versions of zic"));
1376  /* fallthrough */
1377  case 5:
1378  ok &= mmx == ':';
1379  /* fallthrough */
1380  case 3:
1381  ok &= hhx == ':';
1382  /* fallthrough */
1383  case 1:
1384  break;
1385  }
1386  if (!ok)
1387  {
1388  error("%s", errstring);
1389  return 0;
1390  }
1391  if (hh < 0 ||
1392  mm < 0 || mm >= MINSPERHOUR ||
1393  ss < 0 || ss > SECSPERMIN)
1394  {
1395  error("%s", errstring);
1396  return 0;
1397  }
1398  /* Some compilers warn that this test is unsatisfiable for 32-bit ints */
1399 #if INT_MAX > PG_INT32_MAX
1400  if (ZIC_MAX / SECSPERHOUR < hh)
1401  {
1402  error(_("time overflow"));
1403  return 0;
1404  }
1405 #endif
1406  ss += 5 + ((ss ^ 1) & (xr == '0')) <= tenths; /* Round to even. */
1407  if (noise && (hh > HOURSPERDAY ||
1408  (hh == HOURSPERDAY && (mm != 0 || ss != 0))))
1409  warning(_("values over 24 hours not handled by pre-2007 versions of zic"));
1410  return oadd(sign * (zic_t) hh * SECSPERHOUR,
1411  sign * (mm * SECSPERMIN + ss));
1412 }
#define SECSPERMIN
Definition: private.h:101
static void static void static void warning(const char *string,...) pg_attribute_printf(1
Definition: zic.c:509
#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:187
static void static void error(const char *string,...) pg_attribute_printf(1
Definition: zic.c:498
#define _(x)
Definition: elog.c:87
static zic_t oadd(zic_t t1, zic_t t2)
Definition: zic.c:3769
#define MINSPERHOUR
Definition: private.h:102

◆ getsave()

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

Definition at line 1415 of file zic.c.

References _, and gethms().

Referenced by associate(), and inrule().

1416 {
1417  int dst = -1;
1418  zic_t save;
1419  size_t fieldlen = strlen(field);
1420 
1421  if (fieldlen != 0)
1422  {
1423  char *ep = field + fieldlen - 1;
1424 
1425  switch (*ep)
1426  {
1427  case 'd':
1428  dst = 1;
1429  *ep = '\0';
1430  break;
1431  case 's':
1432  dst = 0;
1433  *ep = '\0';
1434  break;
1435  }
1436  }
1437  save = gethms(field, _("invalid saved time"));
1438  *isdst = dst < 0 ? save != 0 : dst;
1439  return save;
1440 }
static zic_t gethms(const char *string, const char *errstring)
Definition: zic.c:1337
int64 zic_t
Definition: zic.c:25
#define _(x)
Definition: elog.c:87

◆ growalloc()

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

Definition at line 446 of file zic.c.

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

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

447 {
448  if (nitems < *nitems_alloc)
449  return ptr;
450  else
451  {
452  ptrdiff_t nitems_max = PTRDIFF_MAX - WORK_AROUND_QTBUG_53071;
453  ptrdiff_t amax = nitems_max < SIZE_MAX ? nitems_max : SIZE_MAX;
454 
455  if ((amax - 1) / 3 * 2 < *nitems_alloc)
456  memory_exhausted(_("integer overflow"));
457  *nitems_alloc += (*nitems_alloc >> 1) + 1;
458  return erealloc(ptr, size_product(*nitems_alloc, itemsize));
459  }
460 }
#define SIZE_MAX
Definition: c.h:453
static ptrdiff_t const PTRDIFF_MAX
Definition: zic.c:51
static void memory_exhausted(const char *msg) pg_attribute_noreturn()
Definition: zic.c:405
#define _(x)
Definition: elog.c:87
static size_t size_product(size_t nitems, size_t itemsize)
Definition: zic.c:412
static void * erealloc(void *ptr, size_t size)
Definition: zic.c:434

◆ hardlinkerr()

static int hardlinkerr ( char const *  from,
char const *  to 
)
static

Definition at line 989 of file zic.c.

References linkat.

Referenced by dolink().

990 {
991  int r = linkat(AT_FDCWD, from, AT_FDCWD, to, AT_SYMLINK_FOLLOW);
992 
993  return r == 0 ? 0 : errno;
994 }
#define linkat(fromdir, from, todir, to, flag)
Definition: zic.c:41

◆ infile()

static void infile ( const char *  filename)
static

Definition at line 1233 of file zic.c.

References _, buf, byword(), close_file(), eat(), error(), EXIT_FAILURE, fprintf, free, getfields(), inleap(), inlink(), inrule(), inzcont(), inzone(), lookup::l_value, 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().

1234 {
1235  FILE *fp;
1236  char **fields;
1237  char *cp;
1238  const struct lookup *lp;
1239  int nfields;
1240  bool wantcont;
1241  lineno_t num;
1242  char buf[BUFSIZ];
1243 
1244  if (strcmp(name, "-") == 0)
1245  {
1246  name = _("standard input");
1247  fp = stdin;
1248  }
1249  else if ((fp = fopen(name, "r")) == NULL)
1250  {
1251  const char *e = strerror(errno);
1252 
1253  fprintf(stderr, _("%s: Cannot open %s: %s\n"),
1254  progname, name, e);
1255  exit(EXIT_FAILURE);
1256  }
1257  wantcont = false;
1258  for (num = 1;; ++num)
1259  {
1260  eat(name, num);
1261  if (fgets(buf, sizeof buf, fp) != buf)
1262  break;
1263  cp = strchr(buf, '\n');
1264  if (cp == NULL)
1265  {
1266  error(_("line too long"));
1267  exit(EXIT_FAILURE);
1268  }
1269  *cp = '\0';
1270  fields = getfields(buf);
1271  nfields = 0;
1272  while (fields[nfields] != NULL)
1273  {
1274  static char nada;
1275 
1276  if (strcmp(fields[nfields], "-") == 0)
1277  fields[nfields] = &nada;
1278  ++nfields;
1279  }
1280  if (nfields == 0)
1281  {
1282  /* nothing to do */
1283  }
1284  else if (wantcont)
1285  {
1286  wantcont = inzcont(fields, nfields);
1287  }
1288  else
1289  {
1290  struct lookup const *line_codes
1292 
1293  lp = byword(fields[0], line_codes);
1294  if (lp == NULL)
1295  error(_("input line of unknown type"));
1296  else
1297  switch (lp->l_value)
1298  {
1299  case LC_RULE:
1300  inrule(fields, nfields);
1301  wantcont = false;
1302  break;
1303  case LC_ZONE:
1304  wantcont = inzone(fields, nfields);
1305  break;
1306  case LC_LINK:
1307  inlink(fields, nfields);
1308  wantcont = false;
1309  break;
1310  case LC_LEAP:
1311  inleap(fields, nfields);
1312  wantcont = false;
1313  break;
1314  default: /* "cannot happen" */
1315  fprintf(stderr,
1316  _("%s: panic: Invalid l_value %d\n"),
1317  progname, lp->l_value);
1318  exit(EXIT_FAILURE);
1319  }
1320  }
1321  free(fields);
1322  }
1323  close_file(fp, NULL, filename);
1324  if (wantcont)
1325  error(_("expected continuation line not found"));
1326 }
static struct lookup const zi_line_codes[]
Definition: zic.c:307
static struct lookup const leap_line_codes[]
Definition: zic.c:313
static void inrule(char **fields, int nfields)
Definition: zic.c:1443
#define LC_LEAP
Definition: zic.c:204
static const char * leapsec
Definition: zic.c:623
#define fprintf
Definition: port.h:196
const int l_value
Definition: zic.c:301
static const char * filename
Definition: zic.c:177
static void inleap(char **fields, int nfields)
Definition: zic.c:1638
static char ** getfields(char *buf)
Definition: zic.c:3722
static bool inzcont(char **fields, int nfields)
Definition: zic.c:1528
static char * buf
Definition: pg_test_fsync.c:67
Definition: zic.c:298
#define LC_LINK
Definition: zic.c:203
static void eat(char const *name, lineno_t num)
Definition: zic.c:476
#define LC_ZONE
Definition: zic.c:202
static const char * progname
Definition: zic.c:192
#define free(a)
Definition: header.h:65
static bool inzone(char **fields, int nfields)
Definition: zic.c:1490
static void inlink(char **fields, int nfields)
Definition: zic.c:1758
#define strerror
Definition: port.h:205
static void close_file(FILE *stream, char const *dir, char const *name)
Definition: zic.c:521
static struct lookup const * byword(const char *string, const struct lookup *lp)
Definition: zic.c:3656
const char * name
Definition: encode.c:521
e
Definition: preproc-init.c:82
#define EXIT_FAILURE
Definition: settings.h:153
int lineno_t
Definition: zic.c:59
static void static void error(const char *string,...) pg_attribute_printf(1
Definition: zic.c:498
#define LC_RULE
Definition: zic.c:201
#define _(x)
Definition: elog.c:87

◆ inleap()

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

Definition at line 1638 of file zic.c.

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

Referenced by infile().

1639 {
1640  const char *cp;
1641  const struct lookup *lp;
1642  zic_t i,
1643  j;
1644 
1645  /* PG: make year be int not zic_t to avoid sscanf portability issues */
1646  int year;
1647  int month,
1648  day;
1649  zic_t dayoff,
1650  tod;
1651  zic_t t;
1652  char xs;
1653 
1654  if (nfields != LEAP_FIELDS)
1655  {
1656  error(_("wrong number of fields on Leap line"));
1657  return;
1658  }
1659  dayoff = 0;
1660  cp = fields[LP_YEAR];
1661  if (sscanf(cp, "%d%c", &year, &xs) != 1)
1662  {
1663  /*
1664  * Leapin' Lizards!
1665  */
1666  error(_("invalid leaping year"));
1667  return;
1668  }
1669  if (!leapseen || leapmaxyear < year)
1670  leapmaxyear = year;
1671  if (!leapseen || leapminyear > year)
1672  leapminyear = year;
1673  leapseen = true;
1674  j = EPOCH_YEAR;
1675  while (j != year)
1676  {
1677  if (year > j)
1678  {
1679  i = len_years[isleap(j)];
1680  ++j;
1681  }
1682  else
1683  {
1684  --j;
1685  i = -len_years[isleap(j)];
1686  }
1687  dayoff = oadd(dayoff, i);
1688  }
1689  if ((lp = byword(fields[LP_MONTH], mon_names)) == NULL)
1690  {
1691  error(_("invalid month name"));
1692  return;
1693  }
1694  month = lp->l_value;
1695  j = TM_JANUARY;
1696  while (j != month)
1697  {
1698  i = len_months[isleap(year)][j];
1699  dayoff = oadd(dayoff, i);
1700  ++j;
1701  }
1702  cp = fields[LP_DAY];
1703  if (sscanf(cp, "%d%c", &day, &xs) != 1 ||
1704  day <= 0 || day > len_months[isleap(year)][month])
1705  {
1706  error(_("invalid day of month"));
1707  return;
1708  }
1709  dayoff = oadd(dayoff, day - 1);
1710  if (dayoff < min_time / SECSPERDAY)
1711  {
1712  error(_("time too small"));
1713  return;
1714  }
1715  if (dayoff > max_time / SECSPERDAY)
1716  {
1717  error(_("time too large"));
1718  return;
1719  }
1720  t = dayoff * SECSPERDAY;
1721  tod = gethms(fields[LP_TIME], _("invalid time of day"));
1722  cp = fields[LP_CORR];
1723  {
1724  bool positive;
1725  int count;
1726 
1727  if (strcmp(cp, "") == 0)
1728  { /* infile() turns "-" into "" */
1729  positive = false;
1730  count = 1;
1731  }
1732  else if (strcmp(cp, "+") == 0)
1733  {
1734  positive = true;
1735  count = 1;
1736  }
1737  else
1738  {
1739  error(_("illegal CORRECTION field on Leap line"));
1740  return;
1741  }
1742  if ((lp = byword(fields[LP_ROLL], leap_types)) == NULL)
1743  {
1744  error(_("illegal Rolling/Stationary field on Leap line"));
1745  return;
1746  }
1747  t = tadd(t, tod);
1748  if (t < 0)
1749  {
1750  error(_("leap second precedes Epoch"));
1751  return;
1752  }
1753  leapadd(t, positive, lp->l_value, count);
1754  }
1755 }
#define LP_CORR
Definition: zic.c:266
static zic_t leapmaxyear
Definition: zic.c:181
#define SECSPERDAY
Definition: private.h:108
#define isleap(y)
Definition: datetime.h:271
static const int len_months[2][MONSPERYEAR]
Definition: zic.c:375
const int l_value
Definition: zic.c:301
#define LP_ROLL
Definition: zic.c:267
static zic_t tadd(zic_t t1, zic_t t2)
Definition: zic.c:3777
static zic_t gethms(const char *string, const char *errstring)
Definition: zic.c:1337
#define LEAP_FIELDS
Definition: zic.c:268
static struct lookup const mon_names[]
Definition: zic.c:318
#define LP_DAY
Definition: zic.c:264
static bool leapseen
Definition: zic.c:179
int64 zic_t
Definition: zic.c:25
Definition: zic.c:298
static void leapadd(zic_t, bool, int, int)
Definition: zic.c:3372
#define EPOCH_YEAR
Definition: private.h:134
#define LP_TIME
Definition: zic.c:265
static zic_t const max_time
Definition: zic.c:580
#define TM_JANUARY
Definition: private.h:119
static struct lookup const * byword(const char *string, const struct lookup *lp)
Definition: zic.c:3656
static zic_t leapminyear
Definition: zic.c:180
#define LP_YEAR
Definition: zic.c:262
int i
static struct lookup const leap_types[]
Definition: zic.c:369
static const int len_years[2]
Definition: zic.c:380
static void static void error(const char *string,...) pg_attribute_printf(1
Definition: zic.c:498
static zic_t const min_time
Definition: zic.c:579
#define LP_MONTH
Definition: zic.c:263
#define _(x)
Definition: elog.c:87
static zic_t oadd(zic_t t1, zic_t t2)
Definition: zic.c:3769

◆ inlink()

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

Definition at line 1758 of file zic.c.

References _, ecpyalloc(), error(), filename, growalloc(), link::l_filename, link::l_from, link::l_linenum, link::l_to, LF_FROM, LF_TO, linenum, LINK_FIELDS, and namecheck().

Referenced by infile().

1759 {
1760  struct link l;
1761 
1762  if (nfields != LINK_FIELDS)
1763  {
1764  error(_("wrong number of fields on Link line"));
1765  return;
1766  }
1767  if (*fields[LF_FROM] == '\0')
1768  {
1769  error(_("blank FROM field on Link line"));
1770  return;
1771  }
1772  if (!namecheck(fields[LF_TO]))
1773  return;
1774  l.l_filename = filename;
1775  l.l_linenum = linenum;
1776  l.l_from = ecpyalloc(fields[LF_FROM]);
1777  l.l_to = ecpyalloc(fields[LF_TO]);
1778  links = growalloc(links, sizeof *links, nlinks, &nlinks_alloc);
1779  links[nlinks++] = l;
1780 }
static ptrdiff_t nlinks
Definition: zic.c:295
static char * ecpyalloc(char const *str)
Definition: zic.c:440
#define LF_TO
Definition: zic.c:255
static const char * filename
Definition: zic.c:177
static lineno_t linenum
Definition: zic.c:182
static void * growalloc(void *ptr, size_t itemsize, ptrdiff_t nitems, ptrdiff_t *nitems_alloc)
Definition: zic.c:446
static ptrdiff_t nlinks_alloc
Definition: zic.c:296
#define LF_FROM
Definition: zic.c:254
static struct link * links
Definition: zic.c:294
#define LINK_FIELDS
Definition: zic.c:256
static void static void error(const char *string,...) pg_attribute_printf(1
Definition: zic.c:498
#define _(x)
Definition: elog.c:87
static bool namecheck(const char *name)
Definition: zic.c:896

◆ inrule()

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

Definition at line 1443 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().

1444 {
1445  static struct rule r;
1446 
1447  if (nfields != RULE_FIELDS)
1448  {
1449  error(_("wrong number of fields on Rule line"));
1450  return;
1451  }
1452  switch (*fields[RF_NAME])
1453  {
1454  case '\0':
1455  case ' ':
1456  case '\f':
1457  case '\n':
1458  case '\r':
1459  case '\t':
1460  case '\v':
1461  case '+':
1462  case '-':
1463  case '0':
1464  case '1':
1465  case '2':
1466  case '3':
1467  case '4':
1468  case '5':
1469  case '6':
1470  case '7':
1471  case '8':
1472  case '9':
1473  error(_("Invalid rule name \"%s\""), fields[RF_NAME]);
1474  return;
1475  }
1476  r.r_filename = filename;
1477  r.r_linenum = linenum;
1478  r.r_save = getsave(fields[RF_SAVE], &r.r_isdst);
1479  rulesub(&r, fields[RF_LOYEAR], fields[RF_HIYEAR], fields[RF_COMMAND],
1480  fields[RF_MONTH], fields[RF_DAY], fields[RF_TOD]);
1481  r.r_name = ecpyalloc(fields[RF_NAME]);
1482  r.r_abbrvar = ecpyalloc(fields[RF_ABBRVAR]);
1483  if (max_abbrvar_len < strlen(r.r_abbrvar))
1484  max_abbrvar_len = strlen(r.r_abbrvar);
1485  rules = growalloc(rules, sizeof *rules, nrules, &nrules_alloc);
1486  rules[nrules++] = r;
1487 }
static char * ecpyalloc(char const *str)
Definition: zic.c:440
#define RF_COMMAND
Definition: zic.c:242
Definition: localtime.c:79
static const char * filename
Definition: zic.c:177
static lineno_t linenum
Definition: zic.c:182
static int max_abbrvar_len
Definition: zic.c:183
static struct rule * rules
Definition: zic.c:278
static void * growalloc(void *ptr, size_t itemsize, ptrdiff_t nitems, ptrdiff_t *nitems_alloc)
Definition: zic.c:446
#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:280
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:1783
static zic_t getsave(char *, bool *)
Definition: zic.c:1415
static ptrdiff_t nrules
Definition: zic.c:279
#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:498
#define RF_LOYEAR
Definition: zic.c:240
#define _(x)
Definition: elog.c:87
#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 1528 of file zic.c.

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

Referenced by infile().

1529 {
1530  if (nfields < ZONEC_MINFIELDS || nfields > ZONEC_MAXFIELDS)
1531  {
1532  error(_("wrong number of fields on Zone continuation line"));
1533  return false;
1534  }
1535  return inzsub(fields, nfields, true);
1536 }
#define ZONEC_MAXFIELDS
Definition: zic.c:233
static bool inzsub(char **, int, bool)
Definition: zic.c:1539
static void static void error(const char *string,...) pg_attribute_printf(1
Definition: zic.c:498
#define _(x)
Definition: elog.c:87

◆ inzone()

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

Definition at line 1490 of file zic.c.

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

Referenced by infile().

1491 {
1492  ptrdiff_t i;
1493 
1494  if (nfields < ZONE_MINFIELDS || nfields > ZONE_MAXFIELDS)
1495  {
1496  error(_("wrong number of fields on Zone line"));
1497  return false;
1498  }
1499  if (lcltime != NULL && strcmp(fields[ZF_NAME], tzdefault) == 0)
1500  {
1501  error(
1502  _("\"Zone %s\" line and -l option are mutually exclusive"),
1503  tzdefault);
1504  return false;
1505  }
1506  if (strcmp(fields[ZF_NAME], TZDEFRULES) == 0 && psxrules != NULL)
1507  {
1508  error(
1509  _("\"Zone %s\" line and -p option are mutually exclusive"),
1510  TZDEFRULES);
1511  return false;
1512  }
1513  for (i = 0; i < nzones; ++i)
1514  if (zones[i].z_name != NULL &&
1515  strcmp(zones[i].z_name, fields[ZF_NAME]) == 0)
1516  {
1517  error(_("duplicate zone name %s"
1518  " (file \"%s\", line %d)"),
1519  fields[ZF_NAME],
1520  zones[i].z_filename,
1521  zones[i].z_linenum);
1522  return false;
1523  }
1524  return inzsub(fields, nfields, false);
1525 }
#define ZF_NAME
Definition: zic.c:210
static ptrdiff_t nzones
Definition: zic.c:283
static const char * psxrules
Definition: zic.c:620
static bool inzsub(char **, int, bool)
Definition: zic.c:1539
#define ZONE_MAXFIELDS
Definition: zic.c:219
static const char * lcltime
Definition: zic.c:621
#define TZDEFRULES
Definition: tzfile.h:28
static struct zone * zones
Definition: zic.c:282
int i
static const char * tzdefault
Definition: zic.c:624
static void static void error(const char *string,...) pg_attribute_printf(1
Definition: zic.c:498
#define _(x)
Definition: elog.c:87

◆ inzsub()

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

Definition at line 1539 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().

1540 {
1541  char *cp;
1542  char *cp1;
1543  static struct zone z;
1544  int i_stdoff,
1545  i_rule,
1546  i_format;
1547  int i_untilyear,
1548  i_untilmonth;
1549  int i_untilday,
1550  i_untiltime;
1551  bool hasuntil;
1552 
1553  if (iscont)
1554  {
1555  i_stdoff = ZFC_STDOFF;
1556  i_rule = ZFC_RULE;
1557  i_format = ZFC_FORMAT;
1558  i_untilyear = ZFC_TILYEAR;
1559  i_untilmonth = ZFC_TILMONTH;
1560  i_untilday = ZFC_TILDAY;
1561  i_untiltime = ZFC_TILTIME;
1562  z.z_name = NULL;
1563  }
1564  else if (!namecheck(fields[ZF_NAME]))
1565  return false;
1566  else
1567  {
1568  i_stdoff = ZF_STDOFF;
1569  i_rule = ZF_RULE;
1570  i_format = ZF_FORMAT;
1571  i_untilyear = ZF_TILYEAR;
1572  i_untilmonth = ZF_TILMONTH;
1573  i_untilday = ZF_TILDAY;
1574  i_untiltime = ZF_TILTIME;
1575  z.z_name = ecpyalloc(fields[ZF_NAME]);
1576  }
1577  z.z_filename = filename;
1578  z.z_linenum = linenum;
1579  z.z_stdoff = gethms(fields[i_stdoff], _("invalid UT offset"));
1580  if ((cp = strchr(fields[i_format], '%')) != NULL)
1581  {
1582  if ((*++cp != 's' && *cp != 'z') || strchr(cp, '%')
1583  || strchr(fields[i_format], '/'))
1584  {
1585  error(_("invalid abbreviation format"));
1586  return false;
1587  }
1588  }
1589  z.z_rule = ecpyalloc(fields[i_rule]);
1590  z.z_format = cp1 = ecpyalloc(fields[i_format]);
1591  z.z_format_specifier = cp ? *cp : '\0';
1592  if (z.z_format_specifier == 'z')
1593  {
1594  if (noise)
1595  warning(_("format '%s' not handled by pre-2015 versions of zic"),
1596  z.z_format);
1597  cp1[cp - fields[i_format]] = 's';
1598  }
1599  if (max_format_len < strlen(z.z_format))
1600  max_format_len = strlen(z.z_format);
1601  hasuntil = nfields > i_untilyear;
1602  if (hasuntil)
1603  {
1604  z.z_untilrule.r_filename = filename;
1605  z.z_untilrule.r_linenum = linenum;
1606  rulesub(&z.z_untilrule,
1607  fields[i_untilyear],
1608  "only",
1609  "",
1610  (nfields > i_untilmonth) ?
1611  fields[i_untilmonth] : "Jan",
1612  (nfields > i_untilday) ? fields[i_untilday] : "1",
1613  (nfields > i_untiltime) ? fields[i_untiltime] : "0");
1614  z.z_untiltime = rpytime(&z.z_untilrule,
1615  z.z_untilrule.r_loyear);
1616  if (iscont && nzones > 0 &&
1617  z.z_untiltime > min_time &&
1618  z.z_untiltime < max_time &&
1619  zones[nzones - 1].z_untiltime > min_time &&
1620  zones[nzones - 1].z_untiltime < max_time &&
1621  zones[nzones - 1].z_untiltime >= z.z_untiltime)
1622  {
1623  error(_("Zone continuation line end time is not after end time of previous line"));
1624  return false;
1625  }
1626  }
1627  zones = growalloc(zones, sizeof *zones, nzones, &nzones_alloc);
1628  zones[nzones++] = z;
1629 
1630  /*
1631  * If there was an UNTIL field on this line, there's more information
1632  * about the zone on the next line.
1633  */
1634  return hasuntil;
1635 }
#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:440
#define ZF_RULE
Definition: zic.c:212
static void static void static void warning(const char *string,...) pg_attribute_printf(1
Definition: zic.c:509
#define ZF_STDOFF
Definition: zic.c:211
zic_t z_untiltime
Definition: zic.c:116
static ptrdiff_t nzones
Definition: zic.c:283
#define ZFC_FORMAT
Definition: zic.c:227
static int max_format_len
Definition: zic.c:184
static const char * filename
Definition: zic.c:177
#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:1337
static lineno_t linenum
Definition: zic.c:182
static ptrdiff_t nzones_alloc
Definition: zic.c:284
#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:446
#define ZFC_RULE
Definition: zic.c:226
static zic_t rpytime(const struct rule *rp, zic_t wantedy)
Definition: zic.c:3806
#define ZF_TILDAY
Definition: zic.c:216
static zic_t const max_time
Definition: zic.c:580
static bool noise
Definition: zic.c:187
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:1783
static struct zone * zones
Definition: zic.c:282
Definition: zic.c:98
#define ZFC_TILDAY
Definition: zic.c:230
static void static void error(const char *string,...) pg_attribute_printf(1
Definition: zic.c:498
static zic_t const min_time
Definition: zic.c:579
#define ZFC_TILYEAR
Definition: zic.c:228
#define _(x)
Definition: elog.c:87
static bool namecheck(const char *name)
Definition: zic.c:896

◆ is_alpha()

static bool is_alpha ( char  a)
static

Definition at line 3491 of file zic.c.

Referenced by doabbr(), and newabbr().

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

◆ is_space()

static bool is_space ( char  a)
static

Definition at line 3473 of file zic.c.

Referenced by getfields().

3474 {
3475  switch (a)
3476  {
3477  default:
3478  return false;
3479  case ' ':
3480  case '\f':
3481  case '\n':
3482  case '\r':
3483  case '\t':
3484  case '\v':
3485  return true;
3486  }
3487 }

◆ itsabbr()

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

Definition at line 3628 of file zic.c.

References lowerit(), and word().

Referenced by byword().

3629 {
3630  if (lowerit(*abbr) != lowerit(*word))
3631  return false;
3632  ++word;
3633  while (*++abbr != '\0')
3634  do
3635  {
3636  if (*word == '\0')
3637  return false;
3638  } while (lowerit(*word++) != lowerit(*abbr));
3639  return true;
3640 }
static char lowerit(char)
Definition: zic.c:3556
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 1096 of file zic.c.

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

Referenced by dolink(), and mkdirs().

1097 {
1098  struct stat st;
1099  int res = stat(name, &st);
1100 #ifdef S_ISDIR
1101  if (res == 0)
1102  return S_ISDIR(st.st_mode) != 0;
1103 #endif
1104  if (res == 0 || errno == EOVERFLOW)
1105  {
1106  size_t n = strlen(name);
1107  char *nameslashdot = emalloc(n + 3);
1108  bool dir;
1109 
1110  memcpy(nameslashdot, name, n);
1111  strcpy(&nameslashdot[n], &"/."[!(n && name[n - 1] != '/')]);
1112  dir = stat(nameslashdot, &st) == 0 || errno == EOVERFLOW;
1113  free(nameslashdot);
1114  return dir;
1115  }
1116  return false;
1117 }
#define stat(a, b)
Definition: win32_port.h:255
#define free(a)
Definition: header.h:65
const char * name
Definition: encode.c:521
#define S_ISDIR(m)
Definition: win32_port.h:296
#define EOVERFLOW
Definition: private.h:41
static void * emalloc(size_t size)
Definition: zic.c:428

◆ itssymlink()

static bool itssymlink ( char const *  name)
static

Definition at line 1121 of file zic.c.

References readlink.

Referenced by dolink().

1122 {
1123 #ifdef HAVE_SYMLINK
1124  char c;
1125 
1126  return 0 <= readlink(name, &c, 1);
1127 #else
1128  return false;
1129 #endif
1130 }
char * c
#define readlink(path, buf, size)
Definition: win32_port.h:222
const char * name
Definition: encode.c:521

◆ leapadd()

static void leapadd ( zic_t  t,
bool  positive,
int  rolling,
int  count 
)
static

Definition at line 3372 of file zic.c.

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

Referenced by inleap().

3373 {
3374  int i,
3375  j;
3376 
3377  if (leapcnt + (positive ? count : 1) > TZ_MAX_LEAPS)
3378  {
3379  error(_("too many leap seconds"));
3380  exit(EXIT_FAILURE);
3381  }
3382  for (i = 0; i < leapcnt; ++i)
3383  if (t <= trans[i])
3384  break;
3385  do
3386  {
3387  for (j = leapcnt; j > i; --j)
3388  {
3389  trans[j] = trans[j - 1];
3390  corr[j] = corr[j - 1];
3391  roll[j] = roll[j - 1];
3392  }
3393  trans[i] = t;
3394  corr[i] = positive ? 1 : -count;
3395  roll[i] = rolling;
3396  ++leapcnt;
3397  } while (positive && --count != 0);
3398 }
static zic_t corr[TZ_MAX_LEAPS]
Definition: zic.c:397
#define TZ_MAX_LEAPS
Definition: tzfile.h:108
static int leapcnt
Definition: zic.c:178
static zic_t trans[TZ_MAX_LEAPS]
Definition: zic.c:396
int i
#define EXIT_FAILURE
Definition: settings.h:153
static void static void error(const char *string,...) pg_attribute_printf(1
Definition: zic.c:498
#define _(x)
Definition: elog.c:87
static char roll[TZ_MAX_LEAPS]
Definition: zic.c:398

◆ 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 2022 of file zic.c.

References timerange::defaulttype, types, and ZIC_MAX.

Referenced by writezone().

2024 {
2025  while (0 < r.count && ats[r.base] < lo)
2026  {
2027  r.defaulttype = types[r.base];
2028  r.count--;
2029  r.base++;
2030  }
2031  while (0 < r.leapcount && trans[r.leapbase] < lo)
2032  {
2033  r.leapcount--;
2034  r.leapbase++;
2035  }
2036 
2037  if (hi < ZIC_MAX)
2038  {
2039  while (0 < r.count && hi + 1 < ats[r.base + r.count - 1])
2040  r.count--;
2041  while (0 < r.leapcount && hi + 1 < trans[r.leapbase + r.leapcount - 1])
2042  r.leapcount--;
2043  }
2044 
2045  return r;
2046 }
struct typedefs * types
Definition: ecpg.c:29
ptrdiff_t count
Definition: zic.c:2015
int leapbase
Definition: zic.c:2017
#define ZIC_MAX
Definition: zic.c:27
int defaulttype
Definition: zic.c:2014
int leapcount
Definition: zic.c:2017
ptrdiff_t base
Definition: zic.c:2015
static zic_t trans[TZ_MAX_LEAPS]
Definition: zic.c:396

◆ link()

int link ( const char *  fromname,
const char *  toname 
)

Referenced by durable_link_or_rename(), and mkdirs().

◆ lowerit()

static char lowerit ( char  a)
static

Definition at line 3556 of file zic.c.

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

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

◆ main()

int main ( int  argc,
char **  argv 
)

Definition at line 643 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.

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

◆ memcheck()

static void* memcheck ( void *  ptr)
static

Definition at line 420 of file zic.c.

References memory_exhausted(), and strerror.

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

421 {
422  if (ptr == NULL)
423  memory_exhausted(strerror(errno));
424  return ptr;
425 }
#define strerror
Definition: port.h:205
static void memory_exhausted(const char *msg) pg_attribute_noreturn()
Definition: zic.c:405

◆ memory_exhausted()

static void memory_exhausted ( const char *  msg)
static

Definition at line 405 of file zic.c.

References _, EXIT_FAILURE, and fprintf.

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

406 {
407  fprintf(stderr, _("%s: Memory exhausted: %s\n"), progname, msg);
408  exit(EXIT_FAILURE);
409 }
#define fprintf
Definition: port.h:196
static const char * progname
Definition: zic.c:192
#define EXIT_FAILURE
Definition: settings.h:153
#define _(x)
Definition: elog.c:87

◆ mkdirs()

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

Definition at line 3953 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().

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

◆ namecheck()

static bool namecheck ( const char *  name)
static

Definition at line 896 of file zic.c.

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

Referenced by inlink(), and inzsub().

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

◆ newabbr()

static void newabbr ( const char *  abbr)
static

Definition at line 3915 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().

3916 {
3917  int i;
3918 
3919  if (strcmp(string, GRANDPARENTED) != 0)
3920  {
3921  const char *cp;
3922  const char *mp;
3923 
3924  cp = string;
3925  mp = NULL;
3926  while (is_alpha(*cp) || ('0' <= *cp && *cp <= '9')
3927  || *cp == '-' || *cp == '+')
3928  ++cp;
3929  if (noise && cp - string < 3)
3930  mp = _("time zone abbreviation has fewer than 3 characters");
3931  if (cp - string > ZIC_MAX_ABBR_LEN_WO_WARN)
3932  mp = _("time zone abbreviation has too many characters");
3933  if (*cp != '\0')
3934  mp = _("time zone abbreviation differs from POSIX standard");
3935  if (mp != NULL)
3936  warning("%s (%s)", mp, string);
3937  }
3938  i = strlen(string) + 1;
3939  if (charcnt + i > TZ_MAX_CHARS)
3940  {
3941  error(_("too many, or too long, time zone abbreviations"));
3942  exit(EXIT_FAILURE);
3943  }
3944  strcpy(&chars[charcnt], string);
3945  charcnt += i;
3946 }
static void static void static void warning(const char *string,...) pg_attribute_printf(1
Definition: zic.c:509
#define GRANDPARENTED
Definition: private.h:30
static bool is_alpha(char a)
Definition: zic.c:3491
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:187
static int charcnt
Definition: zic.c:174
int i
#define EXIT_FAILURE
Definition: settings.h:153
static void static void error(const char *string,...) pg_attribute_printf(1
Definition: zic.c:498
static char chars[TZ_MAX_CHARS]
Definition: zic.c:395
#define _(x)
Definition: elog.c:87

◆ oadd()

static zic_t oadd ( zic_t  t1,
zic_t  t2 
)
static

Definition at line 3769 of file zic.c.

References time_overflow(), ZIC_MAX, and ZIC_MIN.

Referenced by gethms(), inleap(), outzone(), and rpytime().

3770 {
3771  if (t1 < 0 ? t2 < ZIC_MIN - t1 : ZIC_MAX - t1 < t2)
3772  time_overflow();
3773  return t1 + t2;
3774 }
#define ZIC_MAX
Definition: zic.c:27
#define ZIC_MIN
Definition: zic.c:26
static void time_overflow(void)
Definition: zic.c:3762

◆ outzone()

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

Definition at line 2915 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, rule::r_yrtype, rpytime(), stringzone(), tadd(), timecnt, TM_JANUARY, generate_unaccent_rules::type, attype::type, updateminmax(), want_bloat(), warning(), writezone(), yearistype(), 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().

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

◆ puttzcode()

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

Definition at line 1981 of file zic.c.

References buf, and convert().

Referenced by puttzcodepass(), and writezone().

1982 {
1983  char buf[4];
1984 
1985  convert(val, buf);
1986  fwrite(buf, sizeof buf, 1, fp);
1987 }
static void convert(const int32 val, char *const buf)
Definition: zic.c:1959
static char * buf
Definition: pg_test_fsync.c:67
long val
Definition: informix.c:664

◆ puttzcodepass()

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

Definition at line 1990 of file zic.c.

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

Referenced by writezone().

1991 {
1992  if (pass == 1)
1993  puttzcode(val, fp);
1994  else
1995  {
1996  char buf[8];
1997 
1998  convert64(val, buf);
1999  fwrite(buf, sizeof buf, 1, fp);
2000  }
2001 }
static char * buf
Definition: pg_test_fsync.c:67
long val
Definition: informix.c:664
static void puttzcode(const int32 val, FILE *const fp)
Definition: zic.c:1981
static void convert64(const zic_t val, char *const buf)
Definition: zic.c:1970

◆ rcomp()

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

Definition at line 1141 of file zic.c.

References rule::r_name.

Referenced by associate().

1142 {
1143  return strcmp(((const struct rule *) cp1)->r_name,
1144  ((const struct rule *) cp2)->r_name);
1145 }
Definition: localtime.c:79

◆ rpytime()

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

Definition at line 3806 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().

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

◆ rule_cmp()

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

Definition at line 2764 of file zic.c.

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

Referenced by stringzone().

2765 {
2766  if (!a)
2767  return -!!b;
2768  if (!b)
2769  return 1;
2770  if (a->r_hiyear != b->r_hiyear)
2771  return a->r_hiyear < b->r_hiyear ? -1 : 1;
2772  if (a->r_month - b->r_month != 0)
2773  return a->r_month - b->r_month;
2774  return a->r_dayofmonth - b->r_dayofmonth;
2775 }

◆ 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 1783 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, rule::r_yrtype, warning(), YR_MAXIMUM, YR_MINIMUM, YR_ONLY, ZIC_MAX, and ZIC_MIN.

Referenced by inrule(), and inzsub().

1786 {
1787  const struct lookup *lp;
1788  const char *cp;
1789  char *dp;
1790  char *ep;
1791  char xs;
1792 
1793  /* PG: year_tmp is to avoid sscanf portability issues */
1794  int year_tmp;
1795 
1796  if ((lp = byword(monthp, mon_names)) == NULL)
1797  {
1798  error(_("invalid month name"));
1799  return;
1800  }
1801  rp->r_month = lp->l_value;
1802  rp->r_todisstd = false;
1803  rp->r_todisut = false;
1804  dp = ecpyalloc(timep);
1805  if (*dp != '\0')
1806  {
1807  ep = dp + strlen(dp) - 1;
1808  switch (lowerit(*ep))
1809  {
1810  case 's': /* Standard */
1811  rp->r_todisstd = true;
1812  rp->r_todisut = false;
1813  *ep = '\0';
1814  break;
1815  case 'w': /* Wall */
1816  rp->r_todisstd = false;
1817  rp->r_todisut = false;
1818  *ep = '\0';
1819  break;
1820  case 'g': /* Greenwich */
1821  case 'u': /* Universal */
1822  case 'z': /* Zulu */
1823  rp->r_todisstd = true;
1824  rp->r_todisut = true;
1825  *ep = '\0';
1826  break;
1827  }
1828  }
1829  rp->r_tod = gethms(dp, _("invalid time of day"));
1830  free(dp);
1831 
1832  /*
1833  * Year work.
1834  */
1835  cp = loyearp;
1836  lp = byword(cp, begin_years);
1837  rp->r_lowasnum = lp == NULL;
1838  if (!rp->r_lowasnum)
1839  switch (lp->l_value)
1840  {
1841  case YR_MINIMUM:
1842  rp->r_loyear = ZIC_MIN;
1843  break;
1844  case YR_MAXIMUM:
1845  rp->r_loyear = ZIC_MAX;
1846  break;
1847  default: /* "cannot happen" */
1848  fprintf(stderr,
1849  _("%s: panic: Invalid l_value %d\n"),
1850  progname, lp->l_value);
1851  exit(EXIT_FAILURE);
1852  }
1853  else if (sscanf(cp, "%d%c", &year_tmp, &xs) == 1)
1854  rp->r_loyear = year_tmp;
1855  else
1856  {
1857  error(_("invalid starting year"));
1858  return;
1859  }
1860  cp = hiyearp;
1861  lp = byword(cp, end_years);
1862  rp->r_hiwasnum = lp == NULL;
1863  if (!rp->r_hiwasnum)
1864  switch (lp->l_value)
1865  {
1866  case YR_MINIMUM:
1867  rp->r_hiyear = ZIC_MIN;
1868  break;
1869  case YR_MAXIMUM:
1870  rp->r_hiyear = ZIC_MAX;
1871  break;
1872  case YR_ONLY:
1873  rp->r_hiyear = rp->r_loyear;
1874  break;
1875  default: /* "cannot happen" */
1876  fprintf(stderr,
1877  _("%s: panic: Invalid l_value %d\n"),
1878  progname, lp->l_value);
1879  exit(EXIT_FAILURE);
1880  }
1881  else if (sscanf(cp, "%d%c", &year_tmp, &xs) == 1)
1882  rp->r_hiyear = year_tmp;
1883  else
1884  {
1885  error(_("invalid ending year"));
1886  return;
1887  }
1888  if (rp->r_loyear > rp->r_hiyear)
1889  {
1890  error(_("starting year greater than ending year"));
1891  return;
1892  }
1893  if (*typep == '\0')
1894  rp->r_yrtype = NULL;
1895  else
1896  {
1897  if (rp->r_loyear == rp->r_hiyear)
1898  {
1899  error(_("typed single year"));
1900  return;
1901  }
1902  warning(_("year type \"%s\" is obsolete; use \"-\" instead"),
1903  typep);
1904  rp->r_yrtype = ecpyalloc(typep);
1905  }
1906 
1907  /*
1908  * Day work. Accept things such as: 1 lastSunday last-Sunday
1909  * (undocumented; warn about this) Sun<=20 Sun>=7
1910  */
1911  dp = ecpyalloc(dayp);
1912  if ((lp = byword(dp, lasts)) != NULL)
1913  {
1914  rp->r_dycode = DC_DOWLEQ;
1915  rp->r_wday = lp->l_value;
1916  rp->r_dayofmonth = len_months[1][rp->r_month];
1917  }
1918  else
1919  {
1920  if ((ep = strchr(dp, '<')) != NULL)
1921  rp->r_dycode = DC_DOWLEQ;
1922  else if ((ep = strchr(dp, '>')) != NULL)
1923  rp->r_dycode = DC_DOWGEQ;
1924  else
1925  {
1926  ep = dp;
1927  rp->r_dycode = DC_DOM;
1928  }
1929  if (rp->r_dycode != DC_DOM)
1930  {
1931  *ep++ = 0;
1932  if (*ep++ != '=')
1933  {
1934  error(_("invalid day of month"));
1935  free(dp);
1936  return;
1937  }
1938  if ((lp = byword(dp, wday_names)) == NULL)
1939  {
1940  error(_("invalid weekday name"));
1941  free(dp);
1942  return;
1943  }
1944  rp->r_wday = lp->l_value;
1945  }
1946  if (sscanf(ep, "%d%c", &rp->r_dayofmonth, &xs) != 1 ||
1947  rp->r_dayofmonth <= 0 ||
1948  (rp->r_dayofmonth > len_months[1][rp->r_month]))
1949  {
1950  error(_("invalid day of month"));
1951  free(dp);
1952  return;
1953  }
1954  }
1955  free(dp);
1956 }
#define YR_MINIMUM
Definition: zic.c:274
zic_t r_tod
Definition: zic.c:79
bool r_todisstd
Definition: zic.c:80
static char * ecpyalloc(char const *str)
Definition: zic.c:440
static void static void static void warning(const char *string,...) pg_attribute_printf(1
Definition: zic.c:509
int r_month
Definition: zic.c:73
#define DC_DOWGEQ
Definition: zic.c:95
static struct lookup const begin_years[]
Definition: zic.c:356
#define DC_DOM
Definition: zic.c:94
static const int len_months[2][MONSPERYEAR]
Definition: zic.c:375
#define fprintf
Definition: port.h:196
const int l_value
Definition: zic.c:301
bool r_lowasnum
Definition: zic.c:70
#define ZIC_MAX
Definition: zic.c:27
#define YR_ONLY
Definition: zic.c:276
static zic_t gethms(const char *string, const char *errstring)
Definition: zic.c:1337
static struct lookup const mon_names[]
Definition: zic.c:318
Definition: zic.c:298
zic_t r_hiyear
Definition: zic.c:68
const char * r_yrtype
Definition: zic.c:69
#define ZIC_MIN
Definition: zic.c:26
bool r_todisut
Definition: zic.c:81
static struct lookup const end_years[]
Definition: zic.c:362
int r_dycode
Definition: zic.c:75
#define DC_DOWLEQ
Definition: zic.c:96
static const char * progname
Definition: zic.c:192
#define free(a)
Definition: header.h:65
int r_dayofmonth
Definition: zic.c:76
int r_wday
Definition: zic.c:77
static struct lookup const * byword(const char *string, const struct lookup *lp)
Definition: zic.c:3656
static char lowerit(char)
Definition: zic.c:3556
#define YR_MAXIMUM
Definition: zic.c:275
static struct lookup const lasts[]
Definition: zic.c:345
bool r_hiwasnum
Definition: zic.c:71
static struct lookup const wday_names[]
Definition: zic.c:334
#define EXIT_FAILURE
Definition: settings.h:153
static void static void error(const char *string,...) pg_attribute_printf(1
Definition: zic.c:498
zic_t r_loyear
Definition: zic.c:67
#define _(x)
Definition: elog.c:87

◆ shellquote()

static char* shellquote ( char *  b,
char const *  s 
)
static

Definition at line 3424 of file zic.c.

Referenced by yearistype().

3425 {
3426  *b++ = '\'';
3427  while (*s)
3428  {
3429  if (*s == '\'')
3430  *b++ = '\'', *b++ = '\\', *b++ = '\'';
3431  *b++ = *s++;
3432  }
3433  *b++ = '\'';
3434  return b;
3435 }

◆ size_product()

static size_t size_product ( size_t  nitems,
size_t  itemsize 
)
static

Definition at line 412 of file zic.c.

References _, memory_exhausted(), and SIZE_MAX.

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

413 {
414  if (SIZE_MAX / itemsize < nitems)
415  memory_exhausted(_("size overflow"));
416  return nitems * itemsize;
417 }
#define SIZE_MAX
Definition: c.h:453
static void memory_exhausted(const char *msg) pg_attribute_noreturn()
Definition: zic.c:405
#define _(x)
Definition: elog.c:87

◆ stringoffset()

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

Definition at line 2649 of file zic.c.

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

Referenced by stringrule(), and stringzone().

2650 {
2651  int hours;
2652  int minutes;
2653  int seconds;
2654  bool negative = offset < 0;
2655  int len = negative;
2656 
2657  if (negative)
2658  {
2659  offset = -offset;
2660  result[0] = '-';
2661  }
2662  seconds = offset % SECSPERMIN;
2663  offset /= SECSPERMIN;
2664  minutes = offset % MINSPERHOUR;
2665  offset /= MINSPERHOUR;
2666  hours = offset;
2667  if (hours >= HOURSPERDAY * DAYSPERWEEK)
2668  {
2669  result[0] = '\0';
2670  return 0;
2671  }
2672  len += sprintf(result + len, "%d", hours);
2673  if (minutes != 0 || seconds != 0)
2674  {
2675  len += sprintf(result + len, ":%02d", minutes);
2676  if (seconds != 0)
2677  len += sprintf(result + len, ":%02d", seconds);
2678  }
2679  return len;
2680 }
#define SECSPERMIN
Definition: private.h:101
#define HOURSPERDAY
Definition: private.h:103
#define sprintf
Definition: port.h:194
#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 2683 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().

2684 {
2685  zic_t tod = rp->r_tod;
2686  int compat = 0;
2687 
2688  if (rp->r_dycode == DC_DOM)
2689  {
2690  int month,
2691  total;
2692 
2693  if (rp->r_dayofmonth == 29 && rp->r_month == TM_FEBRUARY)
2694  return -1;
2695  total = 0;
2696  for (month = 0; month < rp->r_month; ++month)
2697  total += len_months[0][month];
2698  /* Omit the "J" in Jan and Feb, as that's shorter. */
2699  if (rp->r_month <= 1)
2700  result += sprintf(result, "%d", total + rp->r_dayofmonth - 1);
2701  else
2702  result += sprintf(result, "J%d", total + rp->r_dayofmonth);
2703  }
2704  else
2705  {
2706  int week;
2707  int wday = rp->r_wday;
2708  int wdayoff;
2709 
2710  if (rp->r_dycode == DC_DOWGEQ)
2711  {
2712  wdayoff = (rp->r_dayofmonth - 1) % DAYSPERWEEK;
2713  if (wdayoff)
2714  compat = 2013;
2715  wday -= wdayoff;
2716  tod += wdayoff * SECSPERDAY;
2717  week = 1 + (rp->r_dayofmonth - 1) / DAYSPERWEEK;
2718  }
2719  else if (rp->r_dycode == DC_DOWLEQ)
2720  {
2721  if (rp->r_dayofmonth == len_months[1][rp->r_month])
2722  week = 5;
2723  else
2724  {
2725  wdayoff = rp->r_dayofmonth % DAYSPERWEEK;
2726  if (wdayoff)
2727  compat = 2013;
2728  wday -= wdayoff;
2729  tod += wdayoff * SECSPERDAY;
2730  week = rp->r_dayofmonth / DAYSPERWEEK;
2731  }
2732  }
2733  else
2734  return -1; /* "cannot happen" */
2735  if (wday < 0)
2736  wday += DAYSPERWEEK;
2737  result += sprintf(result, "M%d.%d.%d",
2738  rp->r_month + 1, week, wday);
2739  }
2740  if (rp->r_todisut)
2741  tod += stdoff;
2742  if (rp->r_todisstd && !rp->r_isdst)
2743  tod += save;
2744  if (tod != 2 * SECSPERMIN * MINSPERHOUR)
2745  {
2746  *result++ = '/';
2747  if (!stringoffset(result, tod))
2748  return -1;
2749  if (tod < 0)
2750  {
2751  if (compat < 2013)
2752  compat = 2013;
2753  }
2754  else if (SECSPERDAY <= tod)
2755  {
2756  if (compat < 1994)
2757  compat = 1994;
2758  }
2759  }
2760  return compat;
2761 }
#define SECSPERMIN
Definition: private.h:101
zic_t r_tod
Definition: zic.c:79
bool r_todisstd
Definition: zic.c:80
int r_month
Definition: zic.c:73
#define DC_DOWGEQ
Definition: zic.c:95
#define SECSPERDAY
Definition: private.h:108
#define DC_DOM
Definition: zic.c:94
static const int len_months[2][MONSPERYEAR]
Definition: zic.c:375
static int stringoffset(char *result, zic_t offset)
Definition: zic.c:2649
#define sprintf
Definition: port.h:194
#define DAYSPERWEEK
Definition: private.h:104
bool r_isdst
Definition: zic.c:82
int64 zic_t
Definition: zic.c:25
bool r_todisut
Definition: zic.c:81
enum COMPAT_MODE compat
Definition: ecpg.c:25
int r_dycode
Definition: zic.c:75
#define DC_DOWLEQ
Definition: zic.c:96
#define TM_FEBRUARY
Definition: private.h:120
int r_dayofmonth
Definition: zic.c:76
int r_wday
Definition: zic.c:77
#define MINSPERHOUR
Definition: private.h:102

◆ stringzone()

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

Definition at line 2778 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::r_yrtype, 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().

2779 {
2780  const struct zone *zp;
2781  struct rule *rp;
2782  struct rule *stdrp;
2783  struct rule *dstrp;
2784  ptrdiff_t i;
2785  const char *abbrvar;
2786  int compat = 0;
2787  int c;
2788  size_t len;
2789  int offsetlen;
2790  struct rule stdr,
2791  dstr;
2792 
2793  result[0] = '\0';
2794 
2795  /*
2796  * Internet RFC 8536 section 5.1 says to use an empty TZ string if future
2797  * timestamps are truncated.
2798  */
2799  if (hi_time < max_time)
2800  return -1;
2801 
2802  zp = zpfirst + zonecount - 1;
2803  stdrp = dstrp = NULL;
2804  for (i = 0; i < zp->z_nrules; ++i)
2805  {
2806  rp = &zp->z_rules[i];
2807  if (rp->r_hiwasnum || rp->r_hiyear != ZIC_MAX)
2808  continue;
2809  if (rp->r_yrtype != NULL)
2810  continue;
2811  if (!rp->r_isdst)
2812  {
2813  if (stdrp == NULL)
2814  stdrp = rp;
2815  else
2816  return -1;
2817  }
2818  else
2819  {
2820  if (dstrp == NULL)
2821  dstrp = rp;
2822  else
2823  return -1;
2824  }
2825  }
2826  if (stdrp == NULL && dstrp == NULL)
2827  {
2828  /*
2829  * There are no rules running through "max". Find the latest std rule
2830  * in stdabbrrp and latest rule of any type in stdrp.
2831  */
2832  struct rule *stdabbrrp = NULL;
2833 
2834  for (i = 0; i < zp->z_nrules; ++i)
2835  {
2836  rp = &zp->z_rules[i];
2837  if (!rp->r_isdst && rule_cmp(stdabbrrp, rp) < 0)
2838  stdabbrrp = rp;
2839  if (rule_cmp(stdrp, rp) < 0)
2840  stdrp = rp;
2841  }
2842  if (stdrp != NULL && stdrp->r_isdst)
2843  {
2844  /* Perpetual DST. */
2845  dstr.r_month = TM_JANUARY;
2846  dstr.r_dycode = DC_DOM;
2847  dstr.r_dayofmonth = 1;
2848  dstr.r_tod = 0;
2849  dstr.r_todisstd = dstr.r_todisut = false;
2850  dstr.r_isdst = stdrp->r_isdst;
2851  dstr.r_save = stdrp->r_save;
2852  dstr.r_abbrvar = stdrp->r_abbrvar;
2853  stdr.r_month = TM_DECEMBER;
2854  stdr.r_dycode = DC_DOM;
2855  stdr.r_dayofmonth = 31;
2856  stdr.r_tod = SECSPERDAY + stdrp->r_save;
2857  stdr.r_todisstd = stdr.r_todisut = false;
2858  stdr.r_isdst = false;
2859  stdr.r_save = 0;
2860  stdr.r_abbrvar
2861  = (stdabbrrp ? stdabbrrp->r_abbrvar : "");
2862  dstrp = &dstr;
2863  stdrp = &stdr;
2864  }
2865  }
2866  if (stdrp == NULL && (zp->z_nrules != 0 || zp->z_isdst))
2867  return -1;
2868  abbrvar = (stdrp == NULL) ? "" : stdrp->r_abbrvar;
2869  len = doabbr(result, zp, abbrvar, false, 0, true);
2870  offsetlen = stringoffset(result + len, -zp->z_stdoff);
2871  if (!offsetlen)
2872  {
2873  result[0] = '\0';
2874  return -1;
2875  }
2876  len += offsetlen;
2877  if (dstrp == NULL)
2878  return compat;
2879  len += doabbr(result + len, zp, dstrp->r_abbrvar,
2880  dstrp->r_isdst, dstrp->r_save, true);
2881  if (dstrp->r_save != SECSPERMIN * MINSPERHOUR)
2882  {
2883  offsetlen = stringoffset(result + len,
2884  -(zp->z_stdoff + dstrp->r_save));
2885  if (!offsetlen)
2886  {
2887  result[0] = '\0';
2888  return -1;
2889  }
2890  len += offsetlen;
2891  }
2892  result[len++] = ',';
2893  c = stringrule(result + len, dstrp, dstrp->r_save, zp->z_stdoff);
2894  if (c < 0)
2895  {
2896  result[0] = '\0';
2897  return -1;
2898  }
2899  if (compat < c)
2900  compat = c;
2901  len += strlen(result + len);
2902  result[len++] = ',';
2903  c = stringrule(result + len, stdrp, dstrp->r_save, zp->z_stdoff);
2904  if (c < 0)
2905  {
2906  result[0] = '\0';
2907  return -1;
2908  }
2909  if (compat < c)
2910  compat = c;
2911  return compat;
2912 }
#define SECSPERMIN
Definition: private.h:101
int r_month
Definition: zic.c:73
#define SECSPERDAY
Definition: private.h:108
zic_t r_save
Definition: zic.c:83
#define TM_DECEMBER
Definition: private.h:130
static int rule_cmp(struct rule const *a, struct rule const *b)
Definition: zic.c:2764
#define DC_DOM
Definition: zic.c:94
static zic_t hi_time
Definition: zic.c:585
static int stringoffset(char *result, zic_t offset)
Definition: zic.c:2649
bool z_isdst
Definition: zic.c:109
Definition: localtime.c:79
#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:2597
bool r_isdst
Definition: zic.c:82
char * c
static int stringrule(char *result, struct rule *const rp, zic_t save, zic_t stdoff)
Definition: zic.c:2683
zic_t r_hiyear
Definition: zic.c:68
const char * r_yrtype
Definition: zic.c:69
enum COMPAT_MODE compat
Definition: ecpg.c:25
const char * r_abbrvar
Definition: zic.c:84
static zic_t const max_time
Definition: zic.c:580
ptrdiff_t z_nrules
Definition: zic.c:113
#define TM_JANUARY
Definition: private.h:119
struct rule * z_rules
Definition: zic.c:112
Definition: zic.c:98
bool r_hiwasnum
Definition: zic.c:71
int i
#define MINSPERHOUR
Definition: private.h:102
zic_t z_stdoff
Definition: zic.c:104

◆ tadd()

static zic_t tadd ( zic_t  t1,
zic_t  t2 
)
static

Definition at line 3777 of file zic.c.

References max_time, min_time, and time_overflow().

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

3778 {
3779  if (t1 < 0)
3780  {
3781  if (t2 < min_time - t1)
3782  {
3783  if (t1 != min_time)
3784  time_overflow();
3785  return min_time;
3786  }
3787  }
3788  else
3789  {
3790  if (max_time - t1 < t2)
3791  {
3792  if (t1 != max_time)
3793  time_overflow();
3794  return max_time;
3795  }
3796  }
3797  return t1 + t2;
3798 }
static void time_overflow(void)
Definition: zic.c:3762
static zic_t const max_time
Definition: zic.c:580
static zic_t const min_time
Definition: zic.c:579

◆ time_overflow()

static void time_overflow ( void  )
static

Definition at line 3762 of file zic.c.

References _, error(), and EXIT_FAILURE.

Referenced by oadd(), and tadd().

3763 {
3764  error(_("time overflow"));
3765  exit(EXIT_FAILURE);
3766 }
#define EXIT_FAILURE
Definition: settings.h:153
static void static void error(const char *string,...) pg_attribute_printf(1
Definition: zic.c:498
#define _(x)
Definition: elog.c:87

◆ timerange_option()

static bool timerange_option ( char *  timerange)
static

Definition at line 590 of file zic.c.

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

Referenced by main().

591 {
592  int64 lo = min_time,
593  hi = max_time;
594  char *lo_end = timerange,
595  *hi_end;
596 
597  if (*timerange == '@')
598  {
599  errno = 0;
600  lo = strtoimax(timerange + 1, &lo_end, 10);
601  if (lo_end == timerange + 1 || (lo == PG_INT64_MAX && errno == ERANGE))
602  return false;
603  }
604  hi_end = lo_end;
605  if (lo_end[0] == '/' && lo_end[1] == '@')
606  {
607  errno = 0;
608  hi = strtoimax(lo_end + 2, &hi_end, 10);
609  if (hi_end == lo_end + 2 || hi == PG_INT64_MIN)
610  return false;
611  hi -= !(hi == PG_INT64_MAX && errno == ERANGE);
612  }
613  if (*hi_end || hi < lo || max_time < lo || hi < min_time)
614  return false;
615  lo_time = lo < min_time ? min_time : lo;
616  hi_time = max_time < hi ? max_time : hi;
617  return true;
618 }
#define PG_INT64_MAX
Definition: c.h:445
static zic_t lo_time
Definition: zic.c:584
static zic_t hi_time
Definition: zic.c:585
#define PG_INT64_MIN
Definition: c.h:444
#define strtoimax
Definition: private.h:52
static zic_t const max_time
Definition: zic.c:580
static zic_t const min_time
Definition: zic.c:579

◆ updateminmax()

static void updateminmax ( const zic_t  x)
static

Definition at line 2640 of file zic.c.

Referenced by outzone().

2641 {
2642  if (min_year > x)
2643  min_year = x;
2644  if (max_year < x)
2645  max_year = x;
2646 }
static zic_t min_year
Definition: zic.c:186
static zic_t max_year
Definition: zic.c:185

◆ usage()

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

Definition at line 537 of file zic.c.

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

Referenced by main().

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

◆ verror()

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

Definition at line 482 of file zic.c.

References _, fprintf, and vfprintf.

Referenced by error(), and warning().

483 {
484  /*
485  * Match the format of "cc" to allow sh users to zic ... 2>&1 | error -t
486  * "*" -v on BSD systems.
487  */
488  if (filename)
489  fprintf(stderr, _("\"%s\", line %d: "), filename, linenum);
490  vfprintf(stderr, string, args);
491  if (rfilename != NULL)
492  fprintf(stderr, _(" (rule from \"%s\", line %d)"),
494  fprintf(stderr, "\n");
495 }
#define fprintf
Definition: port.h:196
static lineno_t rlinenum
Definition: zic.c:191
static const char * filename
Definition: zic.c:177
static lineno_t linenum
Definition: zic.c:182
static const char * rfilename
Definition: zic.c:190
#define vfprintf
Definition: port.h:195
#define _(x)
Definition: elog.c:87

◆ want_bloat()

static bool want_bloat ( void  )
static

Definition at line 633 of file zic.c.

References bloat.

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

634 {
635  return 0 <= bloat;
636 }
static int bloat
Definition: zic.c:630

◆ warning()

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

Definition at line 509 of file zic.c.

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

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

510 {
511  va_list args;
512 
513  fprintf(stderr, _("warning: "));
514  va_start(args, string);
515  verror(string, args);
516  va_end(args);
517  warnings = true;
518 }
static bool warnings
Definition: zic.c:176
#define fprintf
Definition: port.h:196
static void verror(const char *string, va_list args) pg_attribute_printf(1
Definition: zic.c:482
#define _(x)
Definition: elog.c:87

◆ writezone()

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

Definition at line 2049 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().

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