{
JULIAN_DAY, /* Jn = Julian day */
DAY_OF_YEAR, /* n = day of year */
- MONTH_NTH_DAY_OF_WEEK, /* Mm.n.d = month, week, day of week */
+ MONTH_NTH_DAY_OF_WEEK /* Mm.n.d = month, week, day of week */
};
struct rule
int r_day; /* day number of rule */
int r_week; /* week number of rule */
int r_mon; /* month number of rule */
- int32 r_time; /* transition time of rule */
+ int_fast32_t r_time; /* transition time of rule */
};
/*
* Prototypes for static functions.
*/
-static struct pg_tm *gmtsub(pg_time_t const *timep, int32 offset,
+static struct pg_tm *gmtsub(pg_time_t const *timep, int_fast32_t offset,
struct pg_tm *tmp);
static bool increment_overflow(int *ip, int j);
-static bool increment_overflow_time(pg_time_t *tp, int32 j);
-static int64 leapcorr(struct state const *sp, pg_time_t t);
+static bool increment_overflow_time(pg_time_t *tp, int_fast32_t j);
+static int_fast64_t leapcorr(struct state const *sp, pg_time_t);
static struct pg_tm *timesub(pg_time_t const *timep,
- int32 offset, struct state const *sp,
+ int_fast32_t offset, struct state const *sp,
struct pg_tm *tmp);
static bool typesequiv(struct state const *sp, int a, int b);
/* Initialize *S to a value based on UTOFF, ISDST, and DESIGIDX. */
static void
-init_ttinfo(struct ttinfo *s, int32 utoff, bool isdst, int desigidx)
+init_ttinfo(struct ttinfo *s, int_fast32_t utoff, bool isdst, int desigidx)
{
s->tt_utoff = utoff;
s->tt_isdst = isdst;
s->tt_ttisut = false;
}
-static int32
+static int_fast32_t
detzcode(const char *const codep)
{
- int32 result;
+ int_fast32_t result;
int i;
- int32 one = 1;
- int32 halfmaxval = one << (32 - 2);
- int32 maxval = halfmaxval - 1 + halfmaxval;
- int32 minval = -1 - maxval;
+ int_fast32_t one = 1;
+ int_fast32_t halfmaxval = one << (32 - 2);
+ int_fast32_t maxval = halfmaxval - 1 + halfmaxval;
+ int_fast32_t minval = -1 - maxval;
result = codep[0] & 0x7f;
for (i = 1; i < 4; ++i)
* Do two's-complement negation even on non-two's-complement machines.
* If the result would be minval - 1, return minval.
*/
- result -= !TWOS_COMPLEMENT(int32) && result != 0;
+ result -= !TWOS_COMPLEMENT(int_fast32_t) && result != 0;
result += minval;
}
return result;
}
-static int64
+static int_fast64_t
detzcode64(const char *const codep)
{
- uint64 result;
+ uint_fast64_t result;
int i;
- int64 one = 1;
- int64 halfmaxval = one << (64 - 2);
- int64 maxval = halfmaxval - 1 + halfmaxval;
- int64 minval = -TWOS_COMPLEMENT(int64) - maxval;
+ int_fast64_t one = 1;
+ int_fast64_t halfmaxval = one << (64 - 2);
+ int_fast64_t maxval = halfmaxval - 1 + halfmaxval;
+ int_fast64_t minval = -TWOS_COMPLEMENT(int_fast64_t) - maxval;
result = codep[0] & 0x7f;
for (i = 1; i < 8; ++i)
* Do two's-complement negation even on non-two's-complement machines.
* If the result would be minval - 1, return minval.
*/
- result -= !TWOS_COMPLEMENT(int64) && result != 0;
+ result -= !TWOS_COMPLEMENT(int_fast64_t) && result != 0;
result += minval;
}
return result;
return errno;
for (stored = 4; stored <= 8; stored *= 2)
{
- int32 ttisstdcnt = detzcode(up->tzhead.tzh_ttisstdcnt);
- int32 ttisutcnt = detzcode(up->tzhead.tzh_ttisutcnt);
- int64 prevtr = 0;
- int32 prevcorr = 0;
- int32 leapcnt = detzcode(up->tzhead.tzh_leapcnt);
- int32 timecnt = detzcode(up->tzhead.tzh_timecnt);
- int32 typecnt = detzcode(up->tzhead.tzh_typecnt);
- int32 charcnt = detzcode(up->tzhead.tzh_charcnt);
+ int_fast32_t ttisstdcnt = detzcode(up->tzhead.tzh_ttisstdcnt);
+ int_fast32_t ttisutcnt = detzcode(up->tzhead.tzh_ttisutcnt);
+ int_fast64_t prevtr = 0;
+ int_fast32_t prevcorr = 0;
+ int_fast32_t leapcnt = detzcode(up->tzhead.tzh_leapcnt);
+ int_fast32_t timecnt = detzcode(up->tzhead.tzh_timecnt);
+ int_fast32_t typecnt = detzcode(up->tzhead.tzh_typecnt);
+ int_fast32_t charcnt = detzcode(up->tzhead.tzh_charcnt);
char const *p = up->buf + tzheadsize;
/*
timecnt = 0;
for (i = 0; i < sp->timecnt; ++i)
{
- int64 at
+ int_fast64_t at
= stored == 4 ? detzcode(p) : detzcode64(p);
sp->types[i] = at <= TIME_T_MAX;
leapcnt = 0;
for (i = 0; i < sp->leapcnt; ++i)
{
- int64 tr = stored == 4 ? detzcode(p) : detzcode64(p);
- int32 corr = detzcode(p + stored);
+ int_fast64_t tr = stored == 4 ? detzcode(p) : detzcode64(p);
+ int_fast32_t corr = detzcode(p + stored);
p += stored + 4;
/* Leap seconds cannot occur before the Epoch. */
up->buf[nread - 1] = '\0';
if (tzparse(&up->buf[1], ts, false))
{
+
/*
* Attempt to reuse existing abbreviations. Without this,
* America/Anchorage would be right on the edge after 2037 when
* given name is stored there (the buffer must be > TZ_STRLEN_MAX bytes!).
*/
int
-tzload(const char *name, char *canonname, struct state *sp, bool doextend)
+tzload(char const *name, char *canonname, struct state *sp, bool doextend)
{
union local_storage *lsp = malloc(sizeof *lsp);
*/
static const char *
-getsecs(const char *strp, int32 *const secsp)
+getsecs(const char *strp, int_fast32_t *const secsp)
{
int num;
strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
if (strp == NULL)
return NULL;
- *secsp = num * (int32) SECSPERHOUR;
+ *secsp = num * (int_fast32_t) SECSPERHOUR;
if (*strp == ':')
{
++strp;
*/
static const char *
-getoffset(const char *strp, int32 *const offsetp)
+getoffset(const char *strp, int_fast32_t *const offsetp)
{
bool neg = false;
* effect, calculate the year-relative time that rule takes effect.
*/
-static int32
+static int_fast32_t
transtime(const int year, const struct rule *const rulep,
- const int32 offset)
+ const int_fast32_t offset)
{
bool leapyear;
- int32 value;
+ int_fast32_t value;
int i;
int d,
m1,
size_t stdlen;
size_t dstlen;
size_t charcnt;
- int32 stdoffset;
- int32 dstoffset;
+ int_fast32_t stdoffset;
+ int_fast32_t dstoffset;
char *cp;
bool load_ok;
int yearlim;
int timecnt;
pg_time_t janfirst;
- int32 janoffset = 0;
+ int_fast32_t janoffset = 0;
int yearbeg;
++name;
do
{
- int32 yearsecs
+ int_fast32_t yearsecs
= year_lengths[isleap(yearbeg - 1)] * SECSPERDAY;
yearbeg--;
yearlim = yearbeg + YEARSPERREPEAT + 1;
for (year = yearbeg; year < yearlim; year++)
{
- int32
+ int_fast32_t
starttime = transtime(year, &start, stdoffset),
endtime = transtime(year, &end, dstoffset);
- int32
+ int_fast32_t
yearsecs = (year_lengths[isleap(year)]
* SECSPERDAY);
bool reversed = endtime < starttime;
if (reversed)
{
- int32 swap = starttime;
+ int_fast32_t swap = starttime;
starttime = endtime;
endtime = swap;
}
else
{
- int32 theirstdoffset;
- int32 theirdstoffset;
- int32 theiroffset;
+ int_fast32_t theirstdoffset;
+ int_fast32_t theirdstoffset;
+ int_fast32_t theiroffset;
bool isdst;
int i;
int j;
result = localsub(sp, &newt, tmp);
if (result)
{
- int64 newy;
+ int_fast64_t newy;
newy = result->tm_year;
if (t < sp->ats[0])
*/
static struct pg_tm *
-gmtsub(pg_time_t const *timep, int32 offset,
+gmtsub(pg_time_t const *timep, int_fast32_t offset,
struct pg_tm *tmp)
{
struct pg_tm *result;
}
static struct pg_tm *
-timesub(const pg_time_t *timep, int32 offset,
+timesub(const pg_time_t *timep, int_fast32_t offset,
const struct state *sp, struct pg_tm *tmp)
{
const struct lsinfo *lp;
pg_time_t tdays;
int idays; /* unsigned would be so 2003 */
- int64 rem;
+ int_fast64_t rem;
int y;
const int *ip;
- int64 corr;
+ int_fast64_t corr;
bool hit;
int i;
}
static bool
-increment_overflow_time(pg_time_t *tp, int32 j)
+increment_overflow_time(pg_time_t *tp, int_fast32_t j)
{
/*----------
* This is like
return false;
}
-static int64
+static int_fast64_t
leapcorr(struct state const *sp, pg_time_t t)
{
struct lsinfo const *lp;
#define ZIC_VERSION_PRE_2013 '2'
#define ZIC_VERSION '3'
-typedef int64 zic_t;
-#define ZIC_MIN PG_INT64_MIN
-#define ZIC_MAX PG_INT64_MAX
+typedef int_fast64_t zic_t;
+#define ZIC_MIN INT_FAST64_MIN
+#define ZIC_MAX INT_FAST64_MAX
+#define PRIdZIC PRIdFAST64
+#define SCNdZIC SCNdFAST64
#ifndef ZIC_MAX_ABBR_LEN_WO_WARN
#define ZIC_MAX_ABBR_LEN_WO_WARN 6
static ptrdiff_t const PTRDIFF_MAX = MAXVAL(ptrdiff_t, TYPE_BIT(ptrdiff_t));
#endif
-/*
- * The type for line numbers. In Postgres, use %d to format them; upstream
- * uses PRIdMAX but we prefer not to rely on that, not least because it
- * results in platform-dependent strings to be translated.
- */
-typedef int lineno_t;
+/* The minimum alignment of a type, for pre-C11 platforms. */
+#if __STDC_VERSION__ < 201112
+#define _Alignof(type) offsetof(struct { char a; type b; }, b)
+#endif
+
+/* The type for line numbers. Use PRIdMAX to format them; formerly
+ there was also "#define PRIdLINENO PRIdMAX" and formats used
+ PRIdLINENO, but xgettext cannot grok that. */
+typedef intmax_t lineno_t;
struct rule
{
(itssymlink(target) ? (errno = ENOTSUP, -1) : link(target, linkname))
#endif
-pg_noreturn static void memory_exhausted(const char *msg);
-static void verror(const char *string, va_list args) pg_attribute_printf(1, 0);
-static void error(const char *string,...) pg_attribute_printf(1, 2);
-static void warning(const char *string,...) pg_attribute_printf(1, 2);
-pg_noreturn static void usage(FILE *stream, int status);
+static void verror(const char *const string, va_list args) pg_attribute_printf(1, 0);
+static void error(const char *const string,...) pg_attribute_printf(1, 2);
+static void warning(const char *const string,...) pg_attribute_printf(1, 2);
static void addtt(zic_t starttime, int type);
static int addtype(zic_t utoff, char const *abbr,
bool isdst, bool ttisstd, bool ttisut);
static void leapadd(zic_t t, int correction, int rolling);
static void adjleap(void);
static void associate(void);
-static void dolink(char const *target, char const *linkname,
+static void dolink(const char *target, const char *linkname,
bool staysymlink);
static char **getfields(char *cp);
static zic_t gethms(const char *string, const char *errstring);
* Memory allocation.
*/
-static void
+static _Noreturn void
memory_exhausted(const char *msg)
{
fprintf(stderr, _("%s: Memory exhausted: %s\n"), progname, msg);
return nitems * itemsize;
}
+static size_t
+align_to(size_t size, size_t alignment)
+{
+ size_t aligned_size = size + alignment - 1;
+
+ aligned_size -= aligned_size % alignment;
+ if (aligned_size < size)
+ memory_exhausted(_("alignment overflow"));
+ return aligned_size;
+}
+
static void *
memcheck(void *ptr)
{
}
static void
-verror(const char *string, va_list args)
+verror(const char *const string, va_list args)
{
/*
* Match the format of "cc" to allow sh users to zic ... 2>&1 | error -t
* "*" -v on BSD systems.
*/
if (filename)
- fprintf(stderr, _("\"%s\", line %d: "), filename, linenum);
+ fprintf(stderr, _("\"%s\", line %" PRIdMAX ": "), filename, linenum);
vfprintf(stderr, string, args);
if (rfilename != NULL)
- fprintf(stderr, _(" (rule from \"%s\", line %d)"),
+ fprintf(stderr, _(" (rule from \"%s\", line %" PRIdMAX ")"),
rfilename, rlinenum);
fprintf(stderr, "\n");
}
static void
-error(const char *string,...)
+error(const char *const string,...)
{
va_list args;
}
static void
-warning(const char *string,...)
+warning(const char *const string,...)
{
va_list args;
}
}
-static void
+static _Noreturn void
usage(FILE *stream, int status)
{
fprintf(stream,
static bool
timerange_option(char *timerange)
{
- int64 lo = min_time,
+ intmax_t lo = min_time,
hi = max_time;
char *lo_end = timerange,
*hi_end;
{
errno = 0;
lo = strtoimax(timerange + 1, &lo_end, 10);
- if (lo_end == timerange + 1 || (lo == PG_INT64_MAX && errno == ERANGE))
+ if (lo_end == timerange + 1 || (lo == INTMAX_MAX && errno == ERANGE))
return false;
}
hi_end = lo_end;
{
errno = 0;
hi = strtoimax(lo_end + 2, &hi_end, 10);
- if (hi_end == lo_end + 2 || hi == PG_INT64_MIN)
+ if (hi_end == lo_end + 2 || hi == INTMAX_MIN)
return false;
- hi -= !(hi == PG_INT64_MAX && errno == ERANGE);
+ hi -= !(hi == INTMAX_MAX && errno == ERANGE);
}
if (*hi_end || hi < lo || max_time < lo || hi < min_time)
return false;
if (nfields == 0)
{
if (name == leapsec && *buf == '#')
- {
- /*
- * PG: INT64_FORMAT isn't portable for sscanf, so be content
- * with scanning a "long". Once we are requiring C99 in all
- * live branches, it'd be sensible to adopt upstream's
- * practice of using the <inttypes.h> macros. But for now, we
- * don't actually use this code, and it won't overflow before
- * 2038 anyway.
- */
- long cl_tmp;
-
- sscanf(buf, "#expires %ld", &cl_tmp);
- comment_leapexpires = cl_tmp;
- }
+ sscanf(buf, "#expires %" SCNdZIC, &comment_leapexpires);
}
else if (wantcont)
{
static zic_t
gethms(char const *string, char const *errstring)
{
- /* PG: make hh be int not zic_t to avoid sscanf portability issues */
- int hh;
+ zic_t hh;
int sign,
mm = 0,
ss = 0;
else
sign = 1;
switch (sscanf(string,
- "%d%c%d%c%d%c%1d%*[0]%c%*[0123456789]%c",
+ "%" SCNdZIC "%c%d%c%d%c%1d%*[0]%c%*[0123456789]%c",
&hh, &hhx, &mm, &mmx, &ss, &ssx, &tenths, &xr, &xs))
{
default:
error("%s", errstring);
return 0;
}
- /* Some compilers warn that this test is unsatisfiable for 32-bit ints */
-#if INT_MAX > PG_INT32_MAX
if (ZIC_MAX / SECSPERHOUR < hh)
{
error(_("time overflow"));
return 0;
}
-#endif
ss += 5 + ((ss ^ 1) & (xr == '0')) <= tenths; /* Round to even. */
if (noise && (hh > HOURSPERDAY ||
(hh == HOURSPERDAY && (mm != 0 || ss != 0))))
warning(_("values over 24 hours not handled by pre-2007 versions of zic"));
- return oadd(sign * (zic_t) hh * SECSPERHOUR,
+ return oadd(sign * hh * SECSPERHOUR,
sign * (mm * SECSPERMIN + ss));
}
strcmp(zones[i].z_name, fields[ZF_NAME]) == 0)
{
error(_("duplicate zone name %s"
- " (file \"%s\", line %d)"),
+ " (file \"%s\", line %" PRIdMAX ")"),
fields[ZF_NAME],
zones[i].z_filename,
zones[i].z_linenum);
const struct lookup *lp;
zic_t i,
j;
-
- /* PG: make year be int not zic_t to avoid sscanf portability issues */
- int year;
+ zic_t year;
int month,
day;
zic_t dayoff,
dayoff = 0;
cp = fields[LP_YEAR];
- if (sscanf(cp, "%d%c", &year, &xs) != 1)
+ if (sscanf(cp, "%" SCNdZIC "%c", &year, &xs) != 1)
{
/*
* Leapin' Lizards!
char *ep;
char xs;
- /* PG: year_tmp is to avoid sscanf portability issues */
- int year_tmp;
-
if ((lp = byword(monthp, mon_names)) == NULL)
{
error(_("invalid month name"));
progname, lp->l_value);
exit(EXIT_FAILURE);
}
- else if (sscanf(cp, "%d%c", &year_tmp, &xs) == 1)
- rp->r_loyear = year_tmp;
- else
+ else if (sscanf(cp, "%" SCNdZIC "%c", &rp->r_loyear, &xs) != 1)
{
error(_("invalid starting year"));
return;
progname, lp->l_value);
exit(EXIT_FAILURE);
}
- else if (sscanf(cp, "%d%c", &year_tmp, &xs) == 1)
- rp->r_hiyear = year_tmp;
- else
+ else if (sscanf(cp, "%" SCNdZIC "%c", &rp->r_hiyear, &xs) != 1)
{
error(_("invalid ending year"));
return;
}
static void
-convert(const int32 val, char *const buf)
+convert(const int_fast32_t val, char *const buf)
{
int i;
int shift;
}
static void
-puttzcode(const int32 val, FILE *const fp)
+puttzcode(const int_fast32_t val, FILE *const fp)
{
char buf[4];
* Allocate the ATS and TYPES arrays via a single malloc, as this is a bit
* faster.
*/
- zic_t *ats = emalloc(MAXALIGN(size_product(nats, sizeof *ats + 1)));
+ zic_t *ats = emalloc(align_to(size_product(nats, sizeof *ats + 1),
+ _Alignof(zic_t)));
void *typesptr = ats + nats;
unsigned char *types = typesptr;
struct timerange rangeall,
rangeall.count = timecnt;
rangeall.leapcount = leapcnt;
range64 = limitrange(rangeall, lo_time, hi_time, ats, types);
- range32 = limitrange(range64, PG_INT32_MIN, PG_INT32_MAX, ats, types);
+ range32 = limitrange(range64, INT32_MIN, INT32_MAX, ats, types);
/*
* Remove old file, if any, to snap links.
/*
* Arguably the default time type in the 32-bit data should be
* range32.defaulttype, which is suited for timestamps just before
- * PG_INT32_MIN. However, zic traditionally used the time type of
+ * INT32_MIN. However, zic traditionally used the time type of
* the indefinite past instead. Internet RFC 8532 says readers
* should ignore 32-bit data, so this discrepancy matters only to
* obsolete readers where the traditional type might be more
* value, unless -r specifies a low cutoff that excludes some
* 32-bit timestamps.
*/
- thisdefaulttype = (lo_time <= PG_INT32_MIN
+ thisdefaulttype = (lo_time <= INT32_MIN
? range64.defaulttype
: range32.defaulttype);
toomanytimes = thistimecnt >> 31 >> 1 != 0;
thisleapi = range32.leapbase;
thisleapcnt = range32.leapcount;
- locut = PG_INT32_MIN < lo_time;
- hicut = hi_time < PG_INT32_MAX;
+ locut = INT32_MIN < lo_time;
+ hicut = hi_time < INT32_MAX;
}
else
{
unsigned char tm = types[i];
char *thisabbrev = &thischars[indmap[desigidx[tm]]];
- fprintf(stdout, "%s\t" INT64_FORMAT "%s\n",
+ fprintf(stdout, "%s\t%" PRIdFAST64 "%s\n",
thisabbrev,
utoffs[tm],
isdsts[tm] ? "\tD" : "");
unsigned char tm = defaulttype;
char *thisabbrev = &thischars[indmap[desigidx[tm]]];
- fprintf(stdout, "%s\t" INT64_FORMAT "%s\n",
+ fprintf(stdout, "%s\t%" PRIdFAST64 "%s\n",
thisabbrev,
utoffs[tm],
isdsts[tm] ? "\tD" : "");
* Output a LO_TIME transition if needed; see limitrange. But do not
* go below the minimum representable value for this pass.
*/
- lo = pass == 1 && lo_time < PG_INT32_MIN ? PG_INT32_MIN : lo_time;
+ lo = pass == 1 && lo_time < INT32_MIN ? INT32_MIN : lo_time;
if (locut)
puttzcodepass(lo, fp, pass);
return array;
}
-static void
+static _Noreturn void
time_overflow(void)
{
error(_("time overflow"));