v3-0003-Allow-tzcode-to-use-stdint.h-and-inttypes.h.patch
text/x-patch
Filename: v3-0003-Allow-tzcode-to-use-stdint.h-and-inttypes.h.patch
Type: text/x-patch
Part: 3
Patch
Format: format-patch
Series: patch v3-0003
Subject: Allow tzcode to use <stdint.h> and <inttypes.h>.
| File | + | − |
|---|---|---|
| src/timezone/localtime.c | 56 | 54 |
| src/timezone/README | 0 | 14 |
| src/timezone/zic.c | 40 | 48 |
From 27462adab2f9971ce34972062e51baf7728dc3ea Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Thu, 4 Jul 2024 13:00:08 +1200
Subject: [PATCH v3 3/3] Allow tzcode to use <stdint.h> and <inttypes.h>.
Previously we removed the use of types and macros from these standard
headers when synchronizing with upstream tzcode, to that we could
continue to target C89 toolchains. Now that all supported branches of
PostgreSQL require C99, we can drop a lot of small differences.
Reviewed-by:
Discussion: https://postgr.es/m/ME3P282MB3166F9D1F71F787929C0C7E7B6312%40ME3P282MB3166.AUSP282.PROD.OUTLOOK.COM
---
src/timezone/README | 14 -----
src/timezone/localtime.c | 110 ++++++++++++++++++++-------------------
src/timezone/zic.c | 88 ++++++++++++++-----------------
3 files changed, 96 insertions(+), 116 deletions(-)
diff --git a/src/timezone/README b/src/timezone/README
index dd5d5f9892a..1857f03e3dd 100644
--- a/src/timezone/README
+++ b/src/timezone/README
@@ -79,13 +79,6 @@ fixed that.)
includes relying on configure's results rather than hand-hacked
#defines (see private.h in particular).
-* Similarly, avoid relying on <stdint.h> features that may not exist on old
-systems. In particular this means using Postgres' definitions of the int32
-and int64 typedefs, not int_fast32_t/int_fast64_t. Likewise we use
-PG_INT32_MIN/MAX not INT32_MIN/MAX. (Once we desupport all PG versions
-that don't require C99, it'd be practical to rely on <stdint.h> and remove
-this set of diffs; but that day is not yet.)
-
* Since Postgres is typically built on a system that has its own copy
of the <time.h> functions, we must avoid conflicting with those. This
mandates renaming typedef time_t to pg_time_t, and similarly for most
@@ -119,13 +112,6 @@ to first run the tzcode source files through a sed filter like this:
-e 's|^\*/| */|' \
-e 's/\bregister[ \t]//g' \
-e 's/\bATTRIBUTE_PURE[ \t]//g' \
- -e 's/int_fast32_t/int32/g' \
- -e 's/int_fast64_t/int64/g' \
- -e 's/intmax_t/int64/g' \
- -e 's/INT32_MIN/PG_INT32_MIN/g' \
- -e 's/INT32_MAX/PG_INT32_MAX/g' \
- -e 's/INTMAX_MIN/PG_INT64_MIN/g' \
- -e 's/INTMAX_MAX/PG_INT64_MAX/g' \
-e 's/struct[ \t]+tm\b/struct pg_tm/g' \
-e 's/\btime_t\b/pg_time_t/g' \
-e 's/lineno/lineno_t/g' \
diff --git a/src/timezone/localtime.c b/src/timezone/localtime.c
index 0bc160ea7d7..e9adfc5da04 100644
--- a/src/timezone/localtime.c
+++ b/src/timezone/localtime.c
@@ -17,6 +17,7 @@
#include "c.h"
#include <fcntl.h>
+#include <stdint.h>
#include "datatype/timestamp.h"
#include "pgtz.h"
@@ -75,20 +76,20 @@ 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 bool increment_overflow_time(pg_time_t *tp, int_fast32_t j);
static int64 leapcorr(struct state const *sp, pg_time_t 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);
@@ -105,7 +106,7 @@ static struct pg_tm tm;
/* 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;
@@ -114,15 +115,15 @@ init_ttinfo(struct ttinfo *s, int32 utoff, bool isdst, int desigidx)
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)
@@ -134,21 +135,21 @@ detzcode(const char *const codep)
* 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;
+ int_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)
@@ -160,7 +161,7 @@ detzcode64(const char *const codep)
* 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;
@@ -246,14 +247,14 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
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;
/*
@@ -350,8 +351,8 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
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. */
@@ -361,7 +362,7 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
{
/*
* Leap seconds cannot occur more than once per UTC month, and
- * UTC months are at least 28 days long (minus 1 second for a
+ * UTC months are at least 2 days long (minus 1 second for a
* negative leap second). Each leap second's correction must
* differ from the previous one's by 1 second.
*/
@@ -707,9 +708,10 @@ getnum(const char *strp, int *const nump, const int min, const int max)
*/
static const char *
-getsecs(const char *strp, int32 *const secsp)
+getsecs(const char *strp, int_fast32_t * const secsp)
{
int num;
+ int_fast32_t secsperhour = SECSPERHOUR;
/*
* 'HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
@@ -719,7 +721,7 @@ getsecs(const char *strp, int32 *const secsp)
strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
if (strp == NULL)
return NULL;
- *secsp = num * (int32) SECSPERHOUR;
+ *secsp = num * secsperhour;
if (*strp == ':')
{
++strp;
@@ -748,7 +750,7 @@ getsecs(const char *strp, int32 *const secsp)
*/
static const char *
-getoffset(const char *strp, int32 *const offsetp)
+getoffset(const char *strp, int_fast32_t * const offsetp)
{
bool neg = false;
@@ -835,12 +837,12 @@ getrule(const char *strp, struct rule *const rulep)
* 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,
@@ -940,8 +942,8 @@ tzparse(const char *name, struct state *sp, bool lastditch)
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;
@@ -1033,7 +1035,7 @@ tzparse(const char *name, struct state *sp, bool lastditch)
int yearlim;
int timecnt;
pg_time_t janfirst;
- int32 janoffset = 0;
+ int_fast32_t janoffset = 0;
int yearbeg;
++name;
@@ -1059,7 +1061,7 @@ tzparse(const char *name, struct state *sp, bool lastditch)
do
{
- int32 yearsecs
+ int_fast32_t yearsecs
= year_lengths[isleap(yearbeg - 1)] * SECSPERDAY;
yearbeg--;
@@ -1073,17 +1075,17 @@ tzparse(const char *name, struct state *sp, bool lastditch)
yearlim = yearbeg + YEARSPERREPEAT + 1;
for (year = yearbeg; year < yearlim; year++)
{
- int32
- starttime = transtime(year, &start, stdoffset),
- endtime = transtime(year, &end, dstoffset);
- int32
- yearsecs = (year_lengths[isleap(year)]
- * SECSPERDAY);
+ int_fast32_t
+ starttime = transtime(year, &start, stdoffset),
+ endtime = transtime(year, &end, dstoffset);
+ 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;
@@ -1126,9 +1128,9 @@ tzparse(const char *name, struct state *sp, bool lastditch)
}
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;
@@ -1290,7 +1292,7 @@ localsub(struct state const *sp, pg_time_t const *timep,
result = localsub(sp, &newt, tmp);
if (result)
{
- int64 newy;
+ int_fast64_t newy;
newy = result->tm_year;
if (t < sp->ats[0])
@@ -1354,7 +1356,7 @@ pg_localtime(const pg_time_t *timep, const pg_tz *tz)
*/
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;
@@ -1411,7 +1413,7 @@ leaps_thru_end_of(const int y)
}
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;
@@ -1554,7 +1556,7 @@ increment_overflow(int *ip, int j)
}
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
diff --git a/src/timezone/zic.c b/src/timezone/zic.c
index d605c721ecf..0a98bb0ebb6 100644
--- a/src/timezone/zic.c
+++ b/src/timezone/zic.c
@@ -11,6 +11,8 @@
#include "postgres_fe.h"
#include <fcntl.h>
+#include <inttypes.h>
+#include <stdint.h>
#include <sys/stat.h>
#include <time.h>
@@ -22,12 +24,16 @@
#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;
+static zic_t const
+ ZIC_MIN = INT_FAST64_MIN,
+ ZIC_MAX = INT_FAST64_MAX,
+ ZIC32_MIN = INT32_MIN,
+ ZIC32_MAX = INT32_MAX;
+#define SCNdZIC SCNdFAST64
#ifndef ZIC_MAX_ABBR_LEN_WO_WARN
-#define ZIC_MAX_ABBR_LEN_WO_WARN 6
+#define ZIC_MAX_ABBR_LEN_WO_WARN 6
#endif /* !defined ZIC_MAX_ABBR_LEN_WO_WARN */
#ifndef WIN32
@@ -601,7 +607,7 @@ static zic_t comment_leapexpires = -1;
static bool
timerange_option(char *timerange)
{
- int64 lo = min_time,
+ intmax_t lo = min_time,
hi = max_time;
char *lo_end = timerange,
*hi_end;
@@ -610,7 +616,7 @@ timerange_option(char *timerange)
{
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;
@@ -618,9 +624,9 @@ timerange_option(char *timerange)
{
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;
@@ -1291,18 +1297,7 @@ infile(const char *name)
{
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)
@@ -1364,8 +1359,7 @@ infile(const char *name)
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;
@@ -1387,7 +1381,7 @@ gethms(char const *string, char const *errstring)
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:
@@ -1424,7 +1418,7 @@ gethms(char const *string, char const *errstring)
return 0;
}
/* Some compilers warn that this test is unsatisfiable for 32-bit ints */
-#if INT_MAX > PG_INT32_MAX
+#if INT_MAX > INT32_MAX
if (ZIC_MAX / SECSPERHOUR < hh)
{
error(_("time overflow"));
@@ -1670,8 +1664,7 @@ getleapdatetime(char **fields, int nfields, bool expire_line)
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,
@@ -1681,7 +1674,7 @@ getleapdatetime(char **fields, int nfields, bool expire_line)
dayoff = 0;
cp = fields[LP_YEAR];
- if (sscanf(cp, "%d%c", &year, &xs) != 1)
+ if (sscanf(cp, "%" SCNdZIC "%c", &year, &xs) != 1)
{
/*
* Leapin' Lizards!
@@ -1830,9 +1823,6 @@ rulesub(struct rule *rp, const char *loyearp, const char *hiyearp,
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"));
@@ -1890,9 +1880,7 @@ rulesub(struct rule *rp, const char *loyearp, const char *hiyearp,
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;
@@ -1918,9 +1906,7 @@ rulesub(struct rule *rp, const char *loyearp, const char *hiyearp,
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;
@@ -1989,7 +1975,7 @@ rulesub(struct rule *rp, const char *loyearp, const char *hiyearp,
}
static void
-convert(const int32 val, char *const buf)
+convert(const int_fast32_t val, char *const buf)
{
int i;
int shift;
@@ -2000,7 +1986,7 @@ convert(const int32 val, char *const buf)
}
static void
-convert64(const zic_t val, char *const buf)
+convert64(uint_fast64_t val, char *const buf)
{
int i;
int shift;
@@ -2011,7 +1997,7 @@ convert64(const zic_t val, char *const buf)
}
static void
-puttzcode(const int32 val, FILE *const fp)
+puttzcode(zic_t val, FILE *const fp)
{
char buf[4];
@@ -2201,7 +2187,7 @@ writezone(const char *const name, const char *const string, char version,
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, ZIC32_MIN, ZIC32_MAX, ats, types);
/*
* Remove old file, if any, to snap links.
@@ -2263,7 +2249,7 @@ writezone(const char *const name, const char *const string, char version,
/*
* 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
@@ -2271,7 +2257,7 @@ writezone(const char *const name, const char *const string, char version,
* 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);
@@ -2280,8 +2266,8 @@ writezone(const char *const name, const char *const string, char version,
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
{
@@ -2465,7 +2451,13 @@ writezone(const char *const name, const char *const string, char version,
continue;
}
- /* PG: print current timezone abbreviations if requested */
+ /*
+ * PG: print current timezone abbreviations if requested. Note that
+ * we cast to int64_t, because int_fast64_t is not required to be
+ * compatible with INT64_FORMAT. We can't use PRIdFAST64 here because
+ * we override fprintf with our own implementation that might not
+ * understand it.
+ */
if (print_abbrevs && pass == 2)
{
/* Print "type" data for periods ending after print_cutoff */
@@ -2478,7 +2470,7 @@ writezone(const char *const name, const char *const string, char version,
fprintf(stdout, "%s\t" INT64_FORMAT "%s\n",
thisabbrev,
- utoffs[tm],
+ (int64_t) utoffs[tm],
isdsts[tm] ? "\tD" : "");
}
}
@@ -2490,7 +2482,7 @@ writezone(const char *const name, const char *const string, char version,
fprintf(stdout, "%s\t" INT64_FORMAT "%s\n",
thisabbrev,
- utoffs[tm],
+ (int64_t) utoffs[tm],
isdsts[tm] ? "\tD" : "");
}
}
@@ -2499,7 +2491,7 @@ writezone(const char *const name, const char *const string, char version,
* 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 < ZIC32_MIN ? ZIC32_MIN : lo_time;
if (locut)
puttzcodepass(lo, fp, pass);
--
2.45.2