Cannot find a working 64-bit integer type on Illumos

Started by Japin Lialmost 2 years ago71 messages
#1Japin Li
japinli@hotmail.com

Hi, hackers,

When I try to configure PostgreSQL 16.2 on Illumos using the following command,
it complains $subject.

./configure --enable-cassert --enable-debug --enable-nls --with-perl \
--with-python --without-tcl --without-gssapi --with-openssl \
--with-ldap --with-libxml --with-libxslt --without-systemd \
--with-readline --enable-thread-safety --enable-dtrace \
DTRACEFLAGS=-64 CFLAGS=-Werror

However, if I remove the `CFLAGS=-Werror`, it works fine.

I'm not sure what happened here.

$ uname -a
SunOS db_build 5.11 hunghu-20231216T132436Z i86pc i386 i86pc illumos
$ gcc --version
gcc (GCC) 10.4.0
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

#2Andres Freund
andres@anarazel.de
In reply to: Japin Li (#1)
Re: Cannot find a working 64-bit integer type on Illumos

Hi,

On 2024-03-23 00:48:05 +0800, Japin Li wrote:

When I try to configure PostgreSQL 16.2 on Illumos using the following command,
it complains $subject.

./configure --enable-cassert --enable-debug --enable-nls --with-perl \
--with-python --without-tcl --without-gssapi --with-openssl \
--with-ldap --with-libxml --with-libxslt --without-systemd \
--with-readline --enable-thread-safety --enable-dtrace \
DTRACEFLAGS=-64 CFLAGS=-Werror

However, if I remove the `CFLAGS=-Werror`, it works fine.

Likely there's an unrelated warning triggering the configure test to
fail. We'd need to see config.log to see what that is.

Greetings,

Andres Freund

#3Tom Lane
tgl@sss.pgh.pa.us
In reply to: Japin Li (#1)
Re: Cannot find a working 64-bit integer type on Illumos

Japin Li <japinli@hotmail.com> writes:

When I try to configure PostgreSQL 16.2 on Illumos using the following command,
it complains $subject.

./configure --enable-cassert --enable-debug --enable-nls --with-perl \
--with-python --without-tcl --without-gssapi --with-openssl \
--with-ldap --with-libxml --with-libxslt --without-systemd \
--with-readline --enable-thread-safety --enable-dtrace \
DTRACEFLAGS=-64 CFLAGS=-Werror

However, if I remove the `CFLAGS=-Werror`, it works fine.
I'm not sure what happened here.

CFLAGS=-Werror breaks a whole lot of configure's tests, not only that
one. (We even have this documented, see [1]https://www.postgresql.org/docs/devel/install-make.html#CONFIGURE-ENVVARS.) So you can't inject
-Werror that way. What I do on my buildfarm animals is the equivalent
of

export COPT='-Werror'

after configure and before build. I think configure pays no attention
to COPT, so it'd likely be safe to keep that set all the time, but in
the buildfarm client it's just as easy to be conservative.

regards, tom lane

[1]: https://www.postgresql.org/docs/devel/install-make.html#CONFIGURE-ENVVARS

#4Japin Li
japinli@hotmail.com
In reply to: Andres Freund (#2)
1 attachment(s)
Re: Cannot find a working 64-bit integer type on Illumos

On Sat, 23 Mar 2024 at 00:53, Andres Freund <andres@anarazel.de> wrote:

Hi,

On 2024-03-23 00:48:05 +0800, Japin Li wrote:

When I try to configure PostgreSQL 16.2 on Illumos using the following command,
it complains $subject.

./configure --enable-cassert --enable-debug --enable-nls --with-perl \
--with-python --without-tcl --without-gssapi --with-openssl \
--with-ldap --with-libxml --with-libxslt --without-systemd \
--with-readline --enable-thread-safety --enable-dtrace \
DTRACEFLAGS=-64 CFLAGS=-Werror

However, if I remove the `CFLAGS=-Werror`, it works fine.

Likely there's an unrelated warning triggering the configure test to
fail. We'd need to see config.log to see what that is.

Thanks for your quick reply. Attach the config.log.

Attachments:

config.logtext/plainDownload
#5Japin Li
japinli@hotmail.com
In reply to: Tom Lane (#3)
Re: Cannot find a working 64-bit integer type on Illumos

On Sat, 23 Mar 2024 at 01:04, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Japin Li <japinli@hotmail.com> writes:

When I try to configure PostgreSQL 16.2 on Illumos using the following command,
it complains $subject.

./configure --enable-cassert --enable-debug --enable-nls --with-perl \
--with-python --without-tcl --without-gssapi --with-openssl \
--with-ldap --with-libxml --with-libxslt --without-systemd \
--with-readline --enable-thread-safety --enable-dtrace \
DTRACEFLAGS=-64 CFLAGS=-Werror

However, if I remove the `CFLAGS=-Werror`, it works fine.
I'm not sure what happened here.

CFLAGS=-Werror breaks a whole lot of configure's tests, not only that
one. (We even have this documented, see [1].) So you can't inject
-Werror that way. What I do on my buildfarm animals is the equivalent
of

export COPT='-Werror'

after configure and before build. I think configure pays no attention
to COPT, so it'd likely be safe to keep that set all the time, but in
the buildfarm client it's just as easy to be conservative.

regards, tom lane

[1] https://www.postgresql.org/docs/devel/install-make.html#CONFIGURE-ENVVARS

Thank you very much! I didn't notice this part before.

#6Tom Lane
tgl@sss.pgh.pa.us
In reply to: Japin Li (#4)
Re: Cannot find a working 64-bit integer type on Illumos

Japin Li <japinli@hotmail.com> writes:

On Sat, 23 Mar 2024 at 00:53, Andres Freund <andres@anarazel.de> wrote:

Likely there's an unrelated warning triggering the configure test to
fail. We'd need to see config.log to see what that is.

Thanks for your quick reply. Attach the config.log.

Yup:

conftest.c:139:5: error: no previous prototype for 'does_int64_work' [-Werror=missing-prototypes]
139 | int does_int64_work()
| ^~~~~~~~~~~~~~~
cc1: all warnings being treated as errors
configure:17003: $? = 1
configure: program exited with status 1

This warning is harmless normally, but breaks the configure probe if
you enable -Werror.

No doubt we could improve that test snippet so that it does not
trigger that warning. But trying to make configure safe for -Werror
seems like a fool's errand, for these reasons:

* Do you really want to try to make all of configure's probes proof
against every compiler warning everywhere?

* Many of the test snippets aren't readily under our control, as they
are supplied by Autoconf.

* In the majority of cases, any such failures would be silent, as
configure would just conclude that the feature it is probing for
isn't there. So even finding there's a problem would be difficult.

The short answer is that Autoconf is not designed to support -Werror
and it's not worth it to try to make it do so.

regards, tom lane

#7Andres Freund
andres@anarazel.de
In reply to: Tom Lane (#6)
Re: Cannot find a working 64-bit integer type on Illumos

Hi,

On 2024-03-22 13:25:56 -0400, Tom Lane wrote:

The short answer is that Autoconf is not designed to support -Werror
and it's not worth it to try to make it do so.

I wonder if we ought to make configure warn if it sees -Werror in CFLAGS -
this is far from the first time somebody stumbling with -Werror. Including a
few quite senior hackers, if I recall correctly. We could also just filter it
temporarily and put it back at the end of configure.

I don't think there's great way of making the autoconf buildsystem use -Werror
continually, today. IIRC the best way is to use Makefile.custom.

Greetings,

Andres Freund

#8Robert Haas
robertmhaas@gmail.com
In reply to: Andres Freund (#7)
Re: Cannot find a working 64-bit integer type on Illumos

On Fri, Mar 22, 2024 at 2:38 PM Andres Freund <andres@anarazel.de> wrote:

I wonder if we ought to make configure warn if it sees -Werror in CFLAGS -
this is far from the first time somebody stumbling with -Werror. Including a
few quite senior hackers, if I recall correctly. We could also just filter it
temporarily and put it back at the end of configure.

I think I made this mistake at some point, but I just looked at
config.log and corrected my mistake. I'm not strongly against having
an explicit check for -Werror, but I think the main problem here is
that the original poster didn't have a look at config.log to see what
the actual problem was, and at least IME that's necessary in pretty
much 100% of cases where configure fails for whatever reason. Perhaps
autotools could be better-designed in that regard, but we don't
necessarily want to work around every problem that can stem from that
design choice in our code, either.

--
Robert Haas
EDB: http://www.enterprisedb.com

#9Andres Freund
andres@anarazel.de
In reply to: Robert Haas (#8)
Re: Cannot find a working 64-bit integer type on Illumos

Hi,

On 2024-03-22 15:02:45 -0400, Robert Haas wrote:

On Fri, Mar 22, 2024 at 2:38 PM Andres Freund <andres@anarazel.de> wrote:

I wonder if we ought to make configure warn if it sees -Werror in CFLAGS -
this is far from the first time somebody stumbling with -Werror. Including a
few quite senior hackers, if I recall correctly. We could also just filter it
temporarily and put it back at the end of configure.

I think I made this mistake at some point, but I just looked at
config.log and corrected my mistake.

IME the bigger issue is that sometimes it doesn't lead to outright failures,
just to lots of stuff not being detected as supported / present.

Greetings,

Andres Freund

#10Robert Haas
robertmhaas@gmail.com
In reply to: Andres Freund (#9)
Re: Cannot find a working 64-bit integer type on Illumos

On Fri, Mar 22, 2024 at 3:31 PM Andres Freund <andres@anarazel.de> wrote:

IME the bigger issue is that sometimes it doesn't lead to outright failures,
just to lots of stuff not being detected as supported / present.

Ugh. That does, indeed, sound not very nice.

--
Robert Haas
EDB: http://www.enterprisedb.com

#11Tom Lane
tgl@sss.pgh.pa.us
In reply to: Robert Haas (#10)
Re: Cannot find a working 64-bit integer type on Illumos

Robert Haas <robertmhaas@gmail.com> writes:

On Fri, Mar 22, 2024 at 3:31 PM Andres Freund <andres@anarazel.de> wrote:

IME the bigger issue is that sometimes it doesn't lead to outright failures,
just to lots of stuff not being detected as supported / present.

Ugh. That does, indeed, sound not very nice.

I could get behind throwing an error if -Werror is spotted. I think
trying to pull it out and put it back is too much work and a bit
too much magic.

regards, tom lane

#12Thomas Munro
thomas.munro@gmail.com
In reply to: Tom Lane (#6)
Re: Cannot find a working 64-bit integer type on Illumos

On Sat, Mar 23, 2024 at 6:26 AM Tom Lane <tgl@sss.pgh.pa.us> wrote:

conftest.c:139:5: error: no previous prototype for 'does_int64_work' [-Werror=missing-prototypes]
139 | int does_int64_work()
| ^~~~~~~~~~~~~~~
cc1: all warnings being treated as errors
configure:17003: $? = 1
configure: program exited with status 1

. o O ( int64_t, PRIdi64, etc were standardised a quarter of a century ago )

#13Tom Lane
tgl@sss.pgh.pa.us
In reply to: Thomas Munro (#12)
Re: Cannot find a working 64-bit integer type on Illumos

Thomas Munro <thomas.munro@gmail.com> writes:

. o O ( int64_t, PRIdi64, etc were standardised a quarter of a century ago )

Yeah. Now that we require C99 it's probably reasonable to assume
that those things exist. I wouldn't be in favor of ripping out our
existing notations like UINT64CONST, because the code churn would be
substantial and the gain minimal. But we could imagine reimplementing
that stuff atop <stdint.h> and then getting rid of the configure-time
probes.

regards, tom lane

#14Japin Li
japinli@hotmail.com
In reply to: Japin Li (#1)
Re: Cannot find a working 64-bit integer type on Illumos

On Sat, 23 Mar 2024 at 01:22, Japin Li <japinli@hotmail.com> wrote:

On Sat, 23 Mar 2024 at 01:04, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Japin Li <japinli@hotmail.com> writes:

When I try to configure PostgreSQL 16.2 on Illumos using the following command,
it complains $subject.

./configure --enable-cassert --enable-debug --enable-nls --with-perl \
--with-python --without-tcl --without-gssapi --with-openssl \
--with-ldap --with-libxml --with-libxslt --without-systemd \
--with-readline --enable-thread-safety --enable-dtrace \
DTRACEFLAGS=-64 CFLAGS=-Werror

However, if I remove the `CFLAGS=-Werror`, it works fine.
I'm not sure what happened here.

CFLAGS=-Werror breaks a whole lot of configure's tests, not only that
one. (We even have this documented, see [1].) So you can't inject
-Werror that way. What I do on my buildfarm animals is the equivalent
of

export COPT='-Werror'

after configure and before build. I think configure pays no attention
to COPT, so it'd likely be safe to keep that set all the time, but in
the buildfarm client it's just as easy to be conservative.

regards, tom lane

[1] https://www.postgresql.org/docs/devel/install-make.html#CONFIGURE-ENVVARS

Thank you very much! I didn't notice this part before.

I try to use the following to compile it, however, it cannot compile it.

$ ../configure --enable-cassert --enable-debug --enable-nls --with-perl --with-python --without-tcl --without-gssapi --with-openssl --with-ldap --with-libxml --with-libxslt --without-systemd --with-readline --enable-thread-safety --enable-dtrace DTRACEFLAGS=-64
$ make COPT='-Werror' -s
/home/japin/postgres/debug/../src/bin/pg_dump/pg_dump_sort.c: In function 'repairDependencyLoop':
/home/japin/postgres/debug/../src/bin/pg_dump/pg_dump_sort.c:1276:3: error: format not a string literal and no format arguments [-Werror=format-security]
1276 | pg_log_warning(ngettext("there are circular foreign-key constraints on this table:",
| ^~~~~~~~~~~~~~
cc1: all warnings being treated as errors
make[3]: *** [<builtin>: pg_dump_sort.o] Error 1
make[2]: *** [Makefile:43: all-pg_dump-recurse] Error 2
make[1]: *** [Makefile:42: all-bin-recurse] Error 2
make: *** [GNUmakefile:11: all-src-recurse] Error 2

#15Tom Lane
tgl@sss.pgh.pa.us
In reply to: Japin Li (#14)
Re: Cannot find a working 64-bit integer type on Illumos

Japin Li <japinli@hotmail.com> writes:

/home/japin/postgres/debug/../src/bin/pg_dump/pg_dump_sort.c: In function 'repairDependencyLoop':
/home/japin/postgres/debug/../src/bin/pg_dump/pg_dump_sort.c:1276:3: error: format not a string literal and no format arguments [-Werror=format-security]
1276 | pg_log_warning(ngettext("there are circular foreign-key constraints on this table:",
| ^~~~~~~~~~~~~~

Yeah, some of the older buildfarm animals issue that warning too.
AFAICS it's a bogus compiler heuristic: there is not anything
wrong with the code as given.

regards, tom lane

#16Japin Li
japinli@hotmail.com
In reply to: Tom Lane (#15)
Re: Cannot find a working 64-bit integer type on Illumos

On Mon, 25 Mar 2024 at 09:32, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Japin Li <japinli@hotmail.com> writes:

/home/japin/postgres/debug/../src/bin/pg_dump/pg_dump_sort.c: In function 'repairDependencyLoop':
/home/japin/postgres/debug/../src/bin/pg_dump/pg_dump_sort.c:1276:3: error: format not a string literal and no format arguments [-Werror=format-security]
1276 | pg_log_warning(ngettext("there are circular foreign-key constraints on this table:",
| ^~~~~~~~~~~~~~

Yeah, some of the older buildfarm animals issue that warning too.
AFAICS it's a bogus compiler heuristic: there is not anything
wrong with the code as given.

Thanks! It seems I should remove -Werror option on Illumos.

#17Thomas Munro
thomas.munro@gmail.com
In reply to: Tom Lane (#13)
2 attachment(s)
Re: Cannot find a working 64-bit integer type on Illumos

On Sat, Mar 23, 2024 at 3:23 PM Tom Lane <tgl@sss.pgh.pa.us> wrote:

Thomas Munro <thomas.munro@gmail.com> writes:

. o O ( int64_t, PRIdi64, etc were standardised a quarter of a century ago )

Yeah. Now that we require C99 it's probably reasonable to assume
that those things exist. I wouldn't be in favor of ripping out our
existing notations like UINT64CONST, because the code churn would be
substantial and the gain minimal. But we could imagine reimplementing
that stuff atop <stdint.h> and then getting rid of the configure-time
probes.

I played around with this a bit, but am not quite there yet.

printf() is a little tricky. The standard wants us to use
<inttypes.h>'s PRId64 etc, but that might confuse our snprintf.c (in
theory, probably not in practice). "ll" should have the right size on
all systems, but gets warnings from the printf format string checker
on systems where "l" is the right type. So I think we still need to
probe for INT64_MODIFIER at configure-time. Here's one way, but I can
see it's not working on Clang/Linux... perhaps instead of that dubious
incantation I should try compiling some actual printfs and check for
warnings/errors.

I think INT64CONST should just point to standard INT64_C().

For limits, why do we have this:

- * stdint.h limits aren't guaranteed to have compatible types with our fixed
- * width types. So just define our own.

? I mean, how could they not have compatible types?

I noticed that configure.ac checks if int64 (no "_t") might be defined
already by system header pollution, but meson.build doesn't. That's
an inconsistency that should be fixed, but which way? Hmm, commit
15abc7788e6 said that was done for BeOS, which we de-supported. So
maybe we should get rid of that?

Attachments:

0001-Use-int64_t-and-friends-from-stdint.h.patchapplication/octet-stream; name=0001-Use-int64_t-and-friends-from-stdint.h.patchDownload
From af2d279f76d05f1323e0f6e67bf3cb4fd4f68d98 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Thu, 18 Apr 2024 07:53:10 +1200
Subject: [PATCH 1/2] Use int64_t and friends from <stdint.h>.

Remove most of the configure probes for 64 bit integers.  Map our names
to the standard C99 names for types like int64_t, limits like INT64_MAX,
constant constructors like INT64_C().

We don't use printf format strings like PRId64 from <inttypes.h>,
though, because in theory they might not be understood by our
snprintf.c.  That means we still need a configure probe to find out if
it's "long" or not, so we can choose between "l" and "ll", when
implementing our own PRId64-like macros while keeping the system printf
happy too.

We can get rid of pg_config_ext.h.

XXX WIP
XXX The way of probing INT64_MODIFIER is not good enough yet
---
 configure                                     | 261 +++---------------
 configure.ac                                  |  57 +---
 meson.build                                   |  52 ++--
 src/Makefile.global.in                        |   6 -
 src/include/.gitignore                        |   2 -
 src/include/Makefile                          |   8 +-
 src/include/c.h                               |  83 +++---
 src/include/meson.build                       |  10 -
 src/include/pg_config.h.in                    |  17 +-
 src/include/pg_config_ext.h.in                |   7 -
 src/include/pg_config_ext.h.meson             |   7 -
 src/include/port/pg_bitutils.h                |  18 +-
 src/include/postgres_ext.h                    |   7 +-
 src/interfaces/ecpg/ecpglib/typename.c        |   5 +-
 src/interfaces/ecpg/include/ecpg_config.h.in  |  12 -
 src/interfaces/ecpg/include/meson.build       |   3 -
 .../ecpg/include/pgtypes_interval.h           |  13 +-
 src/interfaces/ecpg/include/sqltypes.h        |   2 +-
 .../test/expected/compat_informix-sqlda.c     |   2 +-
 src/port/pg_bitutils.c                        |   7 +-
 src/port/snprintf.c                           |  14 +-
 21 files changed, 153 insertions(+), 440 deletions(-)
 delete mode 100644 src/include/pg_config_ext.h.in
 delete mode 100644 src/include/pg_config_ext.h.meson

diff --git a/configure b/configure
index cfbd2a096f..e084fd2210 100755
--- a/configure
+++ b/configure
@@ -16439,197 +16439,6 @@ fi
 # Run tests below here
 # --------------------
 
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether long int is 64 bits" >&5
-$as_echo_n "checking whether long int is 64 bits... " >&6; }
-if ${pgac_cv_type_long_int_64+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test "$cross_compiling" = yes; then :
-  # If cross-compiling, check the size reported by the compiler and
-# trust that the arithmetic works.
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-static int test_array [1 - 2 * !(sizeof(long int) == 8)];
-test_array [0] = 0;
-return test_array [0];
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  pgac_cv_type_long_int_64=yes
-else
-  pgac_cv_type_long_int_64=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-typedef long int ac_int64;
-
-/*
- * These are globals to discourage the compiler from folding all the
- * arithmetic tests down to compile-time constants.
- */
-ac_int64 a = 20000001;
-ac_int64 b = 40000005;
-
-int does_int64_work()
-{
-  ac_int64 c,d;
-
-  if (sizeof(ac_int64) != 8)
-    return 0;			/* definitely not the right size */
-
-  /* Do perfunctory checks to see if 64-bit arithmetic seems to work */
-  c = a * b;
-  d = (c + b) / b;
-  if (d != a+1)
-    return 0;
-  return 1;
-}
-
-int
-main() {
-  return (! does_int64_work());
-}
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
-  pgac_cv_type_long_int_64=yes
-else
-  pgac_cv_type_long_int_64=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
-  conftest.$ac_objext conftest.beam conftest.$ac_ext
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_type_long_int_64" >&5
-$as_echo "$pgac_cv_type_long_int_64" >&6; }
-
-HAVE_LONG_INT_64=$pgac_cv_type_long_int_64
-if test x"$pgac_cv_type_long_int_64" = xyes ; then
-
-$as_echo "#define HAVE_LONG_INT_64 1" >>confdefs.h
-
-fi
-
-
-if test x"$HAVE_LONG_INT_64" = x"yes" ; then
-  pg_int64_type="long int"
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether long long int is 64 bits" >&5
-$as_echo_n "checking whether long long int is 64 bits... " >&6; }
-if ${pgac_cv_type_long_long_int_64+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test "$cross_compiling" = yes; then :
-  # If cross-compiling, check the size reported by the compiler and
-# trust that the arithmetic works.
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-static int test_array [1 - 2 * !(sizeof(long long int) == 8)];
-test_array [0] = 0;
-return test_array [0];
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  pgac_cv_type_long_long_int_64=yes
-else
-  pgac_cv_type_long_long_int_64=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-typedef long long int ac_int64;
-
-/*
- * These are globals to discourage the compiler from folding all the
- * arithmetic tests down to compile-time constants.
- */
-ac_int64 a = 20000001;
-ac_int64 b = 40000005;
-
-int does_int64_work()
-{
-  ac_int64 c,d;
-
-  if (sizeof(ac_int64) != 8)
-    return 0;			/* definitely not the right size */
-
-  /* Do perfunctory checks to see if 64-bit arithmetic seems to work */
-  c = a * b;
-  d = (c + b) / b;
-  if (d != a+1)
-    return 0;
-  return 1;
-}
-
-int
-main() {
-  return (! does_int64_work());
-}
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
-  pgac_cv_type_long_long_int_64=yes
-else
-  pgac_cv_type_long_long_int_64=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
-  conftest.$ac_objext conftest.beam conftest.$ac_ext
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_type_long_long_int_64" >&5
-$as_echo "$pgac_cv_type_long_long_int_64" >&6; }
-
-HAVE_LONG_LONG_INT_64=$pgac_cv_type_long_long_int_64
-if test x"$pgac_cv_type_long_long_int_64" = xyes ; then
-
-$as_echo "#define HAVE_LONG_LONG_INT_64 1" >>confdefs.h
-
-fi
-
-  if test x"$HAVE_LONG_LONG_INT_64" = x"yes" ; then
-    pg_int64_type="long long int"
-  else
-    as_fn_error $? "Cannot find a working 64-bit integer type." "$LINENO" 5
-  fi
-fi
-
-
-cat >>confdefs.h <<_ACEOF
-#define PG_INT64_TYPE $pg_int64_type
-_ACEOF
-
-
-# Select the printf length modifier that goes with that, too.
-if test x"$pg_int64_type" = x"long long int" ; then
-  INT64_MODIFIER='"ll"'
-else
-  INT64_MODIFIER='"l"'
-fi
-
-
-cat >>confdefs.h <<_ACEOF
-#define INT64_MODIFIER $INT64_MODIFIER
-_ACEOF
-
-
 # has to be down here, rather than with the other builtins, because
 # the test uses PG_INT64_TYPE.
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_mul_overflow" >&5
@@ -16877,43 +16686,41 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
-if test x"$HAVE_LONG_LONG_INT_64" = x"yes" ; then
-  # The cast to long int works around a bug in the HP C Compiler,
+# The cast to long int works around a bug in the HP C Compiler,
 # see AC_CHECK_SIZEOF for more information.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking alignment of long long int" >&5
-$as_echo_n "checking alignment of long long int... " >&6; }
-if ${ac_cv_alignof_long_long_int+:} false; then :
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking alignment of int64_t" >&5
+$as_echo_n "checking alignment of int64_t... " >&6; }
+if ${ac_cv_alignof_int64_t+:} false; then :
   $as_echo_n "(cached) " >&6
 else
-  if ac_fn_c_compute_int "$LINENO" "(long int) offsetof (ac__type_alignof_, y)" "ac_cv_alignof_long_long_int"        "$ac_includes_default
+  if ac_fn_c_compute_int "$LINENO" "(long int) offsetof (ac__type_alignof_, y)" "ac_cv_alignof_int64_t"        "$ac_includes_default
 #ifndef offsetof
 # define offsetof(type, member) ((char *) &((type *) 0)->member - (char *) 0)
 #endif
-typedef struct { char x; long long int y; } ac__type_alignof_;"; then :
+typedef struct { char x; int64_t y; } ac__type_alignof_;"; then :
 
 else
-  if test "$ac_cv_type_long_long_int" = yes; then
+  if test "$ac_cv_type_int64_t" = yes; then
      { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error 77 "cannot compute alignment of long long int
+as_fn_error 77 "cannot compute alignment of int64_t
 See \`config.log' for more details" "$LINENO" 5; }
    else
-     ac_cv_alignof_long_long_int=0
+     ac_cv_alignof_int64_t=0
    fi
 fi
 
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_alignof_long_long_int" >&5
-$as_echo "$ac_cv_alignof_long_long_int" >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_alignof_int64_t" >&5
+$as_echo "$ac_cv_alignof_int64_t" >&6; }
 
 
 
 cat >>confdefs.h <<_ACEOF
-#define ALIGNOF_LONG_LONG_INT $ac_cv_alignof_long_long_int
+#define ALIGNOF_INT64_T $ac_cv_alignof_int64_t
 _ACEOF
 
 
-fi
 # The cast to long int works around a bug in the HP C Compiler,
 # see AC_CHECK_SIZEOF for more information.
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking alignment of double" >&5
@@ -16971,8 +16778,8 @@ MAX_ALIGNOF=$ac_cv_alignof_double
 if test $ac_cv_alignof_long -gt $MAX_ALIGNOF ; then
   as_fn_error $? "alignment of 'long' is greater than the alignment of 'double'" "$LINENO" 5
 fi
-if test x"$HAVE_LONG_LONG_INT_64" = xyes && test $ac_cv_alignof_long_long_int -gt $MAX_ALIGNOF ; then
-  as_fn_error $? "alignment of 'long long int' is greater than the alignment of 'double'" "$LINENO" 5
+if test $ac_cv_alignof_int64_t -gt $MAX_ALIGNOF ; then
+  as_fn_error $? "alignment of 'int64_t' is greater than the alignment of 'double'" "$LINENO" 5
 fi
 
 cat >>confdefs.h <<_ACEOF
@@ -17025,6 +16832,38 @@ _ACEOF
 fi
 
 
+# Check how printf should display if int64_t.  "ll" has the right size on all
+# systems, but "l" might be required on some systems to avoid GCC's print type
+# mismatch warnings.
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+#include <stdint.h>
+int main(int arg, char **argv)
+{
+    _Static_assert(__builtin_types_compatible_p(long, int64_t));
+}
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  int64_modifier='"l"'
+else
+  int64_modifier='"ll"'
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+cat >>confdefs.h <<_ACEOF
+#define INT64_MODIFIER $int64_modifier
+_ACEOF
+
+
 # Some compilers offer a 128-bit integer scalar type.
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __int128" >&5
 $as_echo_n "checking for __int128... " >&6; }
@@ -19272,9 +19111,6 @@ fi
 ac_config_headers="$ac_config_headers src/include/pg_config.h"
 
 
-ac_config_headers="$ac_config_headers src/include/pg_config_ext.h"
-
-
 ac_config_headers="$ac_config_headers src/interfaces/ecpg/include/ecpg_config.h"
 
 
@@ -19989,7 +19825,6 @@ do
     "src/Makefile.port") CONFIG_LINKS="$CONFIG_LINKS src/Makefile.port:src/makefiles/Makefile.${template}" ;;
     "check_win32_symlinks") CONFIG_COMMANDS="$CONFIG_COMMANDS check_win32_symlinks" ;;
     "src/include/pg_config.h") CONFIG_HEADERS="$CONFIG_HEADERS src/include/pg_config.h" ;;
-    "src/include/pg_config_ext.h") CONFIG_HEADERS="$CONFIG_HEADERS src/include/pg_config_ext.h" ;;
     "src/interfaces/ecpg/include/ecpg_config.h") CONFIG_HEADERS="$CONFIG_HEADERS src/interfaces/ecpg/include/ecpg_config.h" ;;
 
   *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
@@ -20597,10 +20432,6 @@ $as_echo "$as_me: WARNING: *** link for $FILE -- please fix by hand" >&2;}
     "src/include/pg_config.h":H)
 # Update timestamp for pg_config.h (see Makefile.global)
 echo >src/include/stamp-h
- ;;
-    "src/include/pg_config_ext.h":H)
-# Update timestamp for pg_config_ext.h (see Makefile.global)
-echo >src/include/stamp-ext-h
  ;;
     "src/interfaces/ecpg/include/ecpg_config.h":H) echo >src/interfaces/ecpg/include/stamp-h ;;
 
diff --git a/configure.ac b/configure.ac
index 67e738d92b..e8cac06a72 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1945,37 +1945,6 @@ for the exact reason.]])],
 # Run tests below here
 # --------------------
 
-dnl Check to see if we have a working 64-bit integer type.
-dnl Since Postgres 8.4, we no longer support compilers without a working
-dnl 64-bit type; but we have to determine whether that type is called
-dnl "long int" or "long long int".
-
-PGAC_TYPE_64BIT_INT([long int])
-
-if test x"$HAVE_LONG_INT_64" = x"yes" ; then
-  pg_int64_type="long int"
-else
-  PGAC_TYPE_64BIT_INT([long long int])
-  if test x"$HAVE_LONG_LONG_INT_64" = x"yes" ; then
-    pg_int64_type="long long int"
-  else
-    AC_MSG_ERROR([Cannot find a working 64-bit integer type.])
-  fi
-fi
-
-AC_DEFINE_UNQUOTED(PG_INT64_TYPE, $pg_int64_type,
-  [Define to the name of a signed 64-bit integer type.])
-
-# Select the printf length modifier that goes with that, too.
-if test x"$pg_int64_type" = x"long long int" ; then
-  INT64_MODIFIER='"ll"'
-else
-  INT64_MODIFIER='"l"'
-fi
-
-AC_DEFINE_UNQUOTED(INT64_MODIFIER, $INT64_MODIFIER,
-                   [Define to the appropriate printf length modifier for 64-bit ints.])
-
 # has to be down here, rather than with the other builtins, because
 # the test uses PG_INT64_TYPE.
 PGAC_C_BUILTIN_OP_OVERFLOW
@@ -1990,9 +1959,7 @@ AC_CHECK_SIZEOF([long])
 AC_CHECK_ALIGNOF(short)
 AC_CHECK_ALIGNOF(int)
 AC_CHECK_ALIGNOF(long)
-if test x"$HAVE_LONG_LONG_INT_64" = x"yes" ; then
-  AC_CHECK_ALIGNOF(long long int)
-fi
+AC_CHECK_ALIGNOF(int64_t)
 AC_CHECK_ALIGNOF(double)
 
 # Compute maximum alignment of any basic type.
@@ -2016,8 +1983,8 @@ MAX_ALIGNOF=$ac_cv_alignof_double
 if test $ac_cv_alignof_long -gt $MAX_ALIGNOF ; then
   AC_MSG_ERROR([alignment of 'long' is greater than the alignment of 'double'])
 fi
-if test x"$HAVE_LONG_LONG_INT_64" = xyes && test $ac_cv_alignof_long_long_int -gt $MAX_ALIGNOF ; then
-  AC_MSG_ERROR([alignment of 'long long int' is greater than the alignment of 'double'])
+if test $ac_cv_alignof_int64_t -gt $MAX_ALIGNOF ; then
+  AC_MSG_ERROR([alignment of 'int64_t' is greater than the alignment of 'double'])
 fi
 AC_DEFINE_UNQUOTED(MAXIMUM_ALIGNOF, $MAX_ALIGNOF, [Define as the maximum alignment requirement of any C data type.])
 
@@ -2027,6 +1994,18 @@ AC_DEFINE_UNQUOTED(MAXIMUM_ALIGNOF, $MAX_ALIGNOF, [Define as the maximum alignme
 AC_CHECK_TYPES([int8, uint8, int64, uint64], [], [],
 [#include <stdio.h>])
 
+# Check how printf should display if int64_t.  "ll" has the right size on all
+# systems, but "l" might be required on some systems to avoid GCC's print type
+# mismatch warnings.
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [
+#include <stdint.h>
+int main(int arg, char **argv)
+{
+    _Static_assert(__builtin_types_compatible_p(long, int64_t));
+}
+])], [int64_modifier='"l"'], [int64_modifier='"ll"'])
+AC_DEFINE_UNQUOTED(INT64_MODIFIER, $int64_modifier, [Define to the appropriate printf length modifier for int64_t.])
+
 # Some compilers offer a 128-bit integer scalar type.
 PGAC_TYPE_128BIT_INT
 
@@ -2520,12 +2499,6 @@ AC_CONFIG_HEADERS([src/include/pg_config.h],
 echo >src/include/stamp-h
 ])
 
-AC_CONFIG_HEADERS([src/include/pg_config_ext.h],
-[
-# Update timestamp for pg_config_ext.h (see Makefile.global)
-echo >src/include/stamp-ext-h
-])
-
 AC_CONFIG_HEADERS([src/interfaces/ecpg/include/ecpg_config.h],
                   [echo >src/interfaces/ecpg/include/stamp-h])
 
diff --git a/meson.build b/meson.build
index 43fad5323c..9b01cef209 100644
--- a/meson.build
+++ b/meson.build
@@ -1488,18 +1488,6 @@ endif
 
 sizeof_long = cc.sizeof('long', args: test_c_args)
 cdata.set('SIZEOF_LONG', sizeof_long)
-if sizeof_long == 8
-  cdata.set('HAVE_LONG_INT_64', 1)
-  pg_int64_type = 'long int'
-  cdata.set_quoted('INT64_MODIFIER', 'l')
-elif sizeof_long == 4 and cc.sizeof('long long', args: test_c_args) == 8
-  cdata.set('HAVE_LONG_LONG_INT_64', 1)
-  pg_int64_type = 'long long int'
-  cdata.set_quoted('INT64_MODIFIER', 'll')
-else
-  error('do not know how to get a 64bit int')
-endif
-cdata.set('PG_INT64_TYPE', pg_int64_type)
 
 if host_machine.endian() == 'big'
   cdata.set('WORDS_BIGENDIAN', 1)
@@ -1529,11 +1517,28 @@ endforeach
 # any types wider than 64 bits, as allowing MAXIMUM_ALIGNOF to exceed 8
 # would be too much of a penalty for disk and memory space.
 alignof_double = cdata.get('ALIGNOF_DOUBLE')
-if cc.alignment(pg_int64_type, args: test_c_args) > alignof_double
-  error('alignment of int64 is greater than the alignment of double')
+if cc.alignment('int64_t', args: test_c_args, prefix: '#include <stdint.h>') > alignof_double
+  error('alignment of int64_t is greater than the alignment of double')
 endif
 cdata.set('MAXIMUM_ALIGNOF', alignof_double)
 
+# Check how printf should display if int64_t.  "ll" has the right size on all
+# systems, but "l" might be required on some systems to avoid GCC's print type
+# mismatch warnings.
+if cc.compiles('''
+    #include <stdint.h>
+    int main(int arg, char **argv)
+    {
+		_Static_assert(__builtin_types_compatible_p(long, int64_t));
+    }
+    ''',
+    args: test_c_args)
+  int64_modifier = 'l'
+else
+  int64_modifier = 'll'
+endif
+cdata.set_quoted('INT64_MODIFIER', int64_modifier)
+
 cdata.set('SIZEOF_VOID_P', cc.sizeof('void *', args: test_c_args))
 cdata.set('SIZEOF_SIZE_T', cc.sizeof('size_t', args: test_c_args))
 
@@ -1742,17 +1747,17 @@ endif
 # compile, and store the results in global variables so the compiler doesn't
 # optimize away the call.
 if cc.links('''
-    INT64 a = 1;
-    INT64 b = 1;
-    INT64 result;
+    #include <stdint.h>
+    int64_t a = 1;
+    int64_t b = 1;
+    int64_t result;
 
     int main(void)
     {
         return __builtin_mul_overflow(a, b, &result);
     }''',
     name: '__builtin_mul_overflow',
-    args: test_c_args + ['-DINT64=@0@'.format(cdata.get('PG_INT64_TYPE'))],
-    )
+    args: test_c_args)
   cdata.set('HAVE__BUILTIN_OP_OVERFLOW', 1)
 endif
 
@@ -2013,7 +2018,7 @@ int main(void)
     cdata.set(check['name'],
       cc.links(test,
         name: check['desc'],
-        args: test_c_args + ['-DINT64=@0@'.format(cdata.get('PG_INT64_TYPE'))]) ? 1 : false
+        args: test_c_args) ? 1 : false
     )
   endforeach
 
@@ -2057,11 +2062,12 @@ if host_cpu == 'x86_64'
 
   prog = '''
 #include <immintrin.h>
+#include <stdint.h>
 
 int main(void)
 {
     const char buf[sizeof(__m512i)];
-    INT64 popcnt = 0;
+    int64_t popcnt = 0;
     __m512i accum = _mm512_setzero_si512();
     const __m512i val = _mm512_maskz_loadu_epi8((__mmask64) 0xf0f0f0f0f0f0f0f0, (const __m512i *) buf);
     const __m512i cnt = _mm512_popcnt_epi64(val);
@@ -2073,10 +2079,10 @@ int main(void)
 '''
 
   if cc.links(prog, name: 'AVX-512 popcount without -mavx512vpopcntdq -mavx512bw',
-        args: test_c_args + ['-DINT64=@0@'.format(cdata.get('PG_INT64_TYPE'))])
+        args: test_c_args)
     cdata.set('USE_AVX512_POPCNT_WITH_RUNTIME_CHECK', 1)
   elif cc.links(prog, name: 'AVX-512 popcount with -mavx512vpopcntdq -mavx512bw',
-        args: test_c_args + ['-DINT64=@0@'.format(cdata.get('PG_INT64_TYPE'))] + ['-mavx512vpopcntdq'] + ['-mavx512bw'])
+        args: test_c_args + ['-mavx512vpopcntdq'] + ['-mavx512bw'])
     cdata.set('USE_AVX512_POPCNT_WITH_RUNTIME_CHECK', 1)
     cflags_popcnt += ['-mavx512vpopcntdq'] + ['-mavx512bw']
   endif
diff --git a/src/Makefile.global.in b/src/Makefile.global.in
index 36d880d225..1928fc2f2c 100644
--- a/src/Makefile.global.in
+++ b/src/Makefile.global.in
@@ -833,12 +833,6 @@ $(top_builddir)/src/include/pg_config.h: $(top_builddir)/src/include/stamp-h ;
 $(top_builddir)/src/include/stamp-h: $(top_srcdir)/src/include/pg_config.h.in $(top_builddir)/config.status
 	cd $(top_builddir) && ./config.status src/include/pg_config.h
 
-# Also remake pg_config_ext.h from pg_config_ext.h.in, same logic as above.
-$(top_builddir)/src/include/pg_config_ext.h: $(top_builddir)/src/include/stamp-ext-h ;
-
-$(top_builddir)/src/include/stamp-ext-h: $(top_srcdir)/src/include/pg_config_ext.h.in $(top_builddir)/config.status
-	cd $(top_builddir) && ./config.status src/include/pg_config_ext.h
-
 # Also remake ecpg_config.h from ecpg_config.h.in if the latter changed, same
 # logic as above.
 $(top_builddir)/src/interfaces/ecpg/include/ecpg_config.h: $(top_builddir)/src/interfaces/ecpg/include/stamp-h ;
diff --git a/src/include/.gitignore b/src/include/.gitignore
index 51819fb4dd..6e99e82fe0 100644
--- a/src/include/.gitignore
+++ b/src/include/.gitignore
@@ -1,5 +1,3 @@
 /stamp-h
-/stamp-ext-h
 /pg_config.h
-/pg_config_ext.h
 /pg_config_os.h
diff --git a/src/include/Makefile b/src/include/Makefile
index b8b576a4de..26332ff9cb 100644
--- a/src/include/Makefile
+++ b/src/include/Makefile
@@ -13,7 +13,7 @@ top_builddir = ../..
 include $(top_builddir)/src/Makefile.global
 
 
-all: pg_config.h pg_config_ext.h pg_config_os.h
+all: pg_config.h pg_config_os.h
 
 
 # Subdirectories containing installable headers
@@ -32,7 +32,6 @@ install: all installdirs
 	$(INSTALL_DATA) $(srcdir)/postgres_ext.h   '$(DESTDIR)$(includedir)'
 	$(INSTALL_DATA) $(srcdir)/libpq/libpq-fs.h '$(DESTDIR)$(includedir)/libpq'
 	$(INSTALL_DATA) pg_config.h     '$(DESTDIR)$(includedir)'
-	$(INSTALL_DATA) pg_config_ext.h '$(DESTDIR)$(includedir)'
 	$(INSTALL_DATA) pg_config_os.h  '$(DESTDIR)$(includedir)'
 	$(INSTALL_DATA) $(srcdir)/pg_config_manual.h '$(DESTDIR)$(includedir)'
 # These headers are needed by the not-so-public headers of the interfaces.
@@ -43,7 +42,6 @@ install: all installdirs
 	$(INSTALL_DATA) $(srcdir)/libpq/protocol.h '$(DESTDIR)$(includedir_internal)/libpq'
 # These headers are needed for server-side development
 	$(INSTALL_DATA) pg_config.h     '$(DESTDIR)$(includedir_server)'
-	$(INSTALL_DATA) pg_config_ext.h '$(DESTDIR)$(includedir_server)'
 	$(INSTALL_DATA) pg_config_os.h  '$(DESTDIR)$(includedir_server)'
 	$(INSTALL_DATA) nodes/nodetags.h '$(DESTDIR)$(includedir_server)/nodes'
 	$(INSTALL_DATA) utils/errcodes.h '$(DESTDIR)$(includedir_server)/utils'
@@ -66,7 +64,7 @@ installdirs:
 
 
 uninstall:
-	rm -f $(addprefix '$(DESTDIR)$(includedir)'/, pg_config.h pg_config_ext.h pg_config_os.h pg_config_manual.h postgres_ext.h libpq/libpq-fs.h)
+	rm -f $(addprefix '$(DESTDIR)$(includedir)'/, pg_config.h pg_config_os.h pg_config_manual.h postgres_ext.h libpq/libpq-fs.h)
 	rm -f $(addprefix '$(DESTDIR)$(includedir_internal)'/, c.h port.h postgres_fe.h libpq/pqcomm.h libpq/protocol.h)
 # heuristic...
 	rm -rf $(addprefix '$(DESTDIR)$(includedir_server)'/, $(SUBDIRS) *.h)
@@ -80,4 +78,4 @@ clean:
 	$(MAKE) -C catalog clean
 
 distclean: clean
-	rm -f pg_config.h pg_config_ext.h pg_config_os.h stamp-h stamp-ext-h
+	rm -f pg_config.h pg_config_os.h stamp-h stamp-ext-h
diff --git a/src/include/c.h b/src/include/c.h
index dc1841346c..b7f97d412c 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -48,9 +48,6 @@
 
 #include "postgres_ext.h"
 
-/* Must undef pg_config_ext.h symbols before including pg_config.h */
-#undef PG_INT64_TYPE
-
 #include "pg_config.h"
 #include "pg_config_manual.h"	/* must be after pg_config.h */
 #include "pg_config_os.h"		/* must be before any system header files */
@@ -489,10 +486,13 @@ typedef char *Pointer;
  *		frontend/backend protocol.
  */
 #ifndef HAVE_INT8
-typedef signed char int8;		/* == 8 bits */
-typedef signed short int16;		/* == 16 bits */
-typedef signed int int32;		/* == 32 bits */
+typedef int8_t int8;			/* == 8 bits */
+typedef int16_t int16;			/* == 16 bits */
+typedef int32_t int32;			/* == 32 bits */
 #endif							/* not HAVE_INT8 */
+#ifndef HAVE_INT64
+typedef int64_t int64;			/* == 64 bits */
+#endif							/* not HAVE_INT64 */
 
 /*
  * uintN
@@ -501,10 +501,13 @@ typedef signed int int32;		/* == 32 bits */
  *		frontend/backend protocol.
  */
 #ifndef HAVE_UINT8
-typedef unsigned char uint8;	/* == 8 bits */
-typedef unsigned short uint16;	/* == 16 bits */
-typedef unsigned int uint32;	/* == 32 bits */
+typedef uint8_t uint8;			/* == 8 bits */
+typedef uint16_t uint16;		/* == 16 bits */
+typedef uint32_t uint32;		/* == 32 bits */
 #endif							/* not HAVE_UINT8 */
+#ifndef HAVE_UINT64
+typedef uint64_t uint64;		/* == 64 bits */
+#endif							/* not HAVE_UINT64 */
 
 /*
  * bitsN
@@ -517,34 +520,13 @@ typedef uint32 bits32;			/* >= 32 bits */
 /*
  * 64-bit integers
  */
-#ifdef HAVE_LONG_INT_64
-/* Plain "long int" fits, use it */
-
-#ifndef HAVE_INT64
-typedef long int int64;
-#endif
-#ifndef HAVE_UINT64
-typedef unsigned long int uint64;
-#endif
-#define INT64CONST(x)  (x##L)
-#define UINT64CONST(x) (x##UL)
-#elif defined(HAVE_LONG_LONG_INT_64)
-/* We have working support for "long long int", use that */
+#define INT64CONST(x)  INT64_C(x)
+#define UINT64CONST(x) UINT64_C(x)
 
-#ifndef HAVE_INT64
-typedef long long int int64;
-#endif
-#ifndef HAVE_UINT64
-typedef unsigned long long int uint64;
-#endif
-#define INT64CONST(x)  (x##LL)
-#define UINT64CONST(x) (x##ULL)
-#else
-/* neither HAVE_LONG_INT_64 nor HAVE_LONG_LONG_INT_64 */
-#error must have a working 64-bit integer datatype
-#endif
-
-/* snprintf format strings to use for 64-bit integers */
+/*
+ * snprintf format strings to use for 64-bit integers, instead of PRId64 etc
+ * which might confuse our snprintf.c.
+ */
 #define INT64_FORMAT "%" INT64_MODIFIER "d"
 #define UINT64_FORMAT "%" INT64_MODIFIER "u"
 
@@ -575,22 +557,19 @@ typedef unsigned PG_INT128_TYPE uint128
 #endif
 #endif
 
-/*
- * stdint.h limits aren't guaranteed to have compatible types with our fixed
- * width types. So just define our own.
- */
-#define PG_INT8_MIN		(-0x7F-1)
-#define PG_INT8_MAX		(0x7F)
-#define PG_UINT8_MAX	(0xFF)
-#define PG_INT16_MIN	(-0x7FFF-1)
-#define PG_INT16_MAX	(0x7FFF)
-#define PG_UINT16_MAX	(0xFFFF)
-#define PG_INT32_MIN	(-0x7FFFFFFF-1)
-#define PG_INT32_MAX	(0x7FFFFFFF)
-#define PG_UINT32_MAX	(0xFFFFFFFFU)
-#define PG_INT64_MIN	(-INT64CONST(0x7FFFFFFFFFFFFFFF) - 1)
-#define PG_INT64_MAX	INT64CONST(0x7FFFFFFFFFFFFFFF)
-#define PG_UINT64_MAX	UINT64CONST(0xFFFFFFFFFFFFFFFF)
+/* Historical names for limits in stdint.h. */
+#define PG_INT8_MIN		INT8_MIN
+#define PG_INT8_MAX		INT8_MAX
+#define PG_UINT8_MAX	UINT8_MAX
+#define PG_INT16_MIN	INT16_MIN
+#define PG_INT16_MAX	INT16_MAX
+#define PG_UINT16_MAX	UINT16_MAX
+#define PG_INT32_MIN	INT32_MIN
+#define PG_INT32_MAX	INT32_MAX
+#define PG_UINT32_MAX	UINT32_MAX
+#define PG_INT64_MIN	INT64_MIN
+#define PG_INT64_MAX	INT64_MAX
+#define PG_UINT64_MAX	UINT64_MAX
 
 /*
  * We now always use int64 timestamps, but keep this symbol defined for the
diff --git a/src/include/meson.build b/src/include/meson.build
index a28f115d86..6b9116341f 100644
--- a/src/include/meson.build
+++ b/src/include/meson.build
@@ -1,14 +1,5 @@
 # Copyright (c) 2022-2024, PostgreSQL Global Development Group
 
-pg_config_ext = configure_file(
-  input: 'pg_config_ext.h.meson',
-  output: 'pg_config_ext.h',
-  configuration: cdata,
-  install: true,
-  install_dir: dir_include,
-)
-configure_files += pg_config_ext
-
 pg_config_os = configure_file(
   output: 'pg_config_os.h',
   input: files('port/@0@.h'.format(portname)),
@@ -116,7 +107,6 @@ install_headers(
   'postgres_fe.h',
   'varatt.h',
   'windowapi.h',
-  pg_config_ext,
   pg_config_os,
   pg_config,
   install_dir: dir_include_server,
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index f8d3e3b6b8..2141010487 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -9,12 +9,12 @@
 /* The normal alignment of `int', in bytes. */
 #undef ALIGNOF_INT
 
+/* The normal alignment of `int64_t', in bytes. */
+#undef ALIGNOF_INT64_T
+
 /* The normal alignment of `long', in bytes. */
 #undef ALIGNOF_LONG
 
-/* The normal alignment of `long long int', in bytes. */
-#undef ALIGNOF_LONG_LONG_INT
-
 /* The normal alignment of `PG_INT128_TYPE', in bytes. */
 #undef ALIGNOF_PG_INT128_TYPE
 
@@ -282,12 +282,6 @@
 /* Define to 1 if you have the `zstd' library (-lzstd). */
 #undef HAVE_LIBZSTD
 
-/* Define to 1 if `long int' works and is 64 bits. */
-#undef HAVE_LONG_INT_64
-
-/* Define to 1 if `long long int' works and is 64 bits. */
-#undef HAVE_LONG_LONG_INT_64
-
 /* Define to 1 if you have the <mbarrier.h> header file. */
 #undef HAVE_MBARRIER_H
 
@@ -570,7 +564,7 @@
 /* Define to 1 if your compiler understands _Static_assert. */
 #undef HAVE__STATIC_ASSERT
 
-/* Define to the appropriate printf length modifier for 64-bit ints. */
+/* Define to the appropriate printf length modifier for int64_t. */
 #undef INT64_MODIFIER
 
 /* Define to 1 if `locale_t' requires <xlocale.h>. */
@@ -607,9 +601,6 @@
 /* Define to the name of a signed 128-bit integer type. */
 #undef PG_INT128_TYPE
 
-/* Define to the name of a signed 64-bit integer type. */
-#undef PG_INT64_TYPE
-
 /* Define to the name of the default PostgreSQL service principal in Kerberos
    (GSSAPI). (--with-krb-srvnam=NAME) */
 #undef PG_KRB_SRVNAM
diff --git a/src/include/pg_config_ext.h.in b/src/include/pg_config_ext.h.in
deleted file mode 100644
index 8acadbdafd..0000000000
--- a/src/include/pg_config_ext.h.in
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
- * src/include/pg_config_ext.h.in.  This is generated manually, not by
- * autoheader, since we want to limit which symbols get defined here.
- */
-
-/* Define to the name of a signed 64-bit integer type. */
-#undef PG_INT64_TYPE
diff --git a/src/include/pg_config_ext.h.meson b/src/include/pg_config_ext.h.meson
deleted file mode 100644
index 57cdfca0cf..0000000000
--- a/src/include/pg_config_ext.h.meson
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
- * src/include/pg_config_ext.h.in.  This is generated manually, not by
- * autoheader, since we want to limit which symbols get defined here.
- */
-
-/* Define to the name of a signed 64-bit integer type. */
-#mesondefine PG_INT64_TYPE
diff --git a/src/include/port/pg_bitutils.h b/src/include/port/pg_bitutils.h
index 4d88478c9c..1c09bf0ff2 100644
--- a/src/include/port/pg_bitutils.h
+++ b/src/include/port/pg_bitutils.h
@@ -74,13 +74,12 @@ pg_leftmost_one_pos64(uint64 word)
 #ifdef HAVE__BUILTIN_CLZ
 	Assert(word != 0);
 
-#if defined(HAVE_LONG_INT_64)
+#if SIZEOF_LONG == 8
 	return 63 - __builtin_clzl(word);
-#elif defined(HAVE_LONG_LONG_INT_64)
-	return 63 - __builtin_clzll(word);
 #else
-#error must have a working 64-bit integer datatype
-#endif							/* HAVE_LONG_INT_64 */
+	StaticAssertStmt(sizeof(word) == sizeof(long long), "unexpected size");
+	return 63 - __builtin_clzll(word);
+#endif
 
 #elif defined(_MSC_VER) && (defined(_M_AMD64) || defined(_M_ARM64))
 	unsigned long result;
@@ -147,13 +146,12 @@ pg_rightmost_one_pos64(uint64 word)
 #ifdef HAVE__BUILTIN_CTZ
 	Assert(word != 0);
 
-#if defined(HAVE_LONG_INT_64)
+#if SIZEOF_LONG == 8
 	return __builtin_ctzl(word);
-#elif defined(HAVE_LONG_LONG_INT_64)
-	return __builtin_ctzll(word);
 #else
-#error must have a working 64-bit integer datatype
-#endif							/* HAVE_LONG_INT_64 */
+	StaticAssertStmt(sizeof(word) == sizeof(long long), "unexpected size");
+	return __builtin_ctzll(word);
+#endif
 
 #elif defined(_MSC_VER) && (defined(_M_AMD64) || defined(_M_ARM64))
 	unsigned long result;
diff --git a/src/include/postgres_ext.h b/src/include/postgres_ext.h
index 240ad4e93b..034056e7d9 100644
--- a/src/include/postgres_ext.h
+++ b/src/include/postgres_ext.h
@@ -23,7 +23,7 @@
 #ifndef POSTGRES_EXT_H
 #define POSTGRES_EXT_H
 
-#include "pg_config_ext.h"
+#include <stdint.h>
 
 /*
  * Object ID is a fundamental type in Postgres.
@@ -36,15 +36,14 @@ typedef unsigned int Oid;
 #define InvalidOid		((Oid) 0)
 #endif
 
-#define OID_MAX  UINT_MAX
-/* you will need to include <limits.h> to use the above #define */
+#define OID_MAX  UINT32_MAX
 
 #define atooid(x) ((Oid) strtoul((x), NULL, 10))
 /* the above needs <stdlib.h> */
 
 
 /* Define a signed 64-bit integer type for use in client API declarations. */
-typedef PG_INT64_TYPE pg_int64;
+typedef int64_t pg_int64;
 
 /*
  * Identifiers of error message fields.  Kept here to keep common
diff --git a/src/interfaces/ecpg/ecpglib/typename.c b/src/interfaces/ecpg/ecpglib/typename.c
index 1d482c4fa6..1ab2cda848 100644
--- a/src/interfaces/ecpg/ecpglib/typename.c
+++ b/src/interfaces/ecpg/ecpglib/typename.c
@@ -131,10 +131,9 @@ sqlda_dynamic_type(Oid type, enum COMPAT_MODE compat)
 		case INTERVALOID:
 			return ECPGt_interval;
 		case INT8OID:
-#ifdef HAVE_LONG_LONG_INT_64
+#if SIZEOF_LONG < 8
 			return ECPGt_long_long;
-#endif
-#ifdef HAVE_LONG_INT_64
+#else
 			return ECPGt_long;
 #endif
 			/* Unhandled types always return a string */
diff --git a/src/interfaces/ecpg/include/ecpg_config.h.in b/src/interfaces/ecpg/include/ecpg_config.h.in
index 5d0f448a86..48bce0878a 100644
--- a/src/interfaces/ecpg/include/ecpg_config.h.in
+++ b/src/interfaces/ecpg/include/ecpg_config.h.in
@@ -1,17 +1,5 @@
 /* Define to 1 to build client libraries as thread-safe code. */
 #define ENABLE_THREAD_SAFETY 1
 
-/* Define to 1 if the system has the type `int64'. */
-#undef HAVE_INT64
-
-/* Define to 1 if `long int' works and is 64 bits. */
-#undef HAVE_LONG_INT_64
-
-/* Define to 1 if the system has the type `long long int'. */
-#define HAVE_LONG_LONG_INT 1
-
-/* Define to 1 if `long long int' works and is 64 bits. */
-#undef HAVE_LONG_LONG_INT_64
-
 /* Define to 1 to use <stdbool.h> to define type bool. */
 #undef PG_USE_STDBOOL
diff --git a/src/interfaces/ecpg/include/meson.build b/src/interfaces/ecpg/include/meson.build
index 31610fef58..d0234413fc 100644
--- a/src/interfaces/ecpg/include/meson.build
+++ b/src/interfaces/ecpg/include/meson.build
@@ -3,9 +3,6 @@
 ecpg_inc = include_directories('.')
 
 ecpg_conf_keys = [
-  'HAVE_INT64',
-  'HAVE_LONG_INT_64',
-  'HAVE_LONG_LONG_INT_64',
   'PG_USE_STDBOOL',
 ]
 
diff --git a/src/interfaces/ecpg/include/pgtypes_interval.h b/src/interfaces/ecpg/include/pgtypes_interval.h
index 2809b356f7..d16f74970c 100644
--- a/src/interfaces/ecpg/include/pgtypes_interval.h
+++ b/src/interfaces/ecpg/include/pgtypes_interval.h
@@ -8,18 +8,7 @@
 
 #ifndef C_H
 
-#ifdef HAVE_LONG_INT_64
-#ifndef HAVE_INT64
-typedef long int int64;
-#endif
-#elif defined(HAVE_LONG_LONG_INT_64)
-#ifndef HAVE_INT64
-typedef long long int int64;
-#endif
-#else
-/* neither HAVE_LONG_INT_64 nor HAVE_LONG_LONG_INT_64 */
-#error must have a working 64-bit integer datatype
-#endif
+typedef int64_t int64;
 
 #define HAVE_INT64_TIMESTAMP
 #endif							/* C_H */
diff --git a/src/interfaces/ecpg/include/sqltypes.h b/src/interfaces/ecpg/include/sqltypes.h
index e7cbfa4795..aed055eb4a 100644
--- a/src/interfaces/ecpg/include/sqltypes.h
+++ b/src/interfaces/ecpg/include/sqltypes.h
@@ -46,7 +46,7 @@
 #define SQLINTERVAL		ECPGt_interval
 #define SQLNCHAR	ECPGt_char
 #define SQLNVCHAR	ECPGt_char
-#ifdef HAVE_LONG_LONG_INT_64
+#if SIZEOF_LONG < 8
 #define SQLINT8		ECPGt_long_long
 #define SQLSERIAL8	ECPGt_long_long
 #else
diff --git a/src/interfaces/ecpg/test/expected/compat_informix-sqlda.c b/src/interfaces/ecpg/test/expected/compat_informix-sqlda.c
index 7e19319d27..02ec7b668d 100644
--- a/src/interfaces/ecpg/test/expected/compat_informix-sqlda.c
+++ b/src/interfaces/ecpg/test/expected/compat_informix-sqlda.c
@@ -97,7 +97,7 @@ typedef struct sqlda_struct sqlda_t;
 #define SQLINTERVAL		ECPGt_interval
 #define SQLNCHAR	ECPGt_char
 #define SQLNVCHAR	ECPGt_char
-#ifdef HAVE_LONG_LONG_INT_64
+#if SIZEOF_LONG < 8
 #define SQLINT8		ECPGt_long_long
 #define SQLSERIAL8	ECPGt_long_long
 #else
diff --git a/src/port/pg_bitutils.c b/src/port/pg_bitutils.c
index 87f56e82b8..d4413a299a 100644
--- a/src/port/pg_bitutils.c
+++ b/src/port/pg_bitutils.c
@@ -370,12 +370,11 @@ static inline int
 pg_popcount64_slow(uint64 word)
 {
 #ifdef HAVE__BUILTIN_POPCOUNT
-#if defined(HAVE_LONG_INT_64)
+#if SIZEOF_LONG == 8
 	return __builtin_popcountl(word);
-#elif defined(HAVE_LONG_LONG_INT_64)
-	return __builtin_popcountll(word);
 #else
-#error must have a working 64-bit integer datatype
+	StaticAssertStmt(sizeof(word) == sizeof(long long), "unexpected size");
+	return __builtin_popcountll(word);
 #endif
 #else							/* !HAVE__BUILTIN_POPCOUNT */
 	int			result = 0;
diff --git a/src/port/snprintf.c b/src/port/snprintf.c
index 884f0262dd..291148b4e8 100644
--- a/src/port/snprintf.c
+++ b/src/port/snprintf.c
@@ -568,12 +568,11 @@ nextch2:
 				goto nextch2;
 			case 'z':
 #if SIZEOF_SIZE_T == 8
-#ifdef HAVE_LONG_INT_64
+#if SIZEOF_LONG == 8
 				longflag = 1;
-#elif defined(HAVE_LONG_LONG_INT_64)
-				longlongflag = 1;
 #else
-#error "Don't know how to print 64bit integers"
+				StaticAssertStmt(sizeof(size_t) == sizeof(long long), "unexpected size");
+				longlongflag = 1;
 #endif
 #else
 				/* assume size_t is same size as int */
@@ -835,12 +834,11 @@ nextch1:
 				goto nextch1;
 			case 'z':
 #if SIZEOF_SIZE_T == 8
-#ifdef HAVE_LONG_INT_64
+#if SIZEOF_LONG == 8
 				longflag = 1;
-#elif defined(HAVE_LONG_LONG_INT_64)
-				longlongflag = 1;
 #else
-#error "Don't know how to print 64bit integers"
+				StaticAssertStmt(sizeof(size_t) == sizeof(long long), "unexpected size");
+				longlongflag = 1;
 #endif
 #else
 				/* assume size_t is same size as int */
-- 
2.39.3 (Apple Git-146)

0002-Remove-traces-of-BeOS.patchapplication/octet-stream; name=0002-Remove-traces-of-BeOS.patchDownload
From 6b773c9489ee1117cea8ec7e03f3e585eb9960c7 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Thu, 18 Apr 2024 12:06:17 +1200
Subject: [PATCH 2/2] Remove traces of BeOS.

Commit 15abc7788e6 tolerated namespace pollution from BeOS system
headers.  Commit 44f902122 de-supported BeOS.  Since that stuff didn't
make it into the Meson build system, synchronize by removing from
configure.
---
 configure                  | 45 --------------------------------------
 configure.ac               |  6 -----
 src/include/c.h            |  8 -------
 src/include/pg_config.h.in | 12 ----------
 4 files changed, 71 deletions(-)

diff --git a/configure b/configure
index e084fd2210..d5da3712e6 100755
--- a/configure
+++ b/configure
@@ -16787,51 +16787,6 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
-
-# Some platforms predefine the types int8, int16, etc.  Only check
-# a (hopefully) representative subset.
-ac_fn_c_check_type "$LINENO" "int8" "ac_cv_type_int8" "#include <stdio.h>
-"
-if test "x$ac_cv_type_int8" = xyes; then :
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_INT8 1
-_ACEOF
-
-
-fi
-ac_fn_c_check_type "$LINENO" "uint8" "ac_cv_type_uint8" "#include <stdio.h>
-"
-if test "x$ac_cv_type_uint8" = xyes; then :
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_UINT8 1
-_ACEOF
-
-
-fi
-ac_fn_c_check_type "$LINENO" "int64" "ac_cv_type_int64" "#include <stdio.h>
-"
-if test "x$ac_cv_type_int64" = xyes; then :
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_INT64 1
-_ACEOF
-
-
-fi
-ac_fn_c_check_type "$LINENO" "uint64" "ac_cv_type_uint64" "#include <stdio.h>
-"
-if test "x$ac_cv_type_uint64" = xyes; then :
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_UINT64 1
-_ACEOF
-
-
-fi
-
-
 # Check how printf should display if int64_t.  "ll" has the right size on all
 # systems, but "l" might be required on some systems to avoid GCC's print type
 # mismatch warnings.
diff --git a/configure.ac b/configure.ac
index e8cac06a72..49b9287585 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1988,12 +1988,6 @@ if test $ac_cv_alignof_int64_t -gt $MAX_ALIGNOF ; then
 fi
 AC_DEFINE_UNQUOTED(MAXIMUM_ALIGNOF, $MAX_ALIGNOF, [Define as the maximum alignment requirement of any C data type.])
 
-
-# Some platforms predefine the types int8, int16, etc.  Only check
-# a (hopefully) representative subset.
-AC_CHECK_TYPES([int8, uint8, int64, uint64], [], [],
-[#include <stdio.h>])
-
 # Check how printf should display if int64_t.  "ll" has the right size on all
 # systems, but "l" might be required on some systems to avoid GCC's print type
 # mismatch warnings.
diff --git a/src/include/c.h b/src/include/c.h
index b7f97d412c..90d70d6491 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -485,14 +485,10 @@ typedef char *Pointer;
  *		used for numerical computations and the
  *		frontend/backend protocol.
  */
-#ifndef HAVE_INT8
 typedef int8_t int8;			/* == 8 bits */
 typedef int16_t int16;			/* == 16 bits */
 typedef int32_t int32;			/* == 32 bits */
-#endif							/* not HAVE_INT8 */
-#ifndef HAVE_INT64
 typedef int64_t int64;			/* == 64 bits */
-#endif							/* not HAVE_INT64 */
 
 /*
  * uintN
@@ -500,14 +496,10 @@ typedef int64_t int64;			/* == 64 bits */
  *		used for numerical computations and the
  *		frontend/backend protocol.
  */
-#ifndef HAVE_UINT8
 typedef uint8_t uint8;			/* == 8 bits */
 typedef uint16_t uint16;		/* == 16 bits */
 typedef uint32_t uint32;		/* == 32 bits */
-#endif							/* not HAVE_UINT8 */
-#ifndef HAVE_UINT64
 typedef uint64_t uint64;		/* == 64 bits */
-#endif							/* not HAVE_UINT64 */
 
 /*
  * bitsN
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index 2141010487..8a34a8d295 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -213,12 +213,6 @@
 /* Define to 1 if you have the `inet_pton' function. */
 #undef HAVE_INET_PTON
 
-/* Define to 1 if the system has the type `int64'. */
-#undef HAVE_INT64
-
-/* Define to 1 if the system has the type `int8'. */
-#undef HAVE_INT8
-
 /* Define to 1 if you have the <inttypes.h> header file. */
 #undef HAVE_INTTYPES_H
 
@@ -465,12 +459,6 @@
 /* Define to 1 if you have the <ucred.h> header file. */
 #undef HAVE_UCRED_H
 
-/* Define to 1 if the system has the type `uint64'. */
-#undef HAVE_UINT64
-
-/* Define to 1 if the system has the type `uint8'. */
-#undef HAVE_UINT8
-
 /* Define to 1 if the system has the type `union semun'. */
 #undef HAVE_UNION_SEMUN
 
-- 
2.39.3 (Apple Git-146)

#18Japin Li
japinli@hotmail.com
In reply to: Thomas Munro (#17)
Re: Cannot find a working 64-bit integer type on Illumos

On Thu, 18 Apr 2024 at 08:31, Thomas Munro <thomas.munro@gmail.com> wrote:

On Sat, Mar 23, 2024 at 3:23 PM Tom Lane <tgl@sss.pgh.pa.us> wrote:

Thomas Munro <thomas.munro@gmail.com> writes:

. o O ( int64_t, PRIdi64, etc were standardised a quarter of a century ago )

Yeah. Now that we require C99 it's probably reasonable to assume
that those things exist. I wouldn't be in favor of ripping out our
existing notations like UINT64CONST, because the code churn would be
substantial and the gain minimal. But we could imagine reimplementing
that stuff atop <stdint.h> and then getting rid of the configure-time
probes.

I played around with this a bit, but am not quite there yet.

printf() is a little tricky. The standard wants us to use
<inttypes.h>'s PRId64 etc, but that might confuse our snprintf.c (in
theory, probably not in practice). "ll" should have the right size on
all systems, but gets warnings from the printf format string checker
on systems where "l" is the right type. So I think we still need to
probe for INT64_MODIFIER at configure-time. Here's one way, but I can
see it's not working on Clang/Linux... perhaps instead of that dubious
incantation I should try compiling some actual printfs and check for
warnings/errors.

I think INT64CONST should just point to standard INT64_C().

For limits, why do we have this:

- * stdint.h limits aren't guaranteed to have compatible types with our fixed
- * width types. So just define our own.

? I mean, how could they not have compatible types?

I noticed that configure.ac checks if int64 (no "_t") might be defined
already by system header pollution, but meson.build doesn't. That's
an inconsistency that should be fixed, but which way? Hmm, commit
15abc7788e6 said that was done for BeOS, which we de-supported. So
maybe we should get rid of that?

Thanks for working on this! I test the patch and it now works on Illumos when
configure with -Werror option. However, there are some errors when compiling.

In file included from /home/japin/postgres/build/../src/include/c.h:834,
from /home/japin/postgres/build/../src/include/postgres_fe.h:25,
from /home/japin/postgres/build/../src/common/config_info.c:20:
/home/japin/postgres/build/../src/common/config_info.c: In function 'get_configdata':
/home/japin/postgres/build/../src/common/config_info.c:198:11: error: comparison of integer expressions of different signedness: 'int' and 'size_t' {aka 'long unsigned int'} [-Werror=sign-compare]
198 | Assert(i == *configdata_len);
| ^~
/home/japin/postgres/build/../src/common/config_info.c:198:2: note: in expansion of macro 'Assert'
198 | Assert(i == *configdata_len);
| ^~~~~~
In file included from /home/japin/postgres/build/../src/common/blkreftable.c:36:
/home/japin/postgres/build/../src/include/lib/simplehash.h: In function 'blockreftable_stat':
/home/japin/postgres/build/../src/include/lib/simplehash.h:1138:9: error: format '%llu' expects argument of type 'long long unsigned int', but argument 4 has type 'uint64' {aka 'long unsigned int'} [-Werror=format=]
1138 | sh_log("size: " UINT64_FORMAT ", members: %u, filled: %f, total chain: %u, max chain: %u, avg chain: %f, total_collisions: %u, max_collisions: %u, avg_collisions: %f",
| ^~~~~~~~
1139 | tb->size, tb->members, fillfactor, total_chain_length, max_chain_length, avg_chain_length,
| ~~~~~~~~
| |
| uint64 {aka long unsigned int}
/home/japin/postgres/build/../src/include/common/logging.h:125:46: note: in definition of macro 'pg_log_info'
125 | pg_log_generic(PG_LOG_INFO, PG_LOG_PRIMARY, __VA_ARGS__)
| ^~~~~~~~~~~
/home/japin/postgres/build/../src/include/lib/simplehash.h:1138:2: note: in expansion of macro 'sh_log'
1138 | sh_log("size: " UINT64_FORMAT ", members: %u, filled: %f, total chain: %u, max chain: %u, avg chain: %f, total_collisions: %u, max_collisions: %u, avg_collisions: %f",
| ^~~~~~
In file included from /home/japin/postgres/build/../src/include/access/xlogrecord.h:14,
from /home/japin/postgres/build/../src/include/access/xlogreader.h:41,
from /home/japin/postgres/build/../src/include/access/xlog_internal.h:23,
from /home/japin/postgres/build/../src/common/controldata_utils.c:28:
/home/japin/postgres/build/../src/include/access/rmgr.h: In function 'RmgrIdIsCustom':
/home/japin/postgres/build/../src/include/access/rmgr.h:50:42: error: comparison of integer expressions of different signedness: 'int' and 'unsigned int' [-Werror=sign-compare]
50 | return rmid >= RM_MIN_CUSTOM_ID && rmid <= RM_MAX_CUSTOM_ID;
| ^~
/home/japin/postgres/build/../src/common/blkreftable.c: In function 'BlockRefTableReaderGetBlocks':
/home/japin/postgres/build/../src/common/blkreftable.c:716:22: error: comparison of integer expressions of different signedness: 'unsigned int' and 'int' [-Werror=sign-compare]
716 | blocks_found < nblocks)
| ^
/home/japin/postgres/build/../src/common/blkreftable.c:732:22: error: comparison of integer expressions of different signedness: 'unsigned int' and 'int' [-Werror=sign-compare]
732 | blocks_found < nblocks)
| ^
/home/japin/postgres/build/../src/common/blkreftable.c:742:20: error: comparison of integer expressions of different signedness: 'unsigned int' and 'int' [-Werror=sign-compare]
742 | if (blocks_found >= nblocks)
| ^~
cc1: all warnings being treated as errors
cc1: all warnings being treated as errors
make[2]https://sourceware.org/git/?p=glibc.git;a=blob;f=stdlib/stdint.h;h=bb3e8b5cc61fb3df8842225d2286de67e6f2ffe2;hb=refs/heads/master#l116: *** [../../src/Makefile.global:947: config_info.o] Error 1
make[2]https://sourceware.org/git/?p=glibc.git;a=blob;f=stdlib/stdint.h;h=bb3e8b5cc61fb3df8842225d2286de67e6f2ffe2;hb=refs/heads/master#l116: *** Waiting for unfinished jobs....
make[2]https://sourceware.org/git/?p=glibc.git;a=blob;f=stdlib/stdint.h;h=bb3e8b5cc61fb3df8842225d2286de67e6f2ffe2;hb=refs/heads/master#l116: *** [../../src/Makefile.global:947: controldata_utils.o] Error 1
In file included from /home/japin/postgres/build/../src/include/postgres_fe.h:25,
from /home/japin/postgres/build/../src/common/logging.c:15:
/home/japin/postgres/build/../src/common/logging.c: In function 'pg_log_generic_v':
/home/japin/postgres/build/../src/include/c.h:523:23: error: format '%llu' expects argument of type 'long long unsigned int', but argument 3 has type 'uint64' {aka 'long unsigned int'} [-Werror=format=]
523 | #define UINT64_FORMAT "%" INT64_MODIFIER "u"
| ^~~
/home/japin/postgres/build/../src/common/logging.c:259:21: note: in expansion of macro 'UINT64_FORMAT'
259 | fprintf(stderr, UINT64_FORMAT ":", lineno);
| ^~~~~~~~~~~~~
/home/japin/postgres/build/../src/include/c.h:523:43: note: format string is defined here
523 | #define UINT64_FORMAT "%" INT64_MODIFIER "u"
| ~~~~~~~~~~~~~~~~~~~^
| |
| long long unsigned int
/home/japin/postgres/build/../src/common/unicode_norm.c: In function 'recompose_code':
/home/japin/postgres/build/../src/common/unicode_norm.c:290:17: error: comparison of integer expressions of different signedness: 'int' and 'long unsigned int' [-Werror=sign-compare]
290 | for (i = 0; i < lengthof(UnicodeDecompMain); i++)
| ^
In file included from /home/japin/postgres/build/../src/include/c.h:834,
from /home/japin/postgres/build/../src/common/encnames.c:13:
/home/japin/postgres/build/../src/common/encnames.c: In function 'pg_encoding_to_char_private':
/home/japin/postgres/build/../src/common/encnames.c:593:19: error: comparison of integer expressions of different signedness: 'int' and 'pg_enc' [-Werror=sign-compare]
593 | Assert(encoding == p->encoding);
| ^~
/home/japin/postgres/build/../src/common/encnames.c:593:3: note: in expansion of macro 'Assert'
593 | Assert(encoding == p->encoding);
| ^~~~~~
/home/japin/postgres/build/../src/common/jsonapi.c: In function 'pg_parse_json_incremental':
/home/japin/postgres/build/../src/common/jsonapi.c:693:11: error: comparison of integer expressions of different signedness: 'char' and 'JsonTokenType' [-Werror=sign-compare]
693 | if (top == tok)
| ^~
cc1: all warnings being treated as errors
cc1: all warnings being treated as errors
make[2]https://sourceware.org/git/?p=glibc.git;a=blob;f=stdlib/stdint.h;h=bb3e8b5cc61fb3df8842225d2286de67e6f2ffe2;hb=refs/heads/master#l116: *** [../../src/Makefile.global:947: logging.o] Error 1
make[2]https://sourceware.org/git/?p=glibc.git;a=blob;f=stdlib/stdint.h;h=bb3e8b5cc61fb3df8842225d2286de67e6f2ffe2;hb=refs/heads/master#l116: *** [../../src/Makefile.global:947: blkreftable.o] Error 1
/home/japin/postgres/build/../src/common/kwlookup.c: In function 'ScanKeywordLookup':
/home/japin/postgres/build/../src/common/kwlookup.c:50:10: error: comparison of integer expressions of different signedness: 'size_t' {aka 'long unsigned int'} and 'int' [-Werror=sign-compare]
50 | if (len > keywords->max_kw_len)
| ^
cc1: all warnings being treated as errors
make[2]https://sourceware.org/git/?p=glibc.git;a=blob;f=stdlib/stdint.h;h=bb3e8b5cc61fb3df8842225d2286de67e6f2ffe2;hb=refs/heads/master#l116: *** [../../src/Makefile.global:947: encnames.o] Error 1
cc1: all warnings being treated as errors
cc1: all warnings being treated as errors
make[2]https://sourceware.org/git/?p=glibc.git;a=blob;f=stdlib/stdint.h;h=bb3e8b5cc61fb3df8842225d2286de67e6f2ffe2;hb=refs/heads/master#l116: *** [../../src/Makefile.global:947: kwlookup.o] Error 1
In file included from /home/japin/postgres/build/../src/include/c.h:834,
from /home/japin/postgres/build/../src/include/postgres_fe.h:25,
from /home/japin/postgres/build/../src/common/file_utils.c:19:
/home/japin/postgres/build/../src/common/file_utils.c: In function 'pg_pwrite_zeros':
/home/japin/postgres/build/../src/common/file_utils.c:725:23: error: comparison of integer expressions of different signedness: 'ssize_t' {aka 'long int'} and 'size_t' {aka 'long unsigned int'} [-Werror=sign-compare]
725 | Assert(total_written == size);
| ^~
/home/japin/postgres/build/../src/common/file_utils.c:725:2: note: in expansion of macro 'Assert'
725 | Assert(total_written == size);
| ^~~~~~
make[2]https://sourceware.org/git/?p=glibc.git;a=blob;f=stdlib/stdint.h;h=bb3e8b5cc61fb3df8842225d2286de67e6f2ffe2;hb=refs/heads/master#l116: *** [../../src/Makefile.global:947: unicode_norm.o] Error 1
cc1: all warnings being treated as errors
make[2]https://sourceware.org/git/?p=glibc.git;a=blob;f=stdlib/stdint.h;h=bb3e8b5cc61fb3df8842225d2286de67e6f2ffe2;hb=refs/heads/master#l116: *** [../../src/Makefile.global:947: file_utils.o] Error 1
/home/japin/postgres/build/../src/common/unicode_case.c: In function 'convert_case':
/home/japin/postgres/build/../src/common/unicode_case.c:155:31: error: comparison of integer expressions of different signedness: 'size_t' {aka 'long unsigned int'} and 'ssize_t' {aka 'long int'} [-Werror=sign-compare]
155 | while ((srclen < 0 || srcoff < srclen) && src[srcoff] != '\0')
| ^
/home/japin/postgres/build/../src/common/wchar.c: In function 'pg_utf8_verifystr':
/home/japin/postgres/build/../src/common/wchar.c:1868:10: error: comparison of integer expressions of different signedness: 'int' and 'long unsigned int' [-Werror=sign-compare]
1868 | if (len >= STRIDE_LENGTH)
| ^~
/home/japin/postgres/build/../src/common/wchar.c:1870:14: error: comparison of integer expressions of different signedness: 'int' and 'long unsigned int' [-Werror=sign-compare]
1870 | while (len >= STRIDE_LENGTH)
| ^~
cc1: all warnings being treated as errors
make[2]https://sourceware.org/git/?p=glibc.git;a=blob;f=stdlib/stdint.h;h=bb3e8b5cc61fb3df8842225d2286de67e6f2ffe2;hb=refs/heads/master#l116: *** [../../src/Makefile.global:947: unicode_case.o] Error 1
cc1: all warnings being treated as errors
make[2]https://sourceware.org/git/?p=glibc.git;a=blob;f=stdlib/stdint.h;h=bb3e8b5cc61fb3df8842225d2286de67e6f2ffe2;hb=refs/heads/master#l116: *** [../../src/Makefile.global:947: jsonapi.o] Error 1
cc1: all warnings being treated as errors
make[2]https://sourceware.org/git/?p=glibc.git;a=blob;f=stdlib/stdint.h;h=bb3e8b5cc61fb3df8842225d2286de67e6f2ffe2;hb=refs/heads/master#l116: *** [../../src/Makefile.global:947: wchar.o] Error 1
make[1]https://github.com/illumos/illumos-gate/blob/master/usr/src/uts/common/sys/int_limits.h#L92: *** [Makefile:42: all-common-recurse] Error 2
make: *** [GNUmakefile:11: all-src-recurse] Error 2

For rmid >= RM_MIN_CUSTOM_ID && rmid <= RM_MAX_CUSTOM_ID comparison error, I
found that UINT8_MAX is defined as '255U' on Illumos, however, Linux glibc
uses '255' for UINT8_MAX, which is signed.

[1]: https://github.com/illumos/illumos-gate/blob/master/usr/src/uts/common/sys/int_limits.h#L92
[2]: https://sourceware.org/git/?p=glibc.git;a=blob;f=stdlib/stdint.h;h=bb3e8b5cc61fb3df8842225d2286de67e6f2ffe2;hb=refs/heads/master#l116

--
Regards,
Japin Li

#19Peter Eisentraut
peter@eisentraut.org
In reply to: Thomas Munro (#17)
Re: Cannot find a working 64-bit integer type on Illumos

On 18.04.24 02:31, Thomas Munro wrote:

On Sat, Mar 23, 2024 at 3:23 PM Tom Lane <tgl@sss.pgh.pa.us> wrote:

Thomas Munro <thomas.munro@gmail.com> writes:

. o O ( int64_t, PRIdi64, etc were standardised a quarter of a century ago )

Yeah. Now that we require C99 it's probably reasonable to assume
that those things exist. I wouldn't be in favor of ripping out our
existing notations like UINT64CONST, because the code churn would be
substantial and the gain minimal. But we could imagine reimplementing
that stuff atop <stdint.h> and then getting rid of the configure-time
probes.

I played around with this a bit, but am not quite there yet.

Looks promising.

printf() is a little tricky. The standard wants us to use
<inttypes.h>'s PRId64 etc, but that might confuse our snprintf.c (in
theory, probably not in practice). "ll" should have the right size on
all systems, but gets warnings from the printf format string checker
on systems where "l" is the right type.

I'm not sure I understand the problem here. Do you mean that in theory
a platform's PRId64 could be something other than "l" or "ll"?

For limits, why do we have this:

- * stdint.h limits aren't guaranteed to have compatible types with our fixed
- * width types. So just define our own.

? I mean, how could they not have compatible types?

Maybe this means something like our int64 is long long int but the
system's int64_t is long int underneath, but I don't see how that would
matter for the limit macros.

I noticed that configure.ac checks if int64 (no "_t") might be defined
already by system header pollution, but meson.build doesn't. That's
an inconsistency that should be fixed, but which way? Hmm, commit
15abc7788e6 said that was done for BeOS, which we de-supported. So
maybe we should get rid of that?

I had a vague recollection that it was for AIX, but the commit indeed
mentions BeOS. Could be removed in either case.

#20Thomas Munro
thomas.munro@gmail.com
In reply to: Peter Eisentraut (#19)
2 attachment(s)
Re: Cannot find a working 64-bit integer type on Illumos

On Thu, Apr 18, 2024 at 8:47 PM Peter Eisentraut <peter@eisentraut.org> wrote:

I'm not sure I understand the problem here. Do you mean that in theory
a platform's PRId64 could be something other than "l" or "ll"?

Yes. I don't know why anyone would do that, and the systems I checked
all have the obvious definitions, eg "ld", "lld" etc. Perhaps it's an
acceptable risk? It certainly gives us a tidier result.

For discussion, here is a variant that fully embraces <inttypes.h> and
the PRI*64 macros.

Attachments:

v2-0001-Use-int64_t-support-from-stdint.h-and-inttypes.h.patchapplication/octet-stream; name=v2-0001-Use-int64_t-support-from-stdint.h-and-inttypes.h.patchDownload
From 0d25af2a59c6d4b9f6972ca02830713cf156b527 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Thu, 18 Apr 2024 07:53:10 +1200
Subject: [PATCH v2 1/2] Use int64_t support from <stdint.h> and <inttypes.h>.

Remove most of the configure probes for 64 bit integers.  Map our names
to the standard C99 names for types like int64_t, limits like INT64_MAX,
constant constructors like INT64_C().  Also use printf format strings
like PRId64 from <inttypes.h>.

There is a slight risk that some system will invent a definition of
PRId64 that our own snprintf.c doesn't understand (ie something other
than "ld" or "lld"), but that seems unlikely and we could easily deal
with it if a report arrives.  In practice, format strings made with
PRI*64 macros are expected to work on both the system printf-family and
our own in-tree snprintf.c.

We can get rid of pg_config_ext.h.

XXX WIP
---
 configure                                     | 230 ++----------------
 configure.ac                                  |  46 +---
 meson.build                                   |  35 +--
 src/Makefile.global.in                        |   6 -
 src/bin/pg_waldump/pg_waldump.c               |  16 +-
 src/bin/pgbench/pgbench.c                     |   4 +-
 src/include/.gitignore                        |   2 -
 src/include/Makefile                          |   8 +-
 src/include/c.h                               |  83 +++----
 src/include/meson.build                       |  10 -
 src/include/pg_config.h.in                    |  18 +-
 src/include/pg_config_ext.h.in                |   7 -
 src/include/pg_config_ext.h.meson             |   7 -
 src/include/port/pg_bitutils.h                |  18 +-
 src/include/postgres_ext.h                    |   7 +-
 src/include/utils/dsa.h                       |   2 +-
 src/interfaces/ecpg/ecpglib/typename.c        |   5 +-
 src/interfaces/ecpg/include/ecpg_config.h.in  |  12 -
 src/interfaces/ecpg/include/meson.build       |   3 -
 .../ecpg/include/pgtypes_interval.h           |  13 +-
 src/interfaces/ecpg/include/sqltypes.h        |   2 +-
 .../test/expected/compat_informix-sqlda.c     |   2 +-
 src/port/pg_bitutils.c                        |   7 +-
 src/port/snprintf.c                           |  14 +-
 .../modules/test_radixtree/test_radixtree.c   |   2 +-
 25 files changed, 102 insertions(+), 457 deletions(-)
 delete mode 100644 src/include/pg_config_ext.h.in
 delete mode 100644 src/include/pg_config_ext.h.meson

diff --git a/configure b/configure
index cfbd2a096f..52b5f666ce 100755
--- a/configure
+++ b/configure
@@ -16439,197 +16439,6 @@ fi
 # Run tests below here
 # --------------------
 
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether long int is 64 bits" >&5
-$as_echo_n "checking whether long int is 64 bits... " >&6; }
-if ${pgac_cv_type_long_int_64+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test "$cross_compiling" = yes; then :
-  # If cross-compiling, check the size reported by the compiler and
-# trust that the arithmetic works.
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-static int test_array [1 - 2 * !(sizeof(long int) == 8)];
-test_array [0] = 0;
-return test_array [0];
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  pgac_cv_type_long_int_64=yes
-else
-  pgac_cv_type_long_int_64=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-typedef long int ac_int64;
-
-/*
- * These are globals to discourage the compiler from folding all the
- * arithmetic tests down to compile-time constants.
- */
-ac_int64 a = 20000001;
-ac_int64 b = 40000005;
-
-int does_int64_work()
-{
-  ac_int64 c,d;
-
-  if (sizeof(ac_int64) != 8)
-    return 0;			/* definitely not the right size */
-
-  /* Do perfunctory checks to see if 64-bit arithmetic seems to work */
-  c = a * b;
-  d = (c + b) / b;
-  if (d != a+1)
-    return 0;
-  return 1;
-}
-
-int
-main() {
-  return (! does_int64_work());
-}
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
-  pgac_cv_type_long_int_64=yes
-else
-  pgac_cv_type_long_int_64=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
-  conftest.$ac_objext conftest.beam conftest.$ac_ext
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_type_long_int_64" >&5
-$as_echo "$pgac_cv_type_long_int_64" >&6; }
-
-HAVE_LONG_INT_64=$pgac_cv_type_long_int_64
-if test x"$pgac_cv_type_long_int_64" = xyes ; then
-
-$as_echo "#define HAVE_LONG_INT_64 1" >>confdefs.h
-
-fi
-
-
-if test x"$HAVE_LONG_INT_64" = x"yes" ; then
-  pg_int64_type="long int"
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether long long int is 64 bits" >&5
-$as_echo_n "checking whether long long int is 64 bits... " >&6; }
-if ${pgac_cv_type_long_long_int_64+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test "$cross_compiling" = yes; then :
-  # If cross-compiling, check the size reported by the compiler and
-# trust that the arithmetic works.
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-static int test_array [1 - 2 * !(sizeof(long long int) == 8)];
-test_array [0] = 0;
-return test_array [0];
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  pgac_cv_type_long_long_int_64=yes
-else
-  pgac_cv_type_long_long_int_64=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-typedef long long int ac_int64;
-
-/*
- * These are globals to discourage the compiler from folding all the
- * arithmetic tests down to compile-time constants.
- */
-ac_int64 a = 20000001;
-ac_int64 b = 40000005;
-
-int does_int64_work()
-{
-  ac_int64 c,d;
-
-  if (sizeof(ac_int64) != 8)
-    return 0;			/* definitely not the right size */
-
-  /* Do perfunctory checks to see if 64-bit arithmetic seems to work */
-  c = a * b;
-  d = (c + b) / b;
-  if (d != a+1)
-    return 0;
-  return 1;
-}
-
-int
-main() {
-  return (! does_int64_work());
-}
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
-  pgac_cv_type_long_long_int_64=yes
-else
-  pgac_cv_type_long_long_int_64=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
-  conftest.$ac_objext conftest.beam conftest.$ac_ext
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_type_long_long_int_64" >&5
-$as_echo "$pgac_cv_type_long_long_int_64" >&6; }
-
-HAVE_LONG_LONG_INT_64=$pgac_cv_type_long_long_int_64
-if test x"$pgac_cv_type_long_long_int_64" = xyes ; then
-
-$as_echo "#define HAVE_LONG_LONG_INT_64 1" >>confdefs.h
-
-fi
-
-  if test x"$HAVE_LONG_LONG_INT_64" = x"yes" ; then
-    pg_int64_type="long long int"
-  else
-    as_fn_error $? "Cannot find a working 64-bit integer type." "$LINENO" 5
-  fi
-fi
-
-
-cat >>confdefs.h <<_ACEOF
-#define PG_INT64_TYPE $pg_int64_type
-_ACEOF
-
-
-# Select the printf length modifier that goes with that, too.
-if test x"$pg_int64_type" = x"long long int" ; then
-  INT64_MODIFIER='"ll"'
-else
-  INT64_MODIFIER='"l"'
-fi
-
-
-cat >>confdefs.h <<_ACEOF
-#define INT64_MODIFIER $INT64_MODIFIER
-_ACEOF
-
-
 # has to be down here, rather than with the other builtins, because
 # the test uses PG_INT64_TYPE.
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_mul_overflow" >&5
@@ -16877,43 +16686,41 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
-if test x"$HAVE_LONG_LONG_INT_64" = x"yes" ; then
-  # The cast to long int works around a bug in the HP C Compiler,
+# The cast to long int works around a bug in the HP C Compiler,
 # see AC_CHECK_SIZEOF for more information.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking alignment of long long int" >&5
-$as_echo_n "checking alignment of long long int... " >&6; }
-if ${ac_cv_alignof_long_long_int+:} false; then :
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking alignment of int64_t" >&5
+$as_echo_n "checking alignment of int64_t... " >&6; }
+if ${ac_cv_alignof_int64_t+:} false; then :
   $as_echo_n "(cached) " >&6
 else
-  if ac_fn_c_compute_int "$LINENO" "(long int) offsetof (ac__type_alignof_, y)" "ac_cv_alignof_long_long_int"        "$ac_includes_default
+  if ac_fn_c_compute_int "$LINENO" "(long int) offsetof (ac__type_alignof_, y)" "ac_cv_alignof_int64_t"        "$ac_includes_default
 #ifndef offsetof
 # define offsetof(type, member) ((char *) &((type *) 0)->member - (char *) 0)
 #endif
-typedef struct { char x; long long int y; } ac__type_alignof_;"; then :
+typedef struct { char x; int64_t y; } ac__type_alignof_;"; then :
 
 else
-  if test "$ac_cv_type_long_long_int" = yes; then
+  if test "$ac_cv_type_int64_t" = yes; then
      { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error 77 "cannot compute alignment of long long int
+as_fn_error 77 "cannot compute alignment of int64_t
 See \`config.log' for more details" "$LINENO" 5; }
    else
-     ac_cv_alignof_long_long_int=0
+     ac_cv_alignof_int64_t=0
    fi
 fi
 
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_alignof_long_long_int" >&5
-$as_echo "$ac_cv_alignof_long_long_int" >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_alignof_int64_t" >&5
+$as_echo "$ac_cv_alignof_int64_t" >&6; }
 
 
 
 cat >>confdefs.h <<_ACEOF
-#define ALIGNOF_LONG_LONG_INT $ac_cv_alignof_long_long_int
+#define ALIGNOF_INT64_T $ac_cv_alignof_int64_t
 _ACEOF
 
 
-fi
 # The cast to long int works around a bug in the HP C Compiler,
 # see AC_CHECK_SIZEOF for more information.
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking alignment of double" >&5
@@ -16971,8 +16778,8 @@ MAX_ALIGNOF=$ac_cv_alignof_double
 if test $ac_cv_alignof_long -gt $MAX_ALIGNOF ; then
   as_fn_error $? "alignment of 'long' is greater than the alignment of 'double'" "$LINENO" 5
 fi
-if test x"$HAVE_LONG_LONG_INT_64" = xyes && test $ac_cv_alignof_long_long_int -gt $MAX_ALIGNOF ; then
-  as_fn_error $? "alignment of 'long long int' is greater than the alignment of 'double'" "$LINENO" 5
+if test $ac_cv_alignof_int64_t -gt $MAX_ALIGNOF ; then
+  as_fn_error $? "alignment of 'int64_t' is greater than the alignment of 'double'" "$LINENO" 5
 fi
 
 cat >>confdefs.h <<_ACEOF
@@ -16980,7 +16787,6 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
-
 # Some platforms predefine the types int8, int16, etc.  Only check
 # a (hopefully) representative subset.
 ac_fn_c_check_type "$LINENO" "int8" "ac_cv_type_int8" "#include <stdio.h>
@@ -19272,9 +19078,6 @@ fi
 ac_config_headers="$ac_config_headers src/include/pg_config.h"
 
 
-ac_config_headers="$ac_config_headers src/include/pg_config_ext.h"
-
-
 ac_config_headers="$ac_config_headers src/interfaces/ecpg/include/ecpg_config.h"
 
 
@@ -19989,7 +19792,6 @@ do
     "src/Makefile.port") CONFIG_LINKS="$CONFIG_LINKS src/Makefile.port:src/makefiles/Makefile.${template}" ;;
     "check_win32_symlinks") CONFIG_COMMANDS="$CONFIG_COMMANDS check_win32_symlinks" ;;
     "src/include/pg_config.h") CONFIG_HEADERS="$CONFIG_HEADERS src/include/pg_config.h" ;;
-    "src/include/pg_config_ext.h") CONFIG_HEADERS="$CONFIG_HEADERS src/include/pg_config_ext.h" ;;
     "src/interfaces/ecpg/include/ecpg_config.h") CONFIG_HEADERS="$CONFIG_HEADERS src/interfaces/ecpg/include/ecpg_config.h" ;;
 
   *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
@@ -20597,10 +20399,6 @@ $as_echo "$as_me: WARNING: *** link for $FILE -- please fix by hand" >&2;}
     "src/include/pg_config.h":H)
 # Update timestamp for pg_config.h (see Makefile.global)
 echo >src/include/stamp-h
- ;;
-    "src/include/pg_config_ext.h":H)
-# Update timestamp for pg_config_ext.h (see Makefile.global)
-echo >src/include/stamp-ext-h
  ;;
     "src/interfaces/ecpg/include/ecpg_config.h":H) echo >src/interfaces/ecpg/include/stamp-h ;;
 
diff --git a/configure.ac b/configure.ac
index 67e738d92b..1c4cd3ab72 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1945,37 +1945,6 @@ for the exact reason.]])],
 # Run tests below here
 # --------------------
 
-dnl Check to see if we have a working 64-bit integer type.
-dnl Since Postgres 8.4, we no longer support compilers without a working
-dnl 64-bit type; but we have to determine whether that type is called
-dnl "long int" or "long long int".
-
-PGAC_TYPE_64BIT_INT([long int])
-
-if test x"$HAVE_LONG_INT_64" = x"yes" ; then
-  pg_int64_type="long int"
-else
-  PGAC_TYPE_64BIT_INT([long long int])
-  if test x"$HAVE_LONG_LONG_INT_64" = x"yes" ; then
-    pg_int64_type="long long int"
-  else
-    AC_MSG_ERROR([Cannot find a working 64-bit integer type.])
-  fi
-fi
-
-AC_DEFINE_UNQUOTED(PG_INT64_TYPE, $pg_int64_type,
-  [Define to the name of a signed 64-bit integer type.])
-
-# Select the printf length modifier that goes with that, too.
-if test x"$pg_int64_type" = x"long long int" ; then
-  INT64_MODIFIER='"ll"'
-else
-  INT64_MODIFIER='"l"'
-fi
-
-AC_DEFINE_UNQUOTED(INT64_MODIFIER, $INT64_MODIFIER,
-                   [Define to the appropriate printf length modifier for 64-bit ints.])
-
 # has to be down here, rather than with the other builtins, because
 # the test uses PG_INT64_TYPE.
 PGAC_C_BUILTIN_OP_OVERFLOW
@@ -1990,9 +1959,7 @@ AC_CHECK_SIZEOF([long])
 AC_CHECK_ALIGNOF(short)
 AC_CHECK_ALIGNOF(int)
 AC_CHECK_ALIGNOF(long)
-if test x"$HAVE_LONG_LONG_INT_64" = x"yes" ; then
-  AC_CHECK_ALIGNOF(long long int)
-fi
+AC_CHECK_ALIGNOF(int64_t)
 AC_CHECK_ALIGNOF(double)
 
 # Compute maximum alignment of any basic type.
@@ -2016,12 +1983,11 @@ MAX_ALIGNOF=$ac_cv_alignof_double
 if test $ac_cv_alignof_long -gt $MAX_ALIGNOF ; then
   AC_MSG_ERROR([alignment of 'long' is greater than the alignment of 'double'])
 fi
-if test x"$HAVE_LONG_LONG_INT_64" = xyes && test $ac_cv_alignof_long_long_int -gt $MAX_ALIGNOF ; then
-  AC_MSG_ERROR([alignment of 'long long int' is greater than the alignment of 'double'])
+if test $ac_cv_alignof_int64_t -gt $MAX_ALIGNOF ; then
+  AC_MSG_ERROR([alignment of 'int64_t' is greater than the alignment of 'double'])
 fi
 AC_DEFINE_UNQUOTED(MAXIMUM_ALIGNOF, $MAX_ALIGNOF, [Define as the maximum alignment requirement of any C data type.])
 
-
 # Some platforms predefine the types int8, int16, etc.  Only check
 # a (hopefully) representative subset.
 AC_CHECK_TYPES([int8, uint8, int64, uint64], [], [],
@@ -2520,12 +2486,6 @@ AC_CONFIG_HEADERS([src/include/pg_config.h],
 echo >src/include/stamp-h
 ])
 
-AC_CONFIG_HEADERS([src/include/pg_config_ext.h],
-[
-# Update timestamp for pg_config_ext.h (see Makefile.global)
-echo >src/include/stamp-ext-h
-])
-
 AC_CONFIG_HEADERS([src/interfaces/ecpg/include/ecpg_config.h],
                   [echo >src/interfaces/ecpg/include/stamp-h])
 
diff --git a/meson.build b/meson.build
index cdfd31377d..96e5edc53f 100644
--- a/meson.build
+++ b/meson.build
@@ -1488,18 +1488,6 @@ endif
 
 sizeof_long = cc.sizeof('long', args: test_c_args)
 cdata.set('SIZEOF_LONG', sizeof_long)
-if sizeof_long == 8
-  cdata.set('HAVE_LONG_INT_64', 1)
-  pg_int64_type = 'long int'
-  cdata.set_quoted('INT64_MODIFIER', 'l')
-elif sizeof_long == 4 and cc.sizeof('long long', args: test_c_args) == 8
-  cdata.set('HAVE_LONG_LONG_INT_64', 1)
-  pg_int64_type = 'long long int'
-  cdata.set_quoted('INT64_MODIFIER', 'll')
-else
-  error('do not know how to get a 64bit int')
-endif
-cdata.set('PG_INT64_TYPE', pg_int64_type)
 
 if host_machine.endian() == 'big'
   cdata.set('WORDS_BIGENDIAN', 1)
@@ -1529,8 +1517,8 @@ endforeach
 # any types wider than 64 bits, as allowing MAXIMUM_ALIGNOF to exceed 8
 # would be too much of a penalty for disk and memory space.
 alignof_double = cdata.get('ALIGNOF_DOUBLE')
-if cc.alignment(pg_int64_type, args: test_c_args) > alignof_double
-  error('alignment of int64 is greater than the alignment of double')
+if cc.alignment('int64_t', args: test_c_args, prefix: '#include <stdint.h>') > alignof_double
+  error('alignment of int64_t is greater than the alignment of double')
 endif
 cdata.set('MAXIMUM_ALIGNOF', alignof_double)
 
@@ -1742,17 +1730,17 @@ endif
 # compile, and store the results in global variables so the compiler doesn't
 # optimize away the call.
 if cc.links('''
-    INT64 a = 1;
-    INT64 b = 1;
-    INT64 result;
+    #include <stdint.h>
+    int64_t a = 1;
+    int64_t b = 1;
+    int64_t result;
 
     int main(void)
     {
         return __builtin_mul_overflow(a, b, &result);
     }''',
     name: '__builtin_mul_overflow',
-    args: test_c_args + ['-DINT64=@0@'.format(cdata.get('PG_INT64_TYPE'))],
-    )
+    args: test_c_args)
   cdata.set('HAVE__BUILTIN_OP_OVERFLOW', 1)
 endif
 
@@ -2013,7 +2001,7 @@ int main(void)
     cdata.set(check['name'],
       cc.links(test,
         name: check['desc'],
-        args: test_c_args + ['-DINT64=@0@'.format(cdata.get('PG_INT64_TYPE'))]) ? 1 : false
+        args: test_c_args) ? 1 : false
     )
   endforeach
 
@@ -2057,11 +2045,12 @@ if host_cpu == 'x86_64'
 
   prog = '''
 #include <immintrin.h>
+#include <stdint.h>
 
 int main(void)
 {
     const char buf[sizeof(__m512i)];
-    INT64 popcnt = 0;
+    int64_t popcnt = 0;
     __m512i accum = _mm512_setzero_si512();
     const __m512i val = _mm512_maskz_loadu_epi8((__mmask64) 0xf0f0f0f0f0f0f0f0, (const __m512i *) buf);
     const __m512i cnt = _mm512_popcnt_epi64(val);
@@ -2073,10 +2062,10 @@ int main(void)
 '''
 
   if cc.links(prog, name: 'AVX-512 popcount without -mavx512vpopcntdq -mavx512bw',
-        args: test_c_args + ['-DINT64=@0@'.format(cdata.get('PG_INT64_TYPE'))])
+        args: test_c_args)
     cdata.set('USE_AVX512_POPCNT_WITH_RUNTIME_CHECK', 1)
   elif cc.links(prog, name: 'AVX-512 popcount with -mavx512vpopcntdq -mavx512bw',
-        args: test_c_args + ['-DINT64=@0@'.format(cdata.get('PG_INT64_TYPE'))] + ['-mavx512vpopcntdq'] + ['-mavx512bw'])
+        args: test_c_args + ['-mavx512vpopcntdq'] + ['-mavx512bw'])
     cdata.set('USE_AVX512_POPCNT_WITH_RUNTIME_CHECK', 1)
     cflags_popcnt += ['-mavx512vpopcntdq'] + ['-mavx512bw']
   endif
diff --git a/src/Makefile.global.in b/src/Makefile.global.in
index 36d880d225..1928fc2f2c 100644
--- a/src/Makefile.global.in
+++ b/src/Makefile.global.in
@@ -833,12 +833,6 @@ $(top_builddir)/src/include/pg_config.h: $(top_builddir)/src/include/stamp-h ;
 $(top_builddir)/src/include/stamp-h: $(top_srcdir)/src/include/pg_config.h.in $(top_builddir)/config.status
 	cd $(top_builddir) && ./config.status src/include/pg_config.h
 
-# Also remake pg_config_ext.h from pg_config_ext.h.in, same logic as above.
-$(top_builddir)/src/include/pg_config_ext.h: $(top_builddir)/src/include/stamp-ext-h ;
-
-$(top_builddir)/src/include/stamp-ext-h: $(top_srcdir)/src/include/pg_config_ext.h.in $(top_builddir)/config.status
-	cd $(top_builddir) && ./config.status src/include/pg_config_ext.h
-
 # Also remake ecpg_config.h from ecpg_config.h.in if the latter changed, same
 # logic as above.
 $(top_builddir)/src/interfaces/ecpg/include/ecpg_config.h: $(top_builddir)/src/interfaces/ecpg/include/stamp-h ;
diff --git a/src/bin/pg_waldump/pg_waldump.c b/src/bin/pg_waldump/pg_waldump.c
index 1f9403fc5c..c4b04d6296 100644
--- a/src/bin/pg_waldump/pg_waldump.c
+++ b/src/bin/pg_waldump/pg_waldump.c
@@ -610,10 +610,10 @@ XLogDumpStatsRow(const char *name,
 		tot_len_pct = 100 * (double) tot_len / total_len;
 
 	printf("%-27s "
-		   "%20" INT64_MODIFIER "u (%6.02f) "
-		   "%20" INT64_MODIFIER "u (%6.02f) "
-		   "%20" INT64_MODIFIER "u (%6.02f) "
-		   "%20" INT64_MODIFIER "u (%6.02f)\n",
+		   "%20" PRIu64 " (%6.02f) "
+		   "%20" PRIu64 " (%6.02f) "
+		   "%20" PRIu64 " (%6.02f) "
+		   "%20" PRIu64 " (%6.02f)\n",
 		   name, n, n_pct, rec_len, rec_len_pct, fpi_len, fpi_len_pct,
 		   tot_len, tot_len_pct);
 }
@@ -742,10 +742,10 @@ XLogDumpDisplayStats(XLogDumpConfig *config, XLogStats *stats)
 		fpi_len_pct = 100 * (double) total_fpi_len / total_len;
 
 	printf("%-27s "
-		   "%20" INT64_MODIFIER "u %-9s"
-		   "%20" INT64_MODIFIER "u %-9s"
-		   "%20" INT64_MODIFIER "u %-9s"
-		   "%20" INT64_MODIFIER "u %-6s\n",
+		   "%20" PRIu64 " %-9s"
+		   "%20" PRIu64 " %-9s"
+		   "%20" PRIu64 " %-9s"
+		   "%20" PRIu64 " %-6s\n",
 		   "Total", stats->count, "",
 		   total_rec_len, psprintf("[%.02f%%]", rec_len_pct),
 		   total_fpi_len, psprintf("[%.02f%%]", fpi_len_pct),
diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c
index af776b31d8..088c5fa0c7 100644
--- a/src/bin/pgbench/pgbench.c
+++ b/src/bin/pgbench/pgbench.c
@@ -6545,13 +6545,13 @@ printResults(StatsData *total,
 					SimpleStats *cstats = &(*commands)->stats;
 
 					if (max_tries == 1)
-						printf("   %11.3f  %10" INT64_MODIFIER "d  %s\n",
+						printf("   %11.3f  %10" PRId64 " %s\n",
 							   (cstats->count > 0) ?
 							   1000.0 * cstats->sum / cstats->count : 0.0,
 							   (*commands)->failures,
 							   (*commands)->first_line);
 					else
-						printf("   %11.3f  %10" INT64_MODIFIER "d  %10" INT64_MODIFIER "d  %s\n",
+						printf("   %11.3f  %10" PRId64 " %10" PRId64 " %s\n",
 							   (cstats->count > 0) ?
 							   1000.0 * cstats->sum / cstats->count : 0.0,
 							   (*commands)->failures,
diff --git a/src/include/.gitignore b/src/include/.gitignore
index 51819fb4dd..6e99e82fe0 100644
--- a/src/include/.gitignore
+++ b/src/include/.gitignore
@@ -1,5 +1,3 @@
 /stamp-h
-/stamp-ext-h
 /pg_config.h
-/pg_config_ext.h
 /pg_config_os.h
diff --git a/src/include/Makefile b/src/include/Makefile
index b8b576a4de..26332ff9cb 100644
--- a/src/include/Makefile
+++ b/src/include/Makefile
@@ -13,7 +13,7 @@ top_builddir = ../..
 include $(top_builddir)/src/Makefile.global
 
 
-all: pg_config.h pg_config_ext.h pg_config_os.h
+all: pg_config.h pg_config_os.h
 
 
 # Subdirectories containing installable headers
@@ -32,7 +32,6 @@ install: all installdirs
 	$(INSTALL_DATA) $(srcdir)/postgres_ext.h   '$(DESTDIR)$(includedir)'
 	$(INSTALL_DATA) $(srcdir)/libpq/libpq-fs.h '$(DESTDIR)$(includedir)/libpq'
 	$(INSTALL_DATA) pg_config.h     '$(DESTDIR)$(includedir)'
-	$(INSTALL_DATA) pg_config_ext.h '$(DESTDIR)$(includedir)'
 	$(INSTALL_DATA) pg_config_os.h  '$(DESTDIR)$(includedir)'
 	$(INSTALL_DATA) $(srcdir)/pg_config_manual.h '$(DESTDIR)$(includedir)'
 # These headers are needed by the not-so-public headers of the interfaces.
@@ -43,7 +42,6 @@ install: all installdirs
 	$(INSTALL_DATA) $(srcdir)/libpq/protocol.h '$(DESTDIR)$(includedir_internal)/libpq'
 # These headers are needed for server-side development
 	$(INSTALL_DATA) pg_config.h     '$(DESTDIR)$(includedir_server)'
-	$(INSTALL_DATA) pg_config_ext.h '$(DESTDIR)$(includedir_server)'
 	$(INSTALL_DATA) pg_config_os.h  '$(DESTDIR)$(includedir_server)'
 	$(INSTALL_DATA) nodes/nodetags.h '$(DESTDIR)$(includedir_server)/nodes'
 	$(INSTALL_DATA) utils/errcodes.h '$(DESTDIR)$(includedir_server)/utils'
@@ -66,7 +64,7 @@ installdirs:
 
 
 uninstall:
-	rm -f $(addprefix '$(DESTDIR)$(includedir)'/, pg_config.h pg_config_ext.h pg_config_os.h pg_config_manual.h postgres_ext.h libpq/libpq-fs.h)
+	rm -f $(addprefix '$(DESTDIR)$(includedir)'/, pg_config.h pg_config_os.h pg_config_manual.h postgres_ext.h libpq/libpq-fs.h)
 	rm -f $(addprefix '$(DESTDIR)$(includedir_internal)'/, c.h port.h postgres_fe.h libpq/pqcomm.h libpq/protocol.h)
 # heuristic...
 	rm -rf $(addprefix '$(DESTDIR)$(includedir_server)'/, $(SUBDIRS) *.h)
@@ -80,4 +78,4 @@ clean:
 	$(MAKE) -C catalog clean
 
 distclean: clean
-	rm -f pg_config.h pg_config_ext.h pg_config_os.h stamp-h stamp-ext-h
+	rm -f pg_config.h pg_config_os.h stamp-h stamp-ext-h
diff --git a/src/include/c.h b/src/include/c.h
index dc1841346c..fd876c32af 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -48,14 +48,12 @@
 
 #include "postgres_ext.h"
 
-/* Must undef pg_config_ext.h symbols before including pg_config.h */
-#undef PG_INT64_TYPE
-
 #include "pg_config.h"
 #include "pg_config_manual.h"	/* must be after pg_config.h */
 #include "pg_config_os.h"		/* must be before any system header files */
 
 /* System header files that should be available everywhere in Postgres */
+#include <inttypes.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -489,10 +487,13 @@ typedef char *Pointer;
  *		frontend/backend protocol.
  */
 #ifndef HAVE_INT8
-typedef signed char int8;		/* == 8 bits */
-typedef signed short int16;		/* == 16 bits */
-typedef signed int int32;		/* == 32 bits */
+typedef int8_t int8;			/* == 8 bits */
+typedef int16_t int16;			/* == 16 bits */
+typedef int32_t int32;			/* == 32 bits */
 #endif							/* not HAVE_INT8 */
+#ifndef HAVE_INT64
+typedef int64_t int64;			/* == 64 bits */
+#endif							/* not HAVE_INT64 */
 
 /*
  * uintN
@@ -501,10 +502,13 @@ typedef signed int int32;		/* == 32 bits */
  *		frontend/backend protocol.
  */
 #ifndef HAVE_UINT8
-typedef unsigned char uint8;	/* == 8 bits */
-typedef unsigned short uint16;	/* == 16 bits */
-typedef unsigned int uint32;	/* == 32 bits */
+typedef uint8_t uint8;			/* == 8 bits */
+typedef uint16_t uint16;		/* == 16 bits */
+typedef uint32_t uint32;		/* == 32 bits */
 #endif							/* not HAVE_UINT8 */
+#ifndef HAVE_UINT64
+typedef uint64_t uint64;		/* == 64 bits */
+#endif							/* not HAVE_UINT64 */
 
 /*
  * bitsN
@@ -517,36 +521,12 @@ typedef uint32 bits32;			/* >= 32 bits */
 /*
  * 64-bit integers
  */
-#ifdef HAVE_LONG_INT_64
-/* Plain "long int" fits, use it */
-
-#ifndef HAVE_INT64
-typedef long int int64;
-#endif
-#ifndef HAVE_UINT64
-typedef unsigned long int uint64;
-#endif
-#define INT64CONST(x)  (x##L)
-#define UINT64CONST(x) (x##UL)
-#elif defined(HAVE_LONG_LONG_INT_64)
-/* We have working support for "long long int", use that */
-
-#ifndef HAVE_INT64
-typedef long long int int64;
-#endif
-#ifndef HAVE_UINT64
-typedef unsigned long long int uint64;
-#endif
-#define INT64CONST(x)  (x##LL)
-#define UINT64CONST(x) (x##ULL)
-#else
-/* neither HAVE_LONG_INT_64 nor HAVE_LONG_LONG_INT_64 */
-#error must have a working 64-bit integer datatype
-#endif
+#define INT64CONST(x)  INT64_C(x)
+#define UINT64CONST(x) UINT64_C(x)
 
 /* snprintf format strings to use for 64-bit integers */
-#define INT64_FORMAT "%" INT64_MODIFIER "d"
-#define UINT64_FORMAT "%" INT64_MODIFIER "u"
+#define INT64_FORMAT "%" PRId64
+#define UINT64_FORMAT "%" PRIu64
 
 /*
  * 128-bit signed and unsigned integers
@@ -575,22 +555,19 @@ typedef unsigned PG_INT128_TYPE uint128
 #endif
 #endif
 
-/*
- * stdint.h limits aren't guaranteed to have compatible types with our fixed
- * width types. So just define our own.
- */
-#define PG_INT8_MIN		(-0x7F-1)
-#define PG_INT8_MAX		(0x7F)
-#define PG_UINT8_MAX	(0xFF)
-#define PG_INT16_MIN	(-0x7FFF-1)
-#define PG_INT16_MAX	(0x7FFF)
-#define PG_UINT16_MAX	(0xFFFF)
-#define PG_INT32_MIN	(-0x7FFFFFFF-1)
-#define PG_INT32_MAX	(0x7FFFFFFF)
-#define PG_UINT32_MAX	(0xFFFFFFFFU)
-#define PG_INT64_MIN	(-INT64CONST(0x7FFFFFFFFFFFFFFF) - 1)
-#define PG_INT64_MAX	INT64CONST(0x7FFFFFFFFFFFFFFF)
-#define PG_UINT64_MAX	UINT64CONST(0xFFFFFFFFFFFFFFFF)
+/* Historical names for limits in stdint.h. */
+#define PG_INT8_MIN		INT8_MIN
+#define PG_INT8_MAX		INT8_MAX
+#define PG_UINT8_MAX	UINT8_MAX
+#define PG_INT16_MIN	INT16_MIN
+#define PG_INT16_MAX	INT16_MAX
+#define PG_UINT16_MAX	UINT16_MAX
+#define PG_INT32_MIN	INT32_MIN
+#define PG_INT32_MAX	INT32_MAX
+#define PG_UINT32_MAX	UINT32_MAX
+#define PG_INT64_MIN	INT64_MIN
+#define PG_INT64_MAX	INT64_MAX
+#define PG_UINT64_MAX	UINT64_MAX
 
 /*
  * We now always use int64 timestamps, but keep this symbol defined for the
diff --git a/src/include/meson.build b/src/include/meson.build
index a28f115d86..6b9116341f 100644
--- a/src/include/meson.build
+++ b/src/include/meson.build
@@ -1,14 +1,5 @@
 # Copyright (c) 2022-2024, PostgreSQL Global Development Group
 
-pg_config_ext = configure_file(
-  input: 'pg_config_ext.h.meson',
-  output: 'pg_config_ext.h',
-  configuration: cdata,
-  install: true,
-  install_dir: dir_include,
-)
-configure_files += pg_config_ext
-
 pg_config_os = configure_file(
   output: 'pg_config_os.h',
   input: files('port/@0@.h'.format(portname)),
@@ -116,7 +107,6 @@ install_headers(
   'postgres_fe.h',
   'varatt.h',
   'windowapi.h',
-  pg_config_ext,
   pg_config_os,
   pg_config,
   install_dir: dir_include_server,
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index f8d3e3b6b8..2791ec5fab 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -9,12 +9,12 @@
 /* The normal alignment of `int', in bytes. */
 #undef ALIGNOF_INT
 
+/* The normal alignment of `int64_t', in bytes. */
+#undef ALIGNOF_INT64_T
+
 /* The normal alignment of `long', in bytes. */
 #undef ALIGNOF_LONG
 
-/* The normal alignment of `long long int', in bytes. */
-#undef ALIGNOF_LONG_LONG_INT
-
 /* The normal alignment of `PG_INT128_TYPE', in bytes. */
 #undef ALIGNOF_PG_INT128_TYPE
 
@@ -282,12 +282,6 @@
 /* Define to 1 if you have the `zstd' library (-lzstd). */
 #undef HAVE_LIBZSTD
 
-/* Define to 1 if `long int' works and is 64 bits. */
-#undef HAVE_LONG_INT_64
-
-/* Define to 1 if `long long int' works and is 64 bits. */
-#undef HAVE_LONG_LONG_INT_64
-
 /* Define to 1 if you have the <mbarrier.h> header file. */
 #undef HAVE_MBARRIER_H
 
@@ -570,9 +564,6 @@
 /* Define to 1 if your compiler understands _Static_assert. */
 #undef HAVE__STATIC_ASSERT
 
-/* Define to the appropriate printf length modifier for 64-bit ints. */
-#undef INT64_MODIFIER
-
 /* Define to 1 if `locale_t' requires <xlocale.h>. */
 #undef LOCALE_T_IN_XLOCALE
 
@@ -607,9 +598,6 @@
 /* Define to the name of a signed 128-bit integer type. */
 #undef PG_INT128_TYPE
 
-/* Define to the name of a signed 64-bit integer type. */
-#undef PG_INT64_TYPE
-
 /* Define to the name of the default PostgreSQL service principal in Kerberos
    (GSSAPI). (--with-krb-srvnam=NAME) */
 #undef PG_KRB_SRVNAM
diff --git a/src/include/pg_config_ext.h.in b/src/include/pg_config_ext.h.in
deleted file mode 100644
index 8acadbdafd..0000000000
--- a/src/include/pg_config_ext.h.in
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
- * src/include/pg_config_ext.h.in.  This is generated manually, not by
- * autoheader, since we want to limit which symbols get defined here.
- */
-
-/* Define to the name of a signed 64-bit integer type. */
-#undef PG_INT64_TYPE
diff --git a/src/include/pg_config_ext.h.meson b/src/include/pg_config_ext.h.meson
deleted file mode 100644
index 57cdfca0cf..0000000000
--- a/src/include/pg_config_ext.h.meson
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
- * src/include/pg_config_ext.h.in.  This is generated manually, not by
- * autoheader, since we want to limit which symbols get defined here.
- */
-
-/* Define to the name of a signed 64-bit integer type. */
-#mesondefine PG_INT64_TYPE
diff --git a/src/include/port/pg_bitutils.h b/src/include/port/pg_bitutils.h
index 4d88478c9c..1c09bf0ff2 100644
--- a/src/include/port/pg_bitutils.h
+++ b/src/include/port/pg_bitutils.h
@@ -74,13 +74,12 @@ pg_leftmost_one_pos64(uint64 word)
 #ifdef HAVE__BUILTIN_CLZ
 	Assert(word != 0);
 
-#if defined(HAVE_LONG_INT_64)
+#if SIZEOF_LONG == 8
 	return 63 - __builtin_clzl(word);
-#elif defined(HAVE_LONG_LONG_INT_64)
-	return 63 - __builtin_clzll(word);
 #else
-#error must have a working 64-bit integer datatype
-#endif							/* HAVE_LONG_INT_64 */
+	StaticAssertStmt(sizeof(word) == sizeof(long long), "unexpected size");
+	return 63 - __builtin_clzll(word);
+#endif
 
 #elif defined(_MSC_VER) && (defined(_M_AMD64) || defined(_M_ARM64))
 	unsigned long result;
@@ -147,13 +146,12 @@ pg_rightmost_one_pos64(uint64 word)
 #ifdef HAVE__BUILTIN_CTZ
 	Assert(word != 0);
 
-#if defined(HAVE_LONG_INT_64)
+#if SIZEOF_LONG == 8
 	return __builtin_ctzl(word);
-#elif defined(HAVE_LONG_LONG_INT_64)
-	return __builtin_ctzll(word);
 #else
-#error must have a working 64-bit integer datatype
-#endif							/* HAVE_LONG_INT_64 */
+	StaticAssertStmt(sizeof(word) == sizeof(long long), "unexpected size");
+	return __builtin_ctzll(word);
+#endif
 
 #elif defined(_MSC_VER) && (defined(_M_AMD64) || defined(_M_ARM64))
 	unsigned long result;
diff --git a/src/include/postgres_ext.h b/src/include/postgres_ext.h
index 240ad4e93b..034056e7d9 100644
--- a/src/include/postgres_ext.h
+++ b/src/include/postgres_ext.h
@@ -23,7 +23,7 @@
 #ifndef POSTGRES_EXT_H
 #define POSTGRES_EXT_H
 
-#include "pg_config_ext.h"
+#include <stdint.h>
 
 /*
  * Object ID is a fundamental type in Postgres.
@@ -36,15 +36,14 @@ typedef unsigned int Oid;
 #define InvalidOid		((Oid) 0)
 #endif
 
-#define OID_MAX  UINT_MAX
-/* you will need to include <limits.h> to use the above #define */
+#define OID_MAX  UINT32_MAX
 
 #define atooid(x) ((Oid) strtoul((x), NULL, 10))
 /* the above needs <stdlib.h> */
 
 
 /* Define a signed 64-bit integer type for use in client API declarations. */
-typedef PG_INT64_TYPE pg_int64;
+typedef int64_t pg_int64;
 
 /*
  * Identifiers of error message fields.  Kept here to keep common
diff --git a/src/include/utils/dsa.h b/src/include/utils/dsa.h
index 8dff964bf3..6c952a43f7 100644
--- a/src/include/utils/dsa.h
+++ b/src/include/utils/dsa.h
@@ -66,7 +66,7 @@ typedef pg_atomic_uint64 dsa_pointer_atomic;
 #define dsa_pointer_atomic_write pg_atomic_write_u64
 #define dsa_pointer_atomic_fetch_add pg_atomic_fetch_add_u64
 #define dsa_pointer_atomic_compare_exchange pg_atomic_compare_exchange_u64
-#define DSA_POINTER_FORMAT "%016" INT64_MODIFIER "x"
+#define DSA_POINTER_FORMAT "%016" PRIx64
 #endif
 
 /* Flags for dsa_allocate_extended. */
diff --git a/src/interfaces/ecpg/ecpglib/typename.c b/src/interfaces/ecpg/ecpglib/typename.c
index 1d482c4fa6..1ab2cda848 100644
--- a/src/interfaces/ecpg/ecpglib/typename.c
+++ b/src/interfaces/ecpg/ecpglib/typename.c
@@ -131,10 +131,9 @@ sqlda_dynamic_type(Oid type, enum COMPAT_MODE compat)
 		case INTERVALOID:
 			return ECPGt_interval;
 		case INT8OID:
-#ifdef HAVE_LONG_LONG_INT_64
+#if SIZEOF_LONG < 8
 			return ECPGt_long_long;
-#endif
-#ifdef HAVE_LONG_INT_64
+#else
 			return ECPGt_long;
 #endif
 			/* Unhandled types always return a string */
diff --git a/src/interfaces/ecpg/include/ecpg_config.h.in b/src/interfaces/ecpg/include/ecpg_config.h.in
index 5d0f448a86..48bce0878a 100644
--- a/src/interfaces/ecpg/include/ecpg_config.h.in
+++ b/src/interfaces/ecpg/include/ecpg_config.h.in
@@ -1,17 +1,5 @@
 /* Define to 1 to build client libraries as thread-safe code. */
 #define ENABLE_THREAD_SAFETY 1
 
-/* Define to 1 if the system has the type `int64'. */
-#undef HAVE_INT64
-
-/* Define to 1 if `long int' works and is 64 bits. */
-#undef HAVE_LONG_INT_64
-
-/* Define to 1 if the system has the type `long long int'. */
-#define HAVE_LONG_LONG_INT 1
-
-/* Define to 1 if `long long int' works and is 64 bits. */
-#undef HAVE_LONG_LONG_INT_64
-
 /* Define to 1 to use <stdbool.h> to define type bool. */
 #undef PG_USE_STDBOOL
diff --git a/src/interfaces/ecpg/include/meson.build b/src/interfaces/ecpg/include/meson.build
index 31610fef58..d0234413fc 100644
--- a/src/interfaces/ecpg/include/meson.build
+++ b/src/interfaces/ecpg/include/meson.build
@@ -3,9 +3,6 @@
 ecpg_inc = include_directories('.')
 
 ecpg_conf_keys = [
-  'HAVE_INT64',
-  'HAVE_LONG_INT_64',
-  'HAVE_LONG_LONG_INT_64',
   'PG_USE_STDBOOL',
 ]
 
diff --git a/src/interfaces/ecpg/include/pgtypes_interval.h b/src/interfaces/ecpg/include/pgtypes_interval.h
index 2809b356f7..d16f74970c 100644
--- a/src/interfaces/ecpg/include/pgtypes_interval.h
+++ b/src/interfaces/ecpg/include/pgtypes_interval.h
@@ -8,18 +8,7 @@
 
 #ifndef C_H
 
-#ifdef HAVE_LONG_INT_64
-#ifndef HAVE_INT64
-typedef long int int64;
-#endif
-#elif defined(HAVE_LONG_LONG_INT_64)
-#ifndef HAVE_INT64
-typedef long long int int64;
-#endif
-#else
-/* neither HAVE_LONG_INT_64 nor HAVE_LONG_LONG_INT_64 */
-#error must have a working 64-bit integer datatype
-#endif
+typedef int64_t int64;
 
 #define HAVE_INT64_TIMESTAMP
 #endif							/* C_H */
diff --git a/src/interfaces/ecpg/include/sqltypes.h b/src/interfaces/ecpg/include/sqltypes.h
index e7cbfa4795..aed055eb4a 100644
--- a/src/interfaces/ecpg/include/sqltypes.h
+++ b/src/interfaces/ecpg/include/sqltypes.h
@@ -46,7 +46,7 @@
 #define SQLINTERVAL		ECPGt_interval
 #define SQLNCHAR	ECPGt_char
 #define SQLNVCHAR	ECPGt_char
-#ifdef HAVE_LONG_LONG_INT_64
+#if SIZEOF_LONG < 8
 #define SQLINT8		ECPGt_long_long
 #define SQLSERIAL8	ECPGt_long_long
 #else
diff --git a/src/interfaces/ecpg/test/expected/compat_informix-sqlda.c b/src/interfaces/ecpg/test/expected/compat_informix-sqlda.c
index 7e19319d27..02ec7b668d 100644
--- a/src/interfaces/ecpg/test/expected/compat_informix-sqlda.c
+++ b/src/interfaces/ecpg/test/expected/compat_informix-sqlda.c
@@ -97,7 +97,7 @@ typedef struct sqlda_struct sqlda_t;
 #define SQLINTERVAL		ECPGt_interval
 #define SQLNCHAR	ECPGt_char
 #define SQLNVCHAR	ECPGt_char
-#ifdef HAVE_LONG_LONG_INT_64
+#if SIZEOF_LONG < 8
 #define SQLINT8		ECPGt_long_long
 #define SQLSERIAL8	ECPGt_long_long
 #else
diff --git a/src/port/pg_bitutils.c b/src/port/pg_bitutils.c
index 87f56e82b8..d4413a299a 100644
--- a/src/port/pg_bitutils.c
+++ b/src/port/pg_bitutils.c
@@ -370,12 +370,11 @@ static inline int
 pg_popcount64_slow(uint64 word)
 {
 #ifdef HAVE__BUILTIN_POPCOUNT
-#if defined(HAVE_LONG_INT_64)
+#if SIZEOF_LONG == 8
 	return __builtin_popcountl(word);
-#elif defined(HAVE_LONG_LONG_INT_64)
-	return __builtin_popcountll(word);
 #else
-#error must have a working 64-bit integer datatype
+	StaticAssertStmt(sizeof(word) == sizeof(long long), "unexpected size");
+	return __builtin_popcountll(word);
 #endif
 #else							/* !HAVE__BUILTIN_POPCOUNT */
 	int			result = 0;
diff --git a/src/port/snprintf.c b/src/port/snprintf.c
index 884f0262dd..291148b4e8 100644
--- a/src/port/snprintf.c
+++ b/src/port/snprintf.c
@@ -568,12 +568,11 @@ nextch2:
 				goto nextch2;
 			case 'z':
 #if SIZEOF_SIZE_T == 8
-#ifdef HAVE_LONG_INT_64
+#if SIZEOF_LONG == 8
 				longflag = 1;
-#elif defined(HAVE_LONG_LONG_INT_64)
-				longlongflag = 1;
 #else
-#error "Don't know how to print 64bit integers"
+				StaticAssertStmt(sizeof(size_t) == sizeof(long long), "unexpected size");
+				longlongflag = 1;
 #endif
 #else
 				/* assume size_t is same size as int */
@@ -835,12 +834,11 @@ nextch1:
 				goto nextch1;
 			case 'z':
 #if SIZEOF_SIZE_T == 8
-#ifdef HAVE_LONG_INT_64
+#if SIZEOF_LONG == 8
 				longflag = 1;
-#elif defined(HAVE_LONG_LONG_INT_64)
-				longlongflag = 1;
 #else
-#error "Don't know how to print 64bit integers"
+				StaticAssertStmt(sizeof(size_t) == sizeof(long long), "unexpected size");
+				longlongflag = 1;
 #endif
 #else
 				/* assume size_t is same size as int */
diff --git a/src/test/modules/test_radixtree/test_radixtree.c b/src/test/modules/test_radixtree/test_radixtree.c
index d301c60d00..f8a80b1a8e 100644
--- a/src/test/modules/test_radixtree/test_radixtree.c
+++ b/src/test/modules/test_radixtree/test_radixtree.c
@@ -23,7 +23,7 @@
 /* uncomment to use shared memory for the tree */
 /* #define TEST_SHARED_RT */
 
-#define UINT64_HEX_FORMAT "%" INT64_MODIFIER "X"
+#define UINT64_HEX_FORMAT "%" PRIX64
 
 /* Convenient macros to test results */
 #define EXPECT_TRUE(expr)	\
-- 
2.39.3 (Apple Git-146)

v2-0002-Remove-traces-of-BeOS.patchapplication/octet-stream; name=v2-0002-Remove-traces-of-BeOS.patchDownload
From 74d09d7a3c91aef776df143407c4363c55939003 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Thu, 18 Apr 2024 12:06:17 +1200
Subject: [PATCH v2 2/2] Remove traces of BeOS.

Commit 15abc7788e6 tolerated namespace pollution from BeOS system
headers.  Commit 44f902122 de-supported BeOS.  Since that stuff didn't
make it into the Meson build system, synchronize by removing from
configure.
---
 configure                  | 44 --------------------------------------
 configure.ac               |  5 -----
 src/include/c.h            |  8 -------
 src/include/pg_config.h.in | 12 -----------
 4 files changed, 69 deletions(-)

diff --git a/configure b/configure
index 52b5f666ce..1a1fa7cbe2 100755
--- a/configure
+++ b/configure
@@ -16787,50 +16787,6 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
-# Some platforms predefine the types int8, int16, etc.  Only check
-# a (hopefully) representative subset.
-ac_fn_c_check_type "$LINENO" "int8" "ac_cv_type_int8" "#include <stdio.h>
-"
-if test "x$ac_cv_type_int8" = xyes; then :
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_INT8 1
-_ACEOF
-
-
-fi
-ac_fn_c_check_type "$LINENO" "uint8" "ac_cv_type_uint8" "#include <stdio.h>
-"
-if test "x$ac_cv_type_uint8" = xyes; then :
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_UINT8 1
-_ACEOF
-
-
-fi
-ac_fn_c_check_type "$LINENO" "int64" "ac_cv_type_int64" "#include <stdio.h>
-"
-if test "x$ac_cv_type_int64" = xyes; then :
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_INT64 1
-_ACEOF
-
-
-fi
-ac_fn_c_check_type "$LINENO" "uint64" "ac_cv_type_uint64" "#include <stdio.h>
-"
-if test "x$ac_cv_type_uint64" = xyes; then :
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_UINT64 1
-_ACEOF
-
-
-fi
-
-
 # Some compilers offer a 128-bit integer scalar type.
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __int128" >&5
 $as_echo_n "checking for __int128... " >&6; }
diff --git a/configure.ac b/configure.ac
index 1c4cd3ab72..f5dc1b03a3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1988,11 +1988,6 @@ if test $ac_cv_alignof_int64_t -gt $MAX_ALIGNOF ; then
 fi
 AC_DEFINE_UNQUOTED(MAXIMUM_ALIGNOF, $MAX_ALIGNOF, [Define as the maximum alignment requirement of any C data type.])
 
-# Some platforms predefine the types int8, int16, etc.  Only check
-# a (hopefully) representative subset.
-AC_CHECK_TYPES([int8, uint8, int64, uint64], [], [],
-[#include <stdio.h>])
-
 # Some compilers offer a 128-bit integer scalar type.
 PGAC_TYPE_128BIT_INT
 
diff --git a/src/include/c.h b/src/include/c.h
index fd876c32af..31a0400539 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -486,14 +486,10 @@ typedef char *Pointer;
  *		used for numerical computations and the
  *		frontend/backend protocol.
  */
-#ifndef HAVE_INT8
 typedef int8_t int8;			/* == 8 bits */
 typedef int16_t int16;			/* == 16 bits */
 typedef int32_t int32;			/* == 32 bits */
-#endif							/* not HAVE_INT8 */
-#ifndef HAVE_INT64
 typedef int64_t int64;			/* == 64 bits */
-#endif							/* not HAVE_INT64 */
 
 /*
  * uintN
@@ -501,14 +497,10 @@ typedef int64_t int64;			/* == 64 bits */
  *		used for numerical computations and the
  *		frontend/backend protocol.
  */
-#ifndef HAVE_UINT8
 typedef uint8_t uint8;			/* == 8 bits */
 typedef uint16_t uint16;		/* == 16 bits */
 typedef uint32_t uint32;		/* == 32 bits */
-#endif							/* not HAVE_UINT8 */
-#ifndef HAVE_UINT64
 typedef uint64_t uint64;		/* == 64 bits */
-#endif							/* not HAVE_UINT64 */
 
 /*
  * bitsN
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index 2791ec5fab..3a3caf9b0a 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -213,12 +213,6 @@
 /* Define to 1 if you have the `inet_pton' function. */
 #undef HAVE_INET_PTON
 
-/* Define to 1 if the system has the type `int64'. */
-#undef HAVE_INT64
-
-/* Define to 1 if the system has the type `int8'. */
-#undef HAVE_INT8
-
 /* Define to 1 if you have the <inttypes.h> header file. */
 #undef HAVE_INTTYPES_H
 
@@ -465,12 +459,6 @@
 /* Define to 1 if you have the <ucred.h> header file. */
 #undef HAVE_UCRED_H
 
-/* Define to 1 if the system has the type `uint64'. */
-#undef HAVE_UINT64
-
-/* Define to 1 if the system has the type `uint8'. */
-#undef HAVE_UINT8
-
 /* Define to 1 if the system has the type `union semun'. */
 #undef HAVE_UNION_SEMUN
 
-- 
2.39.3 (Apple Git-146)

#21Thomas Munro
thomas.munro@gmail.com
In reply to: Peter Eisentraut (#19)
Re: Cannot find a working 64-bit integer type on Illumos

On Thu, Apr 18, 2024 at 8:47 PM Peter Eisentraut <peter@eisentraut.org> wrote:

Maybe this means something like our int64 is long long int but the
system's int64_t is long int underneath, but I don't see how that would
matter for the limit macros.

Agreed, so I don't think it's long vs long long (when they have the same width).

I wonder if this comment is a clue:

static char *
inet_net_ntop_ipv6(const u_char *src, int bits, char *dst, size_t size)
{
/*
* Note that int32_t and int16_t need only be "at least" large enough to
* contain a value of the specified size. On some systems, like Crays,
* there is no such thing as an integer variable with 16 bits. Keep this
* in mind if you think this function should have been coded to use
* pointer overlays. All the world's not a VAX.
*/

I'd seen that claim before somewhere else but I can't recall where.
So there were systems using those names in an ad hoc unspecified way
before C99 nailed this stuff down? In modern C, int32_t is definitely
an exact width type (but there are other standardised variants like
int_fast32_t to allow for Cray-like systems that would prefer to use a
wider type, ie "at least", 32 bits wide, so I guess that's what
happened to that idea?).

Or perhaps it's referring to worries about the width of char, short,
int or the assumption of two's-complement. I think if any of that
stuff weren't as assumed we'd have many problems in many places, so
I'm not seeing a problem. (FTR C23 finally nailed down
two's-complement as a requirement, and although C might not say so,
POSIX says that char is a byte, and our assumption that int = int32_t
is pretty deeply baked into PostgreSQL, so it's almost impossible to
imagine that short has a size other than 16 bits; but these are all
assumptions made by the OLD coding, not by the patch I posted). In
short, I guess that isn't what was meant.

#22Thomas Munro
thomas.munro@gmail.com
In reply to: Japin Li (#18)
Re: Cannot find a working 64-bit integer type on Illumos

On Thu, Apr 18, 2024 at 6:09 PM Japin Li <japinli@hotmail.com> wrote:

/home/japin/postgres/build/../src/common/config_info.c:198:11: error: comparison of integer expressions of different signedness: 'int' and 'size_t' {aka 'long unsigned int'} [-Werror=sign-compare]
198 | Assert(i == *configdata_len);

Right, PostgreSQL doesn't compile cleanly with the "sign-compare"
warning. There have been a few threads about that, and someone might
want to think harder about it, but it's a different topic unrelated to
<stdint.h>.

/home/japin/postgres/build/../src/include/lib/simplehash.h:1138:9: error: format '%llu' expects argument of type 'long long unsigned int', but argument 4 has type 'uint64' {aka 'long unsigned int'} [-Werror=format=]

It seems my v1 patch's configure probe for INT64_FORMAT was broken.
In the v2 patch I tried not doing that probe at all, and instead
inviting <inttypes.h> into our world (that's the standardised way to
produce format strings, which has the slight complication that we are
intercepting printf calls...). I suspect that'll work better for you.

#23Japin Li
japinli@hotmail.com
In reply to: Thomas Munro (#22)
Re: Cannot find a working 64-bit integer type on Illumos

On Fri, 19 Apr 2024 at 05:22, Thomas Munro <thomas.munro@gmail.com> wrote:

On Thu, Apr 18, 2024 at 6:09 PM Japin Li <japinli@hotmail.com> wrote:

/home/japin/postgres/build/../src/include/lib/simplehash.h:1138:9: error: format '%llu' expects argument of type 'long long unsigned int', but argument 4 has type 'uint64' {aka 'long unsigned int'} [-Werror=format=]

It seems my v1 patch's configure probe for INT64_FORMAT was broken.
In the v2 patch I tried not doing that probe at all, and instead
inviting <inttypes.h> into our world (that's the standardised way to
produce format strings, which has the slight complication that we are
intercepting printf calls...). I suspect that'll work better for you.

Yeah, the v2 patch fixed this problem.

--
Regards,
Japin Li

#24Peter Eisentraut
peter@eisentraut.org
In reply to: Thomas Munro (#17)
Re: Cannot find a working 64-bit integer type on Illumos

On 18.04.24 02:31, Thomas Munro wrote:

For limits, why do we have this:

- * stdint.h limits aren't guaranteed to have compatible types with our fixed
- * width types. So just define our own.

? I mean, how could they not have compatible types?

The commit for this was 62e2a8dc2c7 and the thread was
</messages/by-id/E1YatAv-0007cu-KW@gemulon.postgresql.org&gt;.
The problem was that something like

snprintf(bufm, sizeof(bufm), INT64_FORMAT, SEQ_MINVALUE);

could issue a warning if, say, INT64_FORMAT, which refers to our own
int64, is based on long int, but SEQ_MINVALUE, which was then INT64_MIN,
which refers to int64_t, which could be long long int.

So this is correct. If we introduce the use of int64_t, then you need
to be consistent still:

int64, PG_INT64_MIN, PG_INT64_MAX, INT64_FORMAT

int64_t, INT64_MIN, INT64_MAX, PRId64

#25Heikki Linnakangas
hlinnaka@iki.fi
In reply to: Thomas Munro (#20)
Re: Cannot find a working 64-bit integer type on Illumos

On 18/04/2024 23:29, Thomas Munro wrote:

On Thu, Apr 18, 2024 at 8:47 PM Peter Eisentraut <peter@eisentraut.org> wrote:

I'm not sure I understand the problem here. Do you mean that in theory
a platform's PRId64 could be something other than "l" or "ll"?

Yes. I don't know why anyone would do that, and the systems I checked
all have the obvious definitions, eg "ld", "lld" etc. Perhaps it's an
acceptable risk? It certainly gives us a tidier result.

Could we have a configure check or static assertion for that?

For discussion, here is a variant that fully embraces <inttypes.h> and
the PRI*64 macros.

Looks good to me.

Personally, I find "PRId64" pretty unreadable. "INT64_MODIFIER" wasn't
nice either, though, and following standards is good, so I'm sure I'll
get used to it.

They're both less readable than INT64_FORMAT and "%lld", which we use in
most places, though. Perhaps "%lld" and casting the arguments to "long
long" would be more readable in the places where this patch replaces
INT64_MODIFIER with PRI*64, too.

--
Heikki Linnakangas
Neon (https://neon.tech)

#26Thomas Munro
thomas.munro@gmail.com
In reply to: Heikki Linnakangas (#25)
4 attachment(s)
Re: Cannot find a working 64-bit integer type on Illumos

On Wed, Jul 3, 2024 at 1:34 AM Heikki Linnakangas <hlinnaka@iki.fi> wrote:

On 18/04/2024 23:29, Thomas Munro wrote:

On Thu, Apr 18, 2024 at 8:47 PM Peter Eisentraut <peter@eisentraut.org> wrote:

I'm not sure I understand the problem here. Do you mean that in theory
a platform's PRId64 could be something other than "l" or "ll"?

Yes. I don't know why anyone would do that, and the systems I checked
all have the obvious definitions, eg "ld", "lld" etc. Perhaps it's an
acceptable risk? It certainly gives us a tidier result.

Could we have a configure check or static assertion for that?

Unfortunately, that theory turned out to be wrong. The usual suspect,
Windows, uses something else: "I64" or something like that. We could
teach our snprintf to grok that, but I don't like the idea anymore.
So let's go back to INT64_MODIFIER, with just a small amount of
configure time work to pick the right value. I couldn't figure out
any header-only way to do that.

Personally, I find "PRId64" pretty unreadable. "INT64_MODIFIER" wasn't
nice either, though, and following standards is good, so I'm sure I'll
get used to it.

Yeah, I like standards a lot but we've painted ourselves into a corner here...

New version attached. This time I was brave enough to try to tackle
src/timezone too, which had comments planning to drop a lot of small
differences against the upstream tzcode once all supported branches
required C99. I suppose that should make future maintenance easier,
and C89 disappeared from our window of interest with PostgreSQL 11.
It's a little hard to understand what changed, but to try to show it
better I diff'd master against upstream (after filtering through sed
and pgindent as recommended by README), and then diff'd patched
against upstream, and then ... ehm.. diff'd the two diffs, so that you
can see there are some hunks that go away.

IMHO it's a rather scary choice on tzcode's part to use int_fastN_t,
and hard for us to verify that it works correctly especially when
combined with our changes, but on the other hand I don't really expect
any system that PostgreSQL can run on to have "fast" types that really
differ from the "exact width" types. My understanding is that this is
something of interest to historical supercomputers and
microcontrollers, but I can't find any evidence of general
purpose/commodity systems that we target using different sizes (anyone
know better?).

Attachments:

tzcode.diff.diff.txttext/plain; charset=US-ASCII; name=tzcode.diff.diff.txtDownload
--- zic.c-master-vs-upstream.diff	2024-07-04 14:38:42.919508000 +1200
+++ zic.c-patched-vs-upstream.diff	2024-07-04 14:37:23.663247000 +1200
@@ -1,6 +1,6 @@
 --- zic.filtered.c	2024-07-04 12:24:07.383657000 +1200
-+++ zic.c	2024-07-04 14:38:19.086696000 +1200
-@@ -3,104 +3,66 @@
++++ zic.c	2024-07-04 14:17:36.438520000 +1200
+@@ -3,104 +3,72 @@
  /*
   * This file is in the public domain, so clarified as of
   * 2006-07-17 by Arthur David Olson.
@@ -19,6 +19,8 @@
  
 -#include "version.h"
 +#include <fcntl.h>
++#include <inttypes.h>
++#include <stdint.h>
 +#include <sys/stat.h>
 +#include <time.h>
 +
@@ -36,20 +38,18 @@
 +#define	ZIC_VERSION_PRE_2013 '2'
 +#define	ZIC_VERSION	'3'
  
--typedef int_fast64_t zic_t;
--static zic_t const
--			ZIC_MIN = INT_FAST64_MIN,
--			ZIC_MAX = INT_FAST64_MAX,
+ typedef int_fast64_t zic_t;
+ static zic_t const
+ 			ZIC_MIN = INT_FAST64_MIN,
+ 			ZIC_MAX = INT_FAST64_MAX,
 -			ZIC32_MIN = -1 - (zic_t) 0x7fffffff,
 -			ZIC32_MAX = 0x7fffffff;
--#define SCNdZIC SCNdFAST64
-+typedef int64 zic_t;
-+#define ZIC_MIN PG_INT64_MIN
-+#define ZIC_MAX PG_INT64_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
+ #define ZIC_MAX_ABBR_LEN_WO_WARN 6
  #endif							/* !defined ZIC_MAX_ABBR_LEN_WO_WARN */
  
 -/* Minimum and maximum years, assuming signed 32-bit pg_time_t.  */
@@ -137,7 +137,7 @@
  	bool		r_hiwasnum;
  
  	int			r_month;		/* 0..11 */
-@@ -121,18 +83,16 @@
+@@ -121,18 +89,16 @@
  };
  
  /*
@@ -162,7 +162,7 @@
  	lineno_t	z_linenum;
  
  	const char *z_name;
-@@ -151,59 +111,46 @@
+@@ -151,59 +117,46 @@
  	zic_t		z_untiltime;
  };
  
@@ -245,7 +245,7 @@
  					const char *loyearp, const char *hiyearp,
  					const char *typep, const char *monthp,
  					const char *dayp, const char *timep);
-@@ -214,10 +161,21 @@
+@@ -214,10 +167,21 @@
  {
  PERCENT_Z_LEN_BOUND = sizeof "+995959" - 1};
  
@@ -268,7 +268,7 @@
  static int	leapcnt;
  static bool leapseen;
  static zic_t leapminyear;
-@@ -228,132 +186,99 @@
+@@ -228,132 +192,99 @@
  static zic_t max_year;
  static zic_t min_year;
  static bool noise;
@@ -453,7 +453,7 @@
  
  static struct rule *rules;
  static ptrdiff_t nrules;		/* number of rules */
-@@ -365,7 +290,7 @@
+@@ -365,7 +296,7 @@
  
  struct link
  {
@@ -462,7 +462,7 @@
  	lineno_t	l_linenum;
  	const char *l_target;
  	const char *l_linkname;
-@@ -381,8 +306,8 @@
+@@ -381,8 +312,8 @@
  	const int	l_value;
  };
  
@@ -473,7 +473,7 @@
  
  static struct lookup const zi_line_codes[] = {
  	{"Rule", LC_RULE},
-@@ -436,10 +361,12 @@
+@@ -436,10 +367,12 @@
  
  static struct lookup const begin_years[] = {
  	{"minimum", YR_MINIMUM},
@@ -486,7 +486,7 @@
  	{"maximum", YR_MAXIMUM},
  	{"only", YR_ONLY},
  	{NULL, 0}
-@@ -480,79 +407,30 @@
+@@ -480,79 +413,30 @@
   * Memory allocation.
   */
  
@@ -574,7 +574,7 @@
  emalloc(size_t size)
  {
  	return memcheck(malloc(size));
-@@ -564,100 +442,66 @@
+@@ -564,100 +448,66 @@
  	return memcheck(realloc(ptr, size));
  }
  
@@ -703,7 +703,7 @@
  {
  	va_list		args;
  
-@@ -667,8 +511,8 @@
+@@ -667,8 +517,8 @@
  	errors = true;
  }
  
@@ -714,7 +714,7 @@
  {
  	va_list		args;
  
-@@ -679,11 +523,8 @@
+@@ -679,11 +529,8 @@
  	warnings = true;
  }
  
@@ -727,7 +727,7 @@
  {
  	char const *e = (ferror(stream) ? _("I/O error")
  					 : fclose(stream) != 0 ? strerror(errno) : NULL);
-@@ -694,26 +535,23 @@
+@@ -694,26 +541,23 @@
  				dir ? dir : "", dir ? "/" : "",
  				name ? name : "", name ? ": " : "",
  				e);
@@ -759,7 +759,7 @@
  	exit(status);
  }
  
-@@ -741,221 +579,8 @@
+@@ -741,221 +585,8 @@
  	}
  }
  
@@ -982,7 +982,7 @@
  /* The minimum and maximum values representable in a TZif file.  */
  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);
-@@ -965,19 +590,18 @@
+@@ -965,13 +596,12 @@
  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);
  
@@ -999,32 +999,8 @@
  /* Set the time range of the output to TIMERANGE.
     Return true if successful.  */
  static bool
- timerange_option(char *timerange)
- {
--	intmax_t	lo = min_time,
-+	int64		lo = min_time,
- 				hi = max_time;
- 	char	   *lo_end = timerange,
- 			   *hi_end;
-@@ -986,7 +610,7 @@
- 	{
- 		errno = 0;
- 		lo = strtoimax(timerange + 1, &lo_end, 10);
--		if (lo_end == timerange + 1 || (lo == INTMAX_MAX && errno == ERANGE))
-+		if (lo_end == timerange + 1 || (lo == PG_INT64_MAX && errno == ERANGE))
- 			return false;
+@@ -1000,33 +630,15 @@
  	}
- 	hi_end = lo_end;
-@@ -994,39 +618,21 @@
- 	{
- 		errno = 0;
- 		hi = strtoimax(lo_end + 2, &hi_end, 10);
--		if (hi_end == lo_end + 2 || hi == INTMAX_MIN)
-+		if (hi_end == lo_end + 2 || hi == PG_INT64_MIN)
- 			return false;
--		hi -= !(hi == INTMAX_MAX && errno == ERANGE);
-+		hi -= !(hi == PG_INT64_MAX && errno == ERANGE);
- 	}
  	if (*hi_end || hi < lo || max_time < lo || hi < min_time)
  		return false;
 -	lo_time = max(lo, min_time);
@@ -1060,7 +1036,7 @@
  static const char *tzdefault;
  
  /* -1 if the TZif output file should be slim, 0 if default, 1 if the
-@@ -1053,18 +659,10 @@
+@@ -1053,18 +665,10 @@
  				j;
  	bool		timerange_given = false;
  
@@ -1081,7 +1057,7 @@
  	if (TYPE_BIT(zic_t) < 64)
  	{
  		fprintf(stderr, "%s: %s\n", progname,
-@@ -1074,16 +672,15 @@
+@@ -1074,16 +678,15 @@
  	for (k = 1; k < argc; k++)
  		if (strcmp(argv[k], "--version") == 0)
  		{
@@ -1101,7 +1077,7 @@
  		switch (c)
  		{
  			default:
-@@ -1106,36 +703,33 @@
+@@ -1106,36 +709,33 @@
  				break;
  			case 'd':
  				if (directory == NULL)
@@ -1144,7 +1120,7 @@
  							progname);
  					return EXIT_FAILURE;
  				}
-@@ -1156,12 +750,11 @@
+@@ -1156,12 +756,11 @@
  				break;
  			case 'L':
  				if (leapsec == NULL)
@@ -1159,7 +1135,7 @@
  							progname);
  					return EXIT_FAILURE;
  				}
-@@ -1169,12 +762,15 @@
+@@ -1169,12 +768,15 @@
  			case 'v':
  				noise = true;
  				break;
@@ -1177,7 +1153,7 @@
  							progname);
  					return EXIT_FAILURE;
  				}
-@@ -1187,27 +783,12 @@
+@@ -1187,27 +789,12 @@
  				}
  				timerange_given = true;
  				break;
@@ -1205,7 +1181,7 @@
  	if (bloat == 0)
  	{
  		static char const bloat_default[] = ZIC_BLOAT_DEFAULT;
-@@ -1220,23 +801,22 @@
+@@ -1220,23 +807,22 @@
  			abort();			/* Configuration error.  */
  	}
  	if (directory == NULL)
@@ -1232,7 +1208,7 @@
  	for (i = 0; i < nzones; i = j)
  	{
  		/*
-@@ -1246,15 +826,28 @@
+@@ -1246,15 +832,28 @@
  			continue;
  		outzone(&zones[i], j - i);
  	}
@@ -1264,7 +1240,7 @@
  		dolink(psxrules, TZDEFRULES, true);
  	}
  	if (warnings && (ferror(stderr) || fclose(stderr) != 0))
-@@ -1347,211 +940,22 @@
+@@ -1347,211 +946,22 @@
  	return componentcheck(name, component, cp);
  }
  
@@ -1487,7 +1463,7 @@
  	char const *f = target;
  	char	   *result = NULL;
  
-@@ -1559,14 +963,13 @@
+@@ -1559,14 +969,13 @@
  	{
  		/* Make F absolute too.  */
  		size_t		len = strlen(directory);
@@ -1506,7 +1482,7 @@
  	}
  	for (i = 0; f[i] && f[i] == linkname[i]; i++)
  		if (f[i] == '/')
-@@ -1574,7 +977,7 @@
+@@ -1574,7 +983,7 @@
  	for (; linkname[i]; i++)
  		dotdots += linkname[i] == '/' && linkname[i - 1] != '/';
  	taillen = strlen(f + dir_len);
@@ -1515,7 +1491,7 @@
  	if (dotdotetcsize <= linksize)
  	{
  		if (!result)
-@@ -1585,133 +988,80 @@
+@@ -1585,133 +994,80 @@
  	}
  	return result;
  }
@@ -1693,7 +1669,7 @@
  		{
  			FILE	   *fp,
  					   *tp;
-@@ -1726,37 +1076,69 @@
+@@ -1726,37 +1082,69 @@
  						progname, directory, target, e);
  				exit(EXIT_FAILURE);
  			}
@@ -1776,7 +1752,7 @@
  /*
   * Associate sets of rules with zones.
   */
-@@ -1768,10 +1150,8 @@
+@@ -1768,10 +1156,8 @@
  static int
  rcomp(const void *cp1, const void *cp2)
  {
@@ -1789,7 +1765,7 @@
  }
  
  static void
-@@ -1784,7 +1164,7 @@
+@@ -1784,7 +1170,7 @@
  				base,
  				out;
  
@@ -1798,7 +1774,7 @@
  	{
  		qsort(rules, nrules, sizeof *rules, rcomp);
  		for (i = 0; i < nrules - 1; ++i)
-@@ -1792,21 +1172,23 @@
+@@ -1792,21 +1178,23 @@
  			if (strcmp(rules[i].r_name,
  					   rules[i + 1].r_name) != 0)
  				continue;
@@ -1828,7 +1804,7 @@
  					continue;
  				break;
  			}
-@@ -1842,7 +1224,7 @@
+@@ -1842,7 +1230,7 @@
  			/*
  			 * Maybe we have a local standard time offset.
  			 */
@@ -1837,7 +1813,7 @@
  			zp->z_save = getsave(zp->z_rule, &zp->z_isdst);
  
  			/*
-@@ -1857,85 +1239,71 @@
+@@ -1857,85 +1245,60 @@
  		exit(EXIT_FAILURE);
  }
  
@@ -1947,23 +1923,12 @@
 -			/* nothing to do */
 +			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)
  		{
-@@ -1944,7 +1312,7 @@
+@@ -1944,7 +1307,7 @@
  		else
  		{
  			struct lookup const *line_codes
@@ -1972,7 +1937,7 @@
  
  			lp = byword(fields[0], line_codes);
  			if (lp == NULL)
-@@ -1971,12 +1339,16 @@
+@@ -1971,12 +1334,16 @@
  						inexpires(fields, nfields);
  						wantcont = false;
  						break;
@@ -1992,26 +1957,7 @@
  	if (wantcont)
  		error(_("expected continuation line not found"));
  }
-@@ -1992,7 +1364,8 @@
- static zic_t
- gethms(char const *string, char const *errstring)
- {
--	zic_t		hh;
-+	/* PG: make hh be int not zic_t to avoid sscanf portability issues */
-+	int			hh;
- 	int			sign,
- 				mm = 0,
- 				ss = 0;
-@@ -2014,7 +1387,7 @@
- 	else
- 		sign = 1;
- 	switch (sscanf(string,
--				   "%" SCNdZIC "%c%d%c%d%c%1d%*[0]%c%*[0123456789]%c",
-+				   "%d%c%d%c%d%c%1d%*[0]%c%*[0123456789]%c",
- 				   &hh, &hhx, &mm, &mmx, &ss, &ssx, &tenths, &xr, &xs))
- 	{
- 		default:
-@@ -2022,19 +1395,19 @@
+@@ -2022,19 +1389,19 @@
  			break;
  		case 8:
  			ok = '0' <= xr && xr <= '9';
@@ -2035,12 +1981,12 @@
  		case 1:
  			break;
  	}
-@@ -2050,16 +1423,19 @@
+@@ -2050,16 +1417,19 @@
  		error("%s", 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"));
@@ -2056,7 +2002,7 @@
  				sign * (mm * SECSPERMIN + ss));
  }
  
-@@ -2068,7 +1444,7 @@
+@@ -2068,7 +1438,7 @@
  {
  	int			dst = -1;
  	zic_t		save;
@@ -2065,7 +2011,7 @@
  
  	if (fieldlen != 0)
  	{
-@@ -2094,7 +1470,7 @@
+@@ -2094,7 +1464,7 @@
  static void
  inrule(char **fields, int nfields)
  {
@@ -2074,7 +2020,7 @@
  
  	if (nfields != RULE_FIELDS)
  	{
-@@ -2125,15 +1501,13 @@
+@@ -2125,15 +1495,13 @@
  			error(_("Invalid rule name \"%s\""), fields[RF_NAME]);
  			return;
  	}
@@ -2095,7 +2041,7 @@
  	if (max_abbrvar_len < strlen(r.r_abbrvar))
  		max_abbrvar_len = strlen(r.r_abbrvar);
  	rules = growalloc(rules, sizeof *rules, nrules, &nrules_alloc);
-@@ -2152,13 +1526,15 @@
+@@ -2152,13 +1520,15 @@
  	}
  	if (lcltime != NULL && strcmp(fields[ZF_NAME], tzdefault) == 0)
  	{
@@ -2113,7 +2059,7 @@
  			  TZDEFRULES);
  		return false;
  	}
-@@ -2167,9 +1543,9 @@
+@@ -2167,9 +1537,9 @@
  			strcmp(zones[i].z_name, fields[ZF_NAME]) == 0)
  		{
  			error(_("duplicate zone name %s"
@@ -2125,7 +2071,7 @@
  				  zones[i].z_linenum);
  			return false;
  		}
-@@ -2192,8 +1568,7 @@
+@@ -2192,8 +1562,7 @@
  {
  	char	   *cp;
  	char	   *cp1;
@@ -2135,7 +2081,7 @@
  	int			i_stdoff,
  				i_rule,
  				i_format;
-@@ -2212,6 +1587,7 @@
+@@ -2212,6 +1581,7 @@
  		i_untilmonth = ZFC_TILMONTH;
  		i_untilday = ZFC_TILDAY;
  		i_untiltime = ZFC_TILTIME;
@@ -2143,7 +2089,7 @@
  	}
  	else if (!namecheck(fields[ZF_NAME]))
  		return false;
-@@ -2224,11 +1600,12 @@
+@@ -2224,11 +1594,12 @@
  		i_untilmonth = ZF_TILMONTH;
  		i_untilday = ZF_TILDAY;
  		i_untiltime = ZF_TILTIME;
@@ -2158,7 +2104,7 @@
  	{
  		if ((*++cp != 's' && *cp != 'z') || strchr(cp, '%')
  			|| strchr(fields[i_format], '/'))
-@@ -2237,25 +1614,31 @@
+@@ -2237,25 +1608,31 @@
  			return false;
  		}
  	}
@@ -2204,7 +2150,7 @@
  		z.z_untiltime = rpytime(&z.z_untilrule,
  								z.z_untilrule.r_loyear);
  		if (iscont && nzones > 0 &&
-@@ -2265,21 +1648,10 @@
+@@ -2265,21 +1642,10 @@
  			zones[nzones - 1].z_untiltime < max_time &&
  			zones[nzones - 1].z_untiltime >= z.z_untiltime)
  		{
@@ -2227,7 +2173,7 @@
  	zones = growalloc(zones, sizeof *zones, nzones, &nzones_alloc);
  	zones[nzones++] = z;
  
-@@ -2291,13 +1663,15 @@
+@@ -2291,12 +1657,13 @@
  }
  
  static zic_t
@@ -2238,23 +2184,11 @@
  	const struct lookup *lp;
  	zic_t		i,
  				j;
--	zic_t		year;
 +
-+	/* PG: make year be int not zic_t to avoid sscanf portability issues */
-+	int			year;
+ 	zic_t		year;
  	int			month,
  				day;
- 	zic_t		dayoff,
-@@ -2307,7 +1681,7 @@
- 
- 	dayoff = 0;
- 	cp = fields[LP_YEAR];
--	if (sscanf(cp, "%" SCNdZIC "%c", &year, &xs) != 1)
-+	if (sscanf(cp, "%d%c", &year, &xs) != 1)
- 	{
- 		/*
- 		 * Leapin' Lizards!
-@@ -2384,7 +1758,7 @@
+@@ -2384,7 +1751,7 @@
  		error(_("wrong number of fields on Leap line"));
  	else
  	{
@@ -2263,7 +2197,7 @@
  
  		if (0 <= t)
  		{
-@@ -2417,7 +1791,7 @@
+@@ -2417,7 +1784,7 @@
  	else if (0 <= leapexpires)
  		error(_("multiple Expires lines"));
  	else
@@ -2272,7 +2206,7 @@
  }
  
  static void
-@@ -2437,15 +1811,15 @@
+@@ -2437,15 +1804,15 @@
  	}
  	if (!namecheck(fields[LF_LINKNAME]))
  		return;
@@ -2292,13 +2226,7 @@
  rulesub(struct rule *rp, const char *loyearp, const char *hiyearp,
  		const char *typep, const char *monthp, const char *dayp,
  		const char *timep)
-@@ -2456,15 +1830,18 @@
- 	char	   *ep;
- 	char		xs;
- 
-+	/* PG: year_tmp is to avoid sscanf portability issues */
-+	int			year_tmp;
-+
+@@ -2459,12 +1826,12 @@
  	if ((lp = byword(monthp, mon_names)) == NULL)
  	{
  		error(_("invalid month name"));
@@ -2313,7 +2241,7 @@
  	if (*dp != '\0')
  	{
  		ep = dp + strlen(dp) - 1;
-@@ -2497,22 +1874,28 @@
+@@ -2497,22 +1864,26 @@
  	 */
  	cp = loyearp;
  	lp = byword(cp, begin_years);
@@ -2340,10 +2268,7 @@
 +						progname, lp->l_value);
 +				exit(EXIT_FAILURE);
  		}
--	else if (sscanf(cp, "%" SCNdZIC "%c", &rp->r_loyear, &xs) != 1)
-+	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 false;
@@ -2351,7 +2276,7 @@
  	}
  	cp = hiyearp;
  	lp = byword(cp, end_years);
-@@ -2520,37 +1903,45 @@
+@@ -2520,37 +1891,43 @@
  	if (!rp->r_hiwasnum)
  		switch (lp->l_value)
  		{
@@ -2372,10 +2297,7 @@
 +						progname, lp->l_value);
 +				exit(EXIT_FAILURE);
  		}
--	else if (sscanf(cp, "%" SCNdZIC "%c", &rp->r_hiyear, &xs) != 1)
-+	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 false;
@@ -2404,7 +2326,7 @@
  	if ((lp = byword(dp, lasts)) != NULL)
  	{
  		rp->r_dycode = DC_DOWLEQ;
-@@ -2559,9 +1950,9 @@
+@@ -2559,9 +1936,9 @@
  	}
  	else
  	{
@@ -2416,7 +2338,7 @@
  			rp->r_dycode = DC_DOWGEQ;
  		else
  		{
-@@ -2575,13 +1966,13 @@
+@@ -2575,13 +1952,13 @@
  			{
  				error(_("invalid day of month"));
  				free(dp);
@@ -2432,7 +2354,7 @@
  			}
  			rp->r_wday = lp->l_value;
  		}
-@@ -2591,37 +1982,36 @@
+@@ -2591,37 +1968,36 @@
  		{
  			error(_("invalid day of month"));
  			free(dp);
@@ -2446,7 +2368,7 @@
  
  static void
 -convert(uint_fast32_t val, char *buf)
-+convert(const int32 val, char *const buf)
++convert(const int_fast32_t val, char *const buf)
  {
  	int			i;
  	int			shift;
@@ -2459,7 +2381,7 @@
  
  static void
 -convert64(uint_fast64_t val, char *buf)
-+convert64(const zic_t val, char *const buf)
++convert64(uint_fast64_t val, char *const buf)
  {
  	int			i;
  	int			shift;
@@ -2472,11 +2394,11 @@
  
  static void
 -puttzcode(zic_t val, FILE *fp)
-+puttzcode(const int32 val, FILE *const fp)
++puttzcode(zic_t val, FILE *const fp)
  {
  	char		buf[4];
  
-@@ -2646,12 +2036,10 @@
+@@ -2646,12 +2022,10 @@
  static int
  atcomp(const void *avp, const void *bvp)
  {
@@ -2492,7 +2414,7 @@
  }
  
  struct timerange
-@@ -2661,44 +2049,25 @@
+@@ -2661,44 +2035,25 @@
  				count;
  	int			leapbase,
  				leapcount;
@@ -2539,7 +2461,7 @@
  	{
  		while (0 < r.count && hi + 1 < ats[r.base + r.count - 1])
  			r.count--;
-@@ -2706,9 +2075,6 @@
+@@ -2706,9 +2061,6 @@
  			r.leapcount--;
  	}
  
@@ -2549,7 +2471,7 @@
  	return r;
  }
  
-@@ -2720,20 +2086,23 @@
+@@ -2720,20 +2072,23 @@
  	ptrdiff_t	i,
  				j;
  	int			pass;
@@ -2582,7 +2504,7 @@
  
  	/*
  	 * Sort.
-@@ -2810,49 +2179,61 @@
+@@ -2810,49 +2165,61 @@
  			}
  	}
  
@@ -2611,9 +2533,8 @@
 -						 max(hi_time,
 -							 redundant_time - (ZIC_MIN < redundant_time)),
 -						 ats, types);
--	range32 = limitrange(range64, ZIC32_MIN, ZIC32_MAX, ats, types);
 +	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);
  
  	/*
 -	 * TZif version 4 is needed if a no-op transition is appended to indicate
@@ -2674,7 +2595,7 @@
  	for (pass = 1; pass <= 2; ++pass)
  	{
  		ptrdiff_t	thistimei,
-@@ -2861,15 +2242,11 @@
+@@ -2861,15 +2228,11 @@
  		int			thisleapi,
  					thisleapcnt,
  					thisleaplim;
@@ -2693,7 +2614,7 @@
  		int			old0;
  		char		omittype[TZ_MAX_TYPES];
  		int			typemap[TZ_MAX_TYPES];
-@@ -2883,15 +2260,28 @@
+@@ -2883,15 +2246,28 @@
  
  		if (pass == 1)
  		{
@@ -2701,7 +2622,7 @@
 +			/*
 +			 * 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
@@ -2709,7 +2630,7 @@
 +			 * 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);
 +
@@ -2721,12 +2642,12 @@
 -			thisleapexpiry = range32.leapexpiry;
 -			thismin = ZIC32_MIN;
 -			thismax = ZIC32_MAX;
-+			locut = PG_INT32_MIN < lo_time;
-+			hicut = hi_time < PG_INT32_MAX;
++			locut = INT32_MIN < lo_time;
++			hicut = hi_time < INT32_MAX;
  		}
  		else
  		{
-@@ -2901,52 +2291,40 @@
+@@ -2901,52 +2277,40 @@
  			toomanytimes = thistimecnt >> 31 >> 31 >> 2 != 0;
  			thisleapi = range64.leapbase;
  			thisleapcnt = range64.leapcount;
@@ -2801,7 +2722,7 @@
  
  		/*
  		 * Reorder types to make THISDEFAULTTYPE type 0. Use TYPEMAP to swap
-@@ -2972,14 +2350,7 @@
+@@ -2972,14 +2336,7 @@
  						type;
  
  			hidst = histd = mrudst = mrustd = -1;
@@ -2817,7 +2738,7 @@
  				if (isdsts[types[i]])
  					mrudst = types[i];
  				else
-@@ -3059,20 +2430,19 @@
+@@ -3059,20 +2416,19 @@
  		}
  		if (pass == 1 && !want_bloat())
  		{
@@ -2844,11 +2765,16 @@
  		convert(thistypecnt, tzh.tzh_typecnt);
  		convert(thischarcnt, tzh.tzh_charcnt);
  		DO(tzh_magic);
-@@ -3095,26 +2465,62 @@
- 			continue;
+@@ -3096,25 +2452,67 @@
  		}
  
-+		/* 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 */
@@ -2861,7 +2787,7 @@
 +
 +					fprintf(stdout, "%s\t" INT64_FORMAT "%s\n",
 +							thisabbrev,
-+							utoffs[tm],
++							(int64_t) utoffs[tm],
 +							isdsts[tm] ? "\tD" : "");
 +				}
 +			}
@@ -2873,17 +2799,16 @@
 +
 +				fprintf(stdout, "%s\t" INT64_FORMAT "%s\n",
 +						thisabbrev,
-+						utoffs[tm],
++						(int64_t) 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 < ZIC32_MIN ? ZIC32_MIN : lo_time;
-+		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 (0 <= pretranstype)
 +		if (locut)
@@ -2915,7 +2840,7 @@
  
  		for (i = old0; i < typecnt; i++)
  		{
-@@ -3131,7 +2537,6 @@
+@@ -3131,7 +2529,6 @@
  		if (thischarcnt != 0)
  			fwrite(thischars, sizeof thischars[0],
  				   thischarcnt, fp);
@@ -2923,7 +2848,7 @@
  		for (i = thisleapi; i < thisleaplim; ++i)
  		{
  			zic_t		todo;
-@@ -3163,17 +2568,6 @@
+@@ -3163,17 +2560,6 @@
  			puttzcodepass(todo, fp, pass);
  			puttzcode(corr[i], fp);
  		}
@@ -2941,7 +2866,7 @@
  		if (stdcnt != 0)
  			for (i = old0; i < typecnt; i++)
  				if (!omittype[i])
-@@ -3184,8 +2578,7 @@
+@@ -3184,8 +2570,7 @@
  					putc(ttisuts[i], fp);
  	}
  	fprintf(fp, "\n%s\n", string);
@@ -2951,7 +2876,7 @@
  	free(ats);
  }
  
-@@ -3233,15 +2626,13 @@
+@@ -3233,15 +2618,13 @@
  	}
  }
  
@@ -2969,7 +2894,7 @@
  	char const *format = zp->z_format;
  
  	slashp = strchr(format, '/');
-@@ -3253,8 +2644,6 @@
+@@ -3253,8 +2636,6 @@
  			letters = abbroffset(letterbuf, zp->z_stdoff + save);
  		else if (!letters)
  			letters = "%s";
@@ -2978,7 +2903,7 @@
  		sprintf(abbr, format, letters);
  	}
  	else if (isdst)
-@@ -3413,17 +2802,11 @@
+@@ -3413,17 +2794,11 @@
  		return 1;
  	if (a->r_hiyear != b->r_hiyear)
  		return a->r_hiyear < b->r_hiyear ? -1 : 1;
@@ -2996,7 +2921,7 @@
  static int
  stringzone(char *result, struct zone const *zpfirst, ptrdiff_t zonecount)
  {
-@@ -3432,17 +2815,13 @@
+@@ -3432,17 +2807,13 @@
  	struct rule *stdrp;
  	struct rule *dstrp;
  	ptrdiff_t	i;
@@ -3016,7 +2941,7 @@
  
  	result[0] = '\0';
  
-@@ -3454,74 +2833,72 @@
+@@ -3454,74 +2825,72 @@
  		return -1;
  
  	zp = zpfirst + zonecount - 1;
@@ -3146,7 +3071,7 @@
  	if (!offsetlen)
  	{
  		result[0] = '\0';
-@@ -3530,12 +2907,12 @@
+@@ -3530,12 +2899,12 @@
  	len += offsetlen;
  	if (dstrp == NULL)
  		return compat;
@@ -3161,7 +3086,7 @@
  		if (!offsetlen)
  		{
  			result[0] = '\0';
-@@ -3544,7 +2921,7 @@
+@@ -3544,7 +2913,7 @@
  		len += offsetlen;
  	}
  	result[len++] = ',';
@@ -3170,7 +3095,7 @@
  	if (c < 0)
  	{
  		result[0] = '\0';
-@@ -3554,7 +2931,7 @@
+@@ -3554,7 +2923,7 @@
  		compat = c;
  	len += strlen(result + len);
  	result[len++] = ',';
@@ -3179,7 +3104,7 @@
  	if (c < 0)
  	{
  		result[0] = '\0';
-@@ -3568,31 +2945,38 @@
+@@ -3568,31 +2937,38 @@
  static void
  outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
  {
@@ -3224,7 +3149,7 @@
  	startbuf = emalloc(max_abbr_len + 1);
  	ab = emalloc(max_abbr_len + 1);
  	envvar = emalloc(max_envvar_len + 1);
-@@ -3605,6 +2989,7 @@
+@@ -3605,6 +2981,7 @@
  	timecnt = 0;
  	typecnt = 0;
  	charcnt = 0;
@@ -3232,7 +3157,7 @@
  
  	/*
  	 * Thanks to Earl Chew for noting the need to unconditionally initialize
-@@ -3620,17 +3005,18 @@
+@@ -3620,17 +2997,18 @@
  	}
  	for (i = 0; i < zonecount; ++i)
  	{
@@ -3256,7 +3181,7 @@
  		}
  	}
  
-@@ -3638,14 +3024,13 @@
+@@ -3638,14 +3016,13 @@
  	 * Generate lots of data if a rule can't cover all future times.
  	 */
  	compat = stringzone(envvar, zpfirst, zonecount);
@@ -3273,7 +3198,7 @@
  					zpfirst->z_name);
  		else if (compat != 0)
  		{
-@@ -3660,6 +3045,22 @@
+@@ -3660,6 +3037,22 @@
  	}
  	if (do_extend)
  	{
@@ -3296,7 +3221,7 @@
  		if (min_year >= ZIC_MIN + years_of_observations)
  			min_year -= years_of_observations;
  		else
-@@ -3668,9 +3069,18 @@
+@@ -3668,9 +3061,18 @@
  			max_year += years_of_observations;
  		else
  			max_year = ZIC_MAX;
@@ -3317,7 +3242,7 @@
  	max_year0 = max_year;
  	if (want_bloat())
  	{
-@@ -3678,35 +3088,31 @@
+@@ -3678,35 +3080,31 @@
  		 * For the benefit of older systems, generate data from 1900 through
  		 * 2038.
  		 */
@@ -3366,7 +3291,7 @@
  			save = zp->z_save;
  			doabbr(startbuf, zp, NULL, zp->z_isdst, save, false);
  			type = addtype(oadd(zp->z_stdoff, save),
-@@ -3715,20 +3121,12 @@
+@@ -3715,20 +3113,12 @@
  			if (usestart)
  			{
  				addtt(starttime, type);
@@ -3387,7 +3312,7 @@
  			for (year = min_year; year <= max_year; ++year)
  			{
  				if (useuntil && year > zp->z_untilrule.r_hiyear)
-@@ -3741,12 +3139,9 @@
+@@ -3741,12 +3131,9 @@
  				 */
  				for (j = 0; j < zp->z_nrules; ++j)
  				{
@@ -3403,7 +3328,7 @@
  					rp->r_todo = year >= rp->r_loyear &&
  						year <= rp->r_hiyear;
  					if (rp->r_todo)
-@@ -3763,8 +3158,6 @@
+@@ -3763,8 +3150,6 @@
  					zic_t		jtime,
  								ktime;
  					zic_t		offset;
@@ -3412,7 +3337,7 @@
  
  					INITIALIZE(ktime);
  					if (useuntil)
-@@ -3789,16 +3182,15 @@
+@@ -3789,16 +3174,15 @@
  					k = -1;
  					for (j = 0; j < zp->z_nrules; ++j)
  					{
@@ -3436,7 +3361,7 @@
  						if (jtime == min_time ||
  							jtime == max_time)
  							continue;
-@@ -3813,12 +3205,12 @@
+@@ -3813,12 +3197,12 @@
  							char const *dup_rules_msg =
  								_("two rules for same instant");
  
@@ -3454,7 +3379,7 @@
  							error("%s", dup_rules_msg);
  						}
  					}
-@@ -3827,15 +3219,7 @@
+@@ -3827,15 +3211,7 @@
  					rp = &zp->z_rules[k];
  					rp->r_todo = false;
  					if (useuntil && ktime >= untiltime)
@@ -3470,7 +3395,7 @@
  					save = rp->r_save;
  					if (usestart && ktime == starttime)
  						usestart = false;
-@@ -3864,41 +3248,44 @@
+@@ -3864,41 +3240,44 @@
  								   false);
  						}
  					}
@@ -3534,7 +3459,7 @@
  				if (defaulttype < 0 && !isdst)
  					defaulttype = type;
  				addtt(starttime, type);
-@@ -3921,50 +3308,17 @@
+@@ -3921,50 +3300,17 @@
  	}
  	if (defaulttype < 0)
  		defaulttype = 0;
@@ -3592,7 +3517,7 @@
  		 * transitions up to that point.
  		 */
  		struct rule xr;
-@@ -4055,11 +3409,6 @@
+@@ -4055,11 +3401,6 @@
  		error(_("too many leap seconds"));
  		exit(EXIT_FAILURE);
  	}
@@ -3604,7 +3529,7 @@
  	for (i = 0; i < leapcnt; ++i)
  		if (t <= trans[i])
  			break;
-@@ -4094,6 +3443,13 @@
+@@ -4094,6 +3435,13 @@
  		last = corr[i] += last;
  	}
  
@@ -3618,7 +3543,7 @@
  	if (0 <= leapexpires)
  	{
  		leapexpires = oadd(leapexpires, last);
-@@ -4102,6 +3458,8 @@
+@@ -4102,6 +3450,8 @@
  			error(_("last Leap time does not precede Expires time"));
  			exit(EXIT_FAILURE);
  		}
@@ -3627,7 +3552,7 @@
  	}
  }
  
-@@ -4252,7 +3610,7 @@
+@@ -4252,7 +3602,7 @@
  }
  
  /* case-insensitive equality */
@@ -3636,7 +3561,7 @@
  ciequal(const char *ap, const char *bp)
  {
  	while (lowerit(*ap) == lowerit(*bp++))
-@@ -4261,7 +3619,7 @@
+@@ -4261,7 +3611,7 @@
  	return false;
  }
  
@@ -3645,7 +3570,7 @@
  itsabbr(const char *abbr, const char *word)
  {
  	if (lowerit(*abbr) != lowerit(*word))
-@@ -4278,7 +3636,7 @@
+@@ -4278,7 +3628,7 @@
  
  /* Return true if ABBR is an initial prefix of WORD, ignoring ASCII case.  */
  
@@ -3654,7 +3579,7 @@
  ciprefix(char const *abbr, char const *word)
  {
  	do
-@@ -4355,22 +3713,24 @@
+@@ -4355,22 +3705,24 @@
  	return foundlp;
  }
  
@@ -3684,7 +3609,7 @@
  		do
  		{
  			if ((*dp = *cp++) != '"')
-@@ -4388,53 +3748,48 @@
+@@ -4388,53 +3740,48 @@
  		if (is_space(*cp))
  			++cp;
  		*dp = '\0';
@@ -3765,7 +3690,7 @@
  }
  
  /*
-@@ -4450,31 +3805,39 @@
+@@ -4450,31 +3797,39 @@
  	zic_t		dayoff;			/* with a nod to Margaret O. */
  	zic_t		t,
  				y;
@@ -3820,7 +3745,7 @@
  	}
  	while (m != rp->r_month)
  	{
-@@ -4497,17 +3860,27 @@
+@@ -4497,17 +3852,27 @@
  	dayoff = oadd(dayoff, i);
  	if (rp->r_dycode == DC_DOWGEQ || rp->r_dycode == DC_DOWLEQ)
  	{
@@ -3852,7 +3777,7 @@
  					wday = 0;
  				++i;
  			}
-@@ -4515,7 +3888,7 @@
+@@ -4515,7 +3880,7 @@
  			{
  				dayoff = oadd(dayoff, -1);
  				if (--wday < 0)
@@ -3861,7 +3786,7 @@
  				--i;
  			}
  		if (i < 0 || i >= len_months[isleap(y)][m])
-@@ -4570,13 +3943,15 @@
+@@ -4570,13 +3935,15 @@
  /* Ensure that the directories of ARGNAME exist, by making any missing
     ones.  If ANCESTORS, do this only for ARGNAME's ancestors; otherwise,
     do it for ARGNAME too.  Exit with failure if there is trouble.
@@ -3880,7 +3805,7 @@
  	/*
  	 * On MS-Windows systems, do not worry about drive letters or backslashes,
  	 * as this should suffice in practice.  Time zone names do not use drive
-@@ -4603,20 +3978,15 @@
+@@ -4603,20 +3970,15 @@
  		if (mkdir(name, MKDIR_UMASK) != 0)
  		{
  			/*
@@ -3906,7 +3831,7 @@
  					  progname, name, strerror(err));
  				exit(EXIT_FAILURE);
  			}
-@@ -4626,3 +3996,20 @@
+@@ -4626,3 +3988,20 @@
  	}
  	free(name);
  }
--- localtime.c-master-vs-upstream.diff	2024-07-04 14:38:31.386232000 +1200
+++ localtime.c-patched-vs-upstream.diff	2024-07-04 14:37:46.783150000 +1200
@@ -1,6 +1,6 @@
 --- localtime.filtered.c	2024-07-04 13:04:23.744118000 +1200
-+++ localtime.c	2024-07-04 14:38:19.086065000 +1200
-@@ -3,64 +3,28 @@
++++ localtime.c	2024-07-04 14:17:36.438049000 +1200
+@@ -3,64 +3,29 @@
  /*
   * This file is in the public domain, so clarified as of
   * 1996-06-05 by Arthur David Olson.
@@ -25,6 +25,7 @@
 -#include "tzdir.h"
 -#include "tzfile.h"
  #include <fcntl.h>
++#include <stdint.h>
  
 -#if defined THREAD_SAFE && THREAD_SAFE
 -#include <pthread.h>
@@ -75,7 +76,7 @@
  #ifndef WILDABBR
  /*
   * Someone might make incorrect use of a time zone abbreviation:
-@@ -72,7 +36,7 @@
+@@ -72,7 +37,7 @@
   *		in which Daylight Saving Time is never observed.
   *	4.	They might reference tzname[0] after setting to a time zone
   *		in which Standard Time is never observed.
@@ -84,7 +85,7 @@
   * What's best to do in the above cases is open to debate;
   * for now, we just set things up so that in any of the five cases
   * WILDABBR is used. Another possibility: initialize tzname[0] to the
-@@ -81,89 +45,28 @@
+@@ -81,89 +46,28 @@
   * manual page of what this "time zone abbreviation" means (doing this so
   * that tzname[0] has the "normal" length of three characters).
   */
@@ -179,12 +180,8 @@
  };
  
  struct rule
-@@ -172,70 +75,37 @@
- 	int			r_day;			/* day number of rule */
- 	int			r_week;			/* week number of rule */
- 	int			r_mon;			/* month number of rule */
--	int_fast32_t r_time;		/* transition time of rule */
-+	int32		r_time;			/* transition time of rule */
+@@ -175,64 +79,31 @@
+ 	int_fast32_t r_time;		/* transition time of rule */
  };
  
 -static struct pg_tm *gmtsub(struct state const *, pg_time_t const *, int_fast32_t,
@@ -204,13 +201,13 @@
 -static struct state *lclptr;
 -static struct state *gmtptr;
 -#endif							/* defined ALL_STATE */
-+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);
  
@@ -259,12 +256,8 @@
 -
  /* Initialize *S to a value based on UTOFF, ISDST, and DESIGIDX.  */
  static void
--init_ttinfo(struct ttinfo *s, int_fast32_t utoff, bool isdst, int desigidx)
-+init_ttinfo(struct ttinfo *s, int32 utoff, bool isdst, int desigidx)
- {
- 	s->tt_utoff = utoff;
- 	s->tt_isdst = isdst;
-@@ -244,25 +114,15 @@
+ init_ttinfo(struct ttinfo *s, int_fast32_t utoff, bool isdst, int desigidx)
+@@ -244,16 +115,6 @@
  	s->tt_ttisut = false;
  }
  
@@ -278,64 +271,13 @@
 -	return memcmp(abbr, UNSPEC, sizeof UNSPEC) == 0;
 -}
 -
--static int_fast32_t
-+static int32
+ static int_fast32_t
  detzcode(const char *const codep)
  {
--	int_fast32_t result;
-+	int32		result;
- 	int			i;
--	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;
-+	int32		one = 1;
-+	int32		halfmaxval = one << (32 - 2);
-+	int32		maxval = halfmaxval - 1 + halfmaxval;
-+	int32		minval = -1 - maxval;
- 
- 	result = codep[0] & 0x7f;
- 	for (i = 1; i < 4; ++i)
-@@ -274,21 +134,21 @@
- 		 * Do two's-complement negation even on non-two's-complement machines.
- 		 * If the result would be minval - 1, return minval.
- 		 */
--		result -= !TWOS_COMPLEMENT(int_fast32_t) && result != 0;
-+		result -= !TWOS_COMPLEMENT(int32) && result != 0;
- 		result += minval;
- 	}
+@@ -306,125 +167,25 @@
  	return result;
  }
  
--static int_fast64_t
-+static int64
- detzcode64(const char *const codep)
- {
--	int_fast64_t result;
-+	uint64		result;
- 	int			i;
--	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;
-+	int64		one = 1;
-+	int64		halfmaxval = one << (64 - 2);
-+	int64		maxval = halfmaxval - 1 + halfmaxval;
-+	int64		minval = -TWOS_COMPLEMENT(int64) - maxval;
- 
- 	result = codep[0] & 0x7f;
- 	for (i = 1; i < 8; ++i)
-@@ -300,131 +160,31 @@
- 		 * Do two's-complement negation even on non-two's-complement machines.
- 		 * If the result would be minval - 1, return minval.
- 		 */
--		result -= !TWOS_COMPLEMENT(int_fast64_t) && result != 0;
-+		result -= !TWOS_COMPLEMENT(int64) && result != 0;
- 		result += minval;
- 	}
- 	return result;
- }
- 
 -static void
 -update_tzname_etc(struct state const *sp, struct ttinfo const *ttisp)
 +static bool
@@ -464,7 +406,7 @@
  /* Local storage needed for 'tzloadbody'.  */
  union local_storage
  {
-@@ -438,28 +198,23 @@
+@@ -438,28 +199,23 @@
  		struct state st;
  	}			u;
  
@@ -500,7 +442,7 @@
  	union input_buffer *up = &lsp->u.u;
  	int			tzheadsize = sizeof(struct tzhead);
  
-@@ -474,50 +229,10 @@
+@@ -474,50 +230,10 @@
  
  	if (name[0] == ':')
  		++name;
@@ -553,33 +495,23 @@
  
  	nread = read(fid, up->buf, sizeof up->buf);
  	if (nread < tzheadsize)
-@@ -531,17 +246,14 @@
+@@ -531,13 +247,10 @@
  		return errno;
  	for (stored = 4; stored <= 8; stored *= 2)
  	{
 -		char		version = up->tzhead.tzh_version[0];
 -		bool		skip_datablock = stored == 4 && version;
 -		int_fast32_t datablock_size;
--		int_fast32_t ttisstdcnt = detzcode(up->tzhead.tzh_ttisstdcnt);
--		int_fast32_t ttisutcnt = detzcode(up->tzhead.tzh_ttisutcnt);
+ 		int_fast32_t ttisstdcnt = detzcode(up->tzhead.tzh_ttisstdcnt);
+ 		int_fast32_t ttisutcnt = detzcode(up->tzhead.tzh_ttisutcnt);
 -		int_fast64_t prevtr = -1;
 -		int_fast32_t prevcorr;
--		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);
-+		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);
- 		char const *p = up->buf + tzheadsize;
- 
- 		/*
-@@ -553,177 +265,152 @@
++		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);
+@@ -553,177 +266,152 @@
  			  && 0 <= typecnt && typecnt < TZ_MAX_TYPES
  			  && 0 <= timecnt && timecnt < TZ_MAX_TIMES
  			  && 0 <= charcnt && charcnt < TZ_MAX_CHARS
@@ -743,8 +675,8 @@
 +		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);
  
 -			/* Read leap seconds, discarding those out of pg_time_t range.  */
 -			leapcnt = 0;
@@ -764,7 +696,7 @@
 -				 * Leap seconds cannot occur before the Epoch, or out of
 -				 * order.
 +				 * 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.
  				 */
@@ -870,7 +802,7 @@
  	}
  	if (doextend && nread > 2 &&
  		up->buf[0] == '\n' && up->buf[nread - 1] == '\n' &&
-@@ -732,9 +419,8 @@
+@@ -732,9 +420,8 @@
  		struct state *ts = &lsp->u.st;
  
  		up->buf[nread - 1] = '\0';
@@ -881,7 +813,7 @@
  			/*
  			 * Attempt to reuse existing abbreviations. Without this,
  			 * America/Anchorage would be right on the edge after 2037 when
-@@ -785,25 +471,20 @@
+@@ -785,25 +472,20 @@
  						   == sp->types[sp->timecnt - 2]))
  					sp->timecnt--;
  
@@ -916,7 +848,7 @@
  				}
  				for (i = 0; i < ts->typecnt; i++)
  					sp->ttis[sp->typecnt++] = ts->ttis[i];
-@@ -812,6 +493,25 @@
+@@ -812,6 +494,25 @@
  	}
  	if (sp->typecnt == 0)
  		return EINVAL;
@@ -942,7 +874,7 @@
  
  	/*
  	 * Infer sp->defaulttype from the data.  Although this default type is
-@@ -826,13 +526,13 @@
+@@ -826,13 +527,13 @@
  	 */
  
  	/*
@@ -959,7 +891,7 @@
  
  	/*
  	 * Absent the above, if there are transition times and the first
-@@ -878,29 +578,49 @@
+@@ -878,29 +579,49 @@
  }
  
  /* Load tz data from the file named NAME into *SP.  Read extended
@@ -1021,7 +953,7 @@
  }
  
  static const int mon_lengths[2][MONSPERYEAR] = {
-@@ -912,20 +632,13 @@
+@@ -912,20 +633,13 @@
  	DAYSPERNYEAR, DAYSPERLYEAR
  };
  
@@ -1043,7 +975,7 @@
  getzname(const char *strp)
  {
  	char		c;
-@@ -946,7 +659,7 @@
+@@ -946,7 +660,7 @@
   * We don't do any checking here; checking is done later in common-case code.
   */
  
@@ -1052,16 +984,9 @@
  getqzname(const char *strp, const int delim)
  {
  	int			c;
-@@ -994,20 +707,19 @@
-  */
+@@ -1000,8 +714,8 @@
+ 	int_fast32_t secsperhour = SECSPERHOUR;
  
- static const char *
--getsecs(const char *strp, int_fast32_t * const secsp)
-+getsecs(const char *strp, int32 *const secsp)
- {
- 	int			num;
--	int_fast32_t secsperhour = SECSPERHOUR;
- 
  	/*
 -	 * 'HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-POSIX rules like
 -	 * "M10.4.6/26", which does not conform to POSIX, but which specifies the
@@ -1070,24 +995,8 @@
  	 * equivalent of "02:00 on the first Sunday on or after 23 Oct".
  	 */
  	strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
- 	if (strp == NULL)
- 		return NULL;
--	*secsp = num * secsperhour;
-+	*secsp = num * (int32) SECSPERHOUR;
- 	if (*strp == ':')
- 	{
- 		++strp;
-@@ -1036,7 +748,7 @@
-  */
+@@ -1057,8 +771,7 @@
  
- static const char *
--getoffset(const char *strp, int_fast32_t * const offsetp)
-+getoffset(const char *strp, int32 *const offsetp)
- {
- 	bool		neg = false;
- 
-@@ -1057,8 +769,7 @@
- 
  /*
   * Given a pointer into a timezone string, extract a rule in the form
 - * date[/time]. See POSIX Base Definitions section 8.3 variable TZ
@@ -1096,23 +1005,7 @@
   * If a valid rule is not found, return NULL.
   * Otherwise, return a pointer to the first character not part of the rule.
   */
-@@ -1124,12 +835,12 @@
-  * effect, calculate the year-relative time that rule takes effect.
-  */
- 
--static int_fast32_t
-+static int32
- transtime(const int year, const struct rule *const rulep,
--		  const int_fast32_t offset)
-+		  const int32 offset)
- {
- 	bool		leapyear;
--	int_fast32_t value;
-+	int32		value;
- 	int			i;
- 	int			d,
- 				m1,
-@@ -1138,6 +849,7 @@
+@@ -1138,6 +851,7 @@
  				yy2,
  				dow;
  
@@ -1120,7 +1013,7 @@
  	leapyear = isleap(year);
  	switch (rulep->r_type)
  	{
-@@ -1193,7 +905,7 @@
+@@ -1193,7 +907,7 @@
  			for (i = 1; i < rulep->r_week; ++i)
  			{
  				if (d + DAYSPERWEEK >=
@@ -1129,7 +1022,7 @@
  					break;
  				d += DAYSPERWEEK;
  			}
-@@ -1203,11 +915,8 @@
+@@ -1203,11 +917,8 @@
  			 */
  			value = d * SECSPERDAY;
  			for (i = 0; i < rulep->r_mon - 1; ++i)
@@ -1142,7 +1035,7 @@
  	}
  
  	/*
-@@ -1219,64 +928,71 @@
+@@ -1219,64 +930,71 @@
  }
  
  /*
@@ -1159,14 +1052,12 @@
  {
  	const char *stdname;
 -	const char *dstname;
--	int_fast32_t stdoffset;
--	int_fast32_t dstoffset;
 +	const char *dstname = NULL;
 +	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;
 -	ptrdiff_t	stdlen,
@@ -1258,7 +1149,7 @@
  	if (*name != '\0')
  	{
  		if (*name == '<')
-@@ -1294,9 +1010,11 @@
+@@ -1294,9 +1012,11 @@
  			name = getzname(name);
  			dstlen = name - dstname;	/* length of DST abbr. */
  		}
@@ -1271,22 +1162,21 @@
  		if (*name != '\0' && *name != ',' && *name != ';')
  		{
  			name = getoffset(name, &dstoffset);
-@@ -1312,11 +1030,11 @@
+@@ -1312,11 +1032,11 @@
  			struct rule start;
  			struct rule end;
  			int			year;
 +			int			yearlim;
  			int			timecnt;
  			pg_time_t	janfirst;
--			int_fast32_t janoffset = 0;
+ 			int_fast32_t janoffset = 0;
 -			int			yearbeg,
 -						yearlim;
-+			int32		janoffset = 0;
 +			int			yearbeg;
  
  			++name;
  			if ((name = getrule(name, &start)) == NULL)
-@@ -1334,13 +1052,14 @@
+@@ -1334,6 +1054,7 @@
  			 */
  			init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
  			init_ttinfo(&sp->ttis[1], -dstoffset, true, stdlen + 1);
@@ -1294,15 +1184,7 @@
  			timecnt = 0;
  			janfirst = 0;
  			yearbeg = EPOCH_YEAR;
- 
- 			do
- 			{
--				int_fast32_t yearsecs
-+				int32		yearsecs
- 				= year_lengths[isleap(yearbeg - 1)] * SECSPERDAY;
- 
- 				yearbeg--;
-@@ -1349,72 +1068,48 @@
+@@ -1349,27 +1070,9 @@
  					janoffset = -yearsecs;
  					break;
  				}
@@ -1331,27 +1213,8 @@
 +			yearlim = yearbeg + YEARSPERREPEAT + 1;
  			for (year = yearbeg; year < yearlim; year++)
  			{
--				int_fast32_t
--					starttime = transtime(year, &start, stdoffset),
--					endtime = transtime(year, &end, dstoffset);
--				int_fast32_t
--					yearsecs = (year_lengths[isleap(year)]
--								* SECSPERDAY);
-+				int32
-+							starttime = transtime(year, &start, stdoffset),
-+							endtime = transtime(year, &end, dstoffset);
-+				int32
-+							yearsecs = (year_lengths[isleap(year)]
-+										* SECSPERDAY);
- 				bool		reversed = endtime < starttime;
- 
- 				if (reversed)
- 				{
--					int_fast32_t swap = starttime;
-+					int32		swap = starttime;
- 
- 					starttime = endtime;
- 					endtime = swap;
+ 				int_fast32_t
+@@ -1389,32 +1092,26 @@
  				}
  				if (reversed
  					|| (starttime < endtime
@@ -1390,7 +1253,7 @@
  				if (increment_overflow_time
  					(&janfirst, janoffset + yearsecs))
  					break;
-@@ -1426,14 +1121,14 @@
+@@ -1426,7 +1123,7 @@
  				sp->ttis[0] = sp->ttis[1];
  				sp->typecnt = 1;	/* Perpetual DST.  */
  			}
@@ -1399,17 +1262,7 @@
  				sp->goback = sp->goahead = true;
  		}
  		else
- 		{
--			int_fast32_t theirstdoffset;
--			int_fast32_t theirdstoffset;
--			int_fast32_t theiroffset;
-+			int32		theirstdoffset;
-+			int32		theirdstoffset;
-+			int32		theiroffset;
- 			bool		isdst;
- 			int			i;
- 			int			j;
-@@ -1471,6 +1166,7 @@
+@@ -1471,6 +1168,7 @@
  			 * Initially we're assumed to be in standard time.
  			 */
  			isdst = false;
@@ -1417,7 +1270,7 @@
  
  			/*
  			 * Now juggle transition times and types tracking offsets as you
-@@ -1495,7 +1191,7 @@
+@@ -1495,7 +1193,7 @@
  					 */
  					/*
  					 * Transitions from DST to DDST will effectively disappear
@@ -1426,7 +1279,7 @@
  					 */
  					if (isdst && !sp->ttis[j].tt_ttisstd)
  					{
-@@ -1521,6 +1217,7 @@
+@@ -1521,6 +1219,7 @@
  			init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
  			init_ttinfo(&sp->ttis[1], -dstoffset, true, stdlen + 1);
  			sp->typecnt = 2;
@@ -1434,7 +1287,7 @@
  		}
  	}
  	else
-@@ -1529,8 +1226,8 @@
+@@ -1529,8 +1228,8 @@
  		sp->typecnt = 1;		/* only standard time */
  		sp->timecnt = 0;
  		init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
@@ -1444,7 +1297,7 @@
  	sp->charcnt = charcnt;
  	cp = sp->chars;
  	memcpy(cp, stdname, stdlen);
-@@ -1547,155 +1244,19 @@
+@@ -1547,155 +1246,19 @@
  static void
  gmtload(struct state *const sp)
  {
@@ -1603,7 +1456,7 @@
  		 struct pg_tm *const tmp)
  {
  	const struct ttinfo *ttisp;
-@@ -1704,14 +1265,11 @@
+@@ -1704,14 +1267,11 @@
  	const pg_time_t t = *timep;
  
  	if (sp == NULL)
@@ -1620,7 +1473,7 @@
  		pg_time_t	seconds;
  		pg_time_t	years;
  
-@@ -1720,34 +1278,19 @@
+@@ -1720,33 +1280,18 @@
  		else
  			seconds = t - sp->ats[sp->timecnt - 1];
  		--seconds;
@@ -1655,12 +1508,10 @@
 -						  result->tm_year, years))
 -				return NULL;
 -#else
--			int_fast64_t newy;
-+			int64		newy;
+ 			int_fast64_t newy;
  
  			newy = result->tm_year;
- 			if (t < sp->ats[0])
-@@ -1757,7 +1300,6 @@
+@@ -1757,7 +1302,6 @@
  			if (!(INT_MIN <= newy && newy <= INT_MAX))
  				return NULL;
  			result->tm_year = newy;
@@ -1668,7 +1519,7 @@
  		}
  		return result;
  	}
-@@ -1779,7 +1321,7 @@
+@@ -1779,7 +1323,7 @@
  			else
  				lo = mid + 1;
  		}
@@ -1677,7 +1528,7 @@
  	}
  	ttisp = &sp->ttis[i];
  
-@@ -1792,132 +1334,76 @@
+@@ -1792,132 +1336,76 @@
  	if (result)
  	{
  		result->tm_isdst = ttisp->tt_isdst;
@@ -1745,7 +1596,7 @@
  static struct pg_tm *
 -gmtsub(ATTRIBUTE_MAYBE_UNUSED struct state const *sp, pg_time_t const *timep,
 -	   int_fast32_t offset, struct pg_tm *tmp)
-+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;
@@ -1840,13 +1691,7 @@
  {
  	return (y < 0
  			? -1 - leaps_thru_end_of_nonneg(-1 - y)
-@@ -1925,28 +1411,21 @@
- }
- 
- static struct pg_tm *
--timesub(const pg_time_t *timep, int_fast32_t offset,
-+timesub(const pg_time_t *timep, int32 offset,
- 		const struct state *sp, struct pg_tm *tmp)
+@@ -1930,23 +1418,16 @@
  {
  	const struct lsinfo *lp;
  	pg_time_t	tdays;
@@ -1876,7 +1721,7 @@
  	i = (sp == NULL) ? 0 : sp->leapcnt;
  	while (--i >= 0)
  	{
-@@ -1954,175 +1433,134 @@
+@@ -1954,175 +1435,134 @@
  		if (*timep >= lp->ls_trans)
  		{
  			corr = lp->ls_corr;
@@ -2092,8 +1937,7 @@
  
  static bool
 -increment_overflow32(int_fast32_t * const lp, int const m)
-+increment_overflow_time(pg_time_t *tp, int32 j)
- {
+-{
 -#ifdef ckd_add
 -	return ckd_add(lp, *lp, m);
 -#else
@@ -2107,8 +1951,8 @@
 -}
 -
 -static bool
--increment_overflow_time(pg_time_t *tp, int_fast32_t j)
--{
+ increment_overflow_time(pg_time_t *tp, int_fast32_t j)
+ {
 -#ifdef ckd_add
 -	return ckd_add(tp, *tp, j);
 -#else
@@ -2124,7 +1968,7 @@
  	 */
  	if (!(j < 0
  		  ? (TYPE_SIGNED(pg_time_t) ? TIME_T_MIN - j <= *tp : -1 - j < *tp)
-@@ -2130,637 +1568,339 @@
+@@ -2130,637 +1570,339 @@
  		return true;
  	*tp += j;
  	return false;
v3-0001-Use-int64_t-support-from-stdint.h.patchtext/x-patch; charset=US-ASCII; name=v3-0001-Use-int64_t-support-from-stdint.h.patchDownload
From eb323ba495a302540945bcb9c6527bdcce87d9a2 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Thu, 18 Apr 2024 07:53:10 +1200
Subject: [PATCH v3 1/3] Use int64_t support from <stdint.h>.

Remove most of the configure probes for 64 bit integers.  Map our names
to the standard C99 names for types like int64_t, limits like INT64_MAX,
constant constructors like INT64_C().

Unfortunately we can't use standard printf format macros like PRId64
from <inttypes.h>, because we have our own snprintf.c implementation.
It does not understand Windows' PRId64 macro, for example.  Selecting
between "l" and "ll" by size alone is trivial, but we still some
configure-time help to work out which one will compile warning-free when
both are candidates, on systems that support printf format string type
checking.

We can get rid of pg_config_ext.h, which existed only to define
PG_INT64_TYPE for client interfaces, which is now redundant.

Reviewed-by: Peter Eisentraut <peter@eisentraut.org>
Reviewed-by: Heikki Linnakangas <hlinnaka@iki.fi>
Reviewed-by: Japin Li <japinli@hotmail.com>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us> (the idea, not the patch)
Discussion: https://postgr.es/m/ME3P282MB3166F9D1F71F787929C0C7E7B6312%40ME3P282MB3166.AUSP282.PROD.OUTLOOK.COM
---
 config/c-compiler.m4                          | 111 +++---
 configure                                     | 377 ++++++------------
 configure.ac                                  |  54 +--
 meson.build                                   |  63 +--
 src/Makefile.global.in                        |   6 -
 src/include/.gitignore                        |   2 -
 src/include/Makefile                          |   8 +-
 src/include/c.h                               |  78 ++--
 src/include/meson.build                       |  10 -
 src/include/pg_config.h.in                    |  17 +-
 src/include/pg_config_ext.h.in                |   7 -
 src/include/pg_config_ext.h.meson             |   7 -
 src/include/port/pg_bitutils.h                |  18 +-
 src/include/postgres_ext.h                    |   7 +-
 src/interfaces/ecpg/ecpglib/typename.c        |   5 +-
 src/interfaces/ecpg/include/ecpg_config.h.in  |   9 -
 src/interfaces/ecpg/include/meson.build       |   3 -
 .../ecpg/include/pgtypes_interval.h           |  13 +-
 src/interfaces/ecpg/include/sqltypes.h        |   2 +-
 .../test/expected/compat_informix-sqlda.c     |   2 +-
 src/port/pg_bitutils.c                        |   7 +-
 src/port/snprintf.c                           |  14 +-
 22 files changed, 268 insertions(+), 552 deletions(-)
 delete mode 100644 src/include/pg_config_ext.h.in
 delete mode 100644 src/include/pg_config_ext.h.meson

diff --git a/config/c-compiler.m4 b/config/c-compiler.m4
index 10f8c7bd0a9..b3fdf1b8c48 100644
--- a/config/c-compiler.m4
+++ b/config/c-compiler.m4
@@ -38,58 +38,41 @@ ac_c_werror_flag=$ac_save_c_werror_flag
 ])# PGAC_TEST_PRINTF_ARCHETYPE
 
 
-# PGAC_TYPE_64BIT_INT(TYPE)
-# -------------------------
-# Check if TYPE is a working 64 bit integer type. Set HAVE_TYPE_64 to
-# yes or no respectively, and define HAVE_TYPE_64 if yes.
-AC_DEFUN([PGAC_TYPE_64BIT_INT],
-[define([Ac_define], [translit([have_$1_64], [a-z *], [A-Z_P])])dnl
-define([Ac_cachevar], [translit([pgac_cv_type_$1_64], [ *], [_p])])dnl
-AC_CACHE_CHECK([whether $1 is 64 bits], [Ac_cachevar],
-[AC_RUN_IFELSE([AC_LANG_SOURCE(
-[typedef $1 ac_int64;
-
-/*
- * These are globals to discourage the compiler from folding all the
- * arithmetic tests down to compile-time constants.
- */
-ac_int64 a = 20000001;
-ac_int64 b = 40000005;
-
-int does_int64_work()
-{
-  ac_int64 c,d;
-
-  if (sizeof(ac_int64) != 8)
-    return 0;			/* definitely not the right size */
-
-  /* Do perfunctory checks to see if 64-bit arithmetic seems to work */
-  c = a * b;
-  d = (c + b) / b;
-  if (d != a+1)
-    return 0;
-  return 1;
-}
-
-int
-main() {
-  return (! does_int64_work());
-}])],
-[Ac_cachevar=yes],
-[Ac_cachevar=no],
-[# If cross-compiling, check the size reported by the compiler and
-# trust that the arithmetic works.
-AC_COMPILE_IFELSE([AC_LANG_BOOL_COMPILE_TRY([], [sizeof($1) == 8])],
-                  Ac_cachevar=yes,
-                  Ac_cachevar=no)])])
-
-Ac_define=$Ac_cachevar
-if test x"$Ac_cachevar" = xyes ; then
-  AC_DEFINE(Ac_define, 1, [Define to 1 if `]$1[' works and is 64 bits.])
+# PGAC_PRINTF_INT64_MODIFIER
+# --------------------------
+# Determine which printf format modifier to use for int64_t values, to avoid
+# warnings from the format string checker (if there is one).
+AC_DEFUN([PGAC_PRINTF_INT64_MODIFIER],
+[AC_CACHE_CHECK([for printf int64_t modifier], pgac_cv_int64_modifier,
+[
+ac_save_c_werror_flag=$ac_c_werror_flag
+ac_c_werror_flag=yes
+if test "$ac_cv_sizeof_long" -lt 8; then
+  # long isn't wide enough, so use "ll"
+  pgac_cv_int64_modifier='"ll"'
+else
+  AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
+[#include <stdint.h>],
+[extern void emit_log(int ignore, const char *fmt,...) __attribute__((format(printf,2,3)));
+ void
+ f()
+ {
+     emit_log(0, "%lld", (int64_t) 42);
+ }])],
+  # this system understands the attribute, and accepted "ll" without
+  # warning, so go with that (example: macOS)
+  [pgac_cv_int64_modifier='"ll"'],
+  # either this system doesn't understand the attribute at all (and
+  # "l" should be fine because now we only care about getting the
+  # right size), or it rejected "ll" with warnings because it expected
+  # "l" (example: FreeBSD)
+  [pgac_cv_int64_modifier='"l"'])
 fi
-undefine([Ac_define])dnl
-undefine([Ac_cachevar])dnl
-])# PGAC_TYPE_64BIT_INT
+ac_c_werror_flag=$ac_save_c_werror_flag
+])
+AC_DEFINE_UNQUOTED([INT64_MODIFIER], [$pgac_cv_int64_modifier],
+[Define to printf format modifier to use for int64_t.])
+])# PGAC_PRINTF_INT64_MODIFIER
 
 
 # PGAC_TYPE_128BIT_INT
@@ -269,10 +252,11 @@ fi])# PGAC_C_BUILTIN_CONSTANT_P
 # optimize away the call.
 AC_DEFUN([PGAC_C_BUILTIN_OP_OVERFLOW],
 [AC_CACHE_CHECK(for __builtin_mul_overflow, pgac_cv__builtin_op_overflow,
-[AC_LINK_IFELSE([AC_LANG_PROGRAM([
-PG_INT64_TYPE a = 1;
-PG_INT64_TYPE b = 1;
-PG_INT64_TYPE result;
+[AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <stdint.h>],
+[
+int64_t a = 1;
+int64_t b = 1;
+int64_t result;
 int oflo;
 ],
 [oflo = __builtin_mul_overflow(a, b, &result);])],
@@ -557,9 +541,9 @@ fi])# PGAC_HAVE_GCC__SYNC_INT32_CAS
 # types, and define HAVE_GCC__SYNC_INT64_CAS if so.
 AC_DEFUN([PGAC_HAVE_GCC__SYNC_INT64_CAS],
 [AC_CACHE_CHECK(for builtin __sync int64 atomic operations, pgac_cv_gcc_sync_int64_cas,
-[AC_LINK_IFELSE([AC_LANG_PROGRAM([],
-  [PG_INT64_TYPE lock = 0;
-   __sync_val_compare_and_swap(&lock, 0, (PG_INT64_TYPE) 37);])],
+[AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <stdint.h>],
+  [int64_t lock = 0;
+   __sync_val_compare_and_swap(&lock, 0, (int64_t) 37);])],
   [pgac_cv_gcc_sync_int64_cas="yes"],
   [pgac_cv_gcc_sync_int64_cas="no"])])
 if test x"$pgac_cv_gcc_sync_int64_cas" = x"yes"; then
@@ -588,9 +572,9 @@ fi])# PGAC_HAVE_GCC__ATOMIC_INT32_CAS
 # types, and define HAVE_GCC__ATOMIC_INT64_CAS if so.
 AC_DEFUN([PGAC_HAVE_GCC__ATOMIC_INT64_CAS],
 [AC_CACHE_CHECK(for builtin __atomic int64 atomic operations, pgac_cv_gcc_atomic_int64_cas,
-[AC_LINK_IFELSE([AC_LANG_PROGRAM([],
-  [PG_INT64_TYPE val = 0;
-   PG_INT64_TYPE expect = 0;
+[AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <stdint.h>],
+  [int64_t val = 0;
+   int64_t expect = 0;
    __atomic_compare_exchange_n(&val, &expect, 37, 0, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);])],
   [pgac_cv_gcc_atomic_int64_cas="yes"],
   [pgac_cv_gcc_atomic_int64_cas="no"])])
@@ -733,9 +717,10 @@ AC_DEFUN([PGAC_AVX512_POPCNT_INTRINSICS],
 AC_CACHE_CHECK([for _mm512_popcnt_epi64 with CFLAGS=$1], [Ac_cachevar],
 [pgac_save_CFLAGS=$CFLAGS
 CFLAGS="$pgac_save_CFLAGS $1"
-AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <immintrin.h>],
+AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <immintrin.h>
+                                 #include <stdint.h>],
   [const char buf@<:@sizeof(__m512i)@:>@;
-   PG_INT64_TYPE popcnt = 0;
+   int64_t popcnt = 0;
    __m512i accum = _mm512_setzero_si512();
    const __m512i val = _mm512_maskz_loadu_epi8((__mmask64) 0xf0f0f0f0f0f0f0f0, (const __m512i *) buf);
    const __m512i cnt = _mm512_popcnt_epi64(val);
diff --git a/configure b/configure
index 76f06bd8fda..cfec577a1c1 100755
--- a/configure
+++ b/configure
@@ -14546,6 +14546,42 @@ if test x"$pgac_cv__builtin_constant_p" = xyes ; then
 
 $as_echo "#define HAVE__BUILTIN_CONSTANT_P 1" >>confdefs.h
 
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_mul_overflow" >&5
+$as_echo_n "checking for __builtin_mul_overflow... " >&6; }
+if ${pgac_cv__builtin_op_overflow+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdint.h>
+int
+main ()
+{
+
+int64_t a = 1;
+int64_t b = 1;
+int64_t result;
+int oflo;
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  pgac_cv__builtin_op_overflow=yes
+else
+  pgac_cv__builtin_op_overflow=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv__builtin_op_overflow" >&5
+$as_echo "$pgac_cv__builtin_op_overflow" >&6; }
+if test x"$pgac_cv__builtin_op_overflow" = xyes ; then
+
+$as_echo "#define HAVE__BUILTIN_OP_OVERFLOW 1" >>confdefs.h
+
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_unreachable" >&5
 $as_echo_n "checking for __builtin_unreachable... " >&6; }
@@ -16439,236 +16475,6 @@ fi
 # Run tests below here
 # --------------------
 
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether long int is 64 bits" >&5
-$as_echo_n "checking whether long int is 64 bits... " >&6; }
-if ${pgac_cv_type_long_int_64+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test "$cross_compiling" = yes; then :
-  # If cross-compiling, check the size reported by the compiler and
-# trust that the arithmetic works.
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-static int test_array [1 - 2 * !(sizeof(long int) == 8)];
-test_array [0] = 0;
-return test_array [0];
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  pgac_cv_type_long_int_64=yes
-else
-  pgac_cv_type_long_int_64=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-typedef long int ac_int64;
-
-/*
- * These are globals to discourage the compiler from folding all the
- * arithmetic tests down to compile-time constants.
- */
-ac_int64 a = 20000001;
-ac_int64 b = 40000005;
-
-int does_int64_work()
-{
-  ac_int64 c,d;
-
-  if (sizeof(ac_int64) != 8)
-    return 0;			/* definitely not the right size */
-
-  /* Do perfunctory checks to see if 64-bit arithmetic seems to work */
-  c = a * b;
-  d = (c + b) / b;
-  if (d != a+1)
-    return 0;
-  return 1;
-}
-
-int
-main() {
-  return (! does_int64_work());
-}
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
-  pgac_cv_type_long_int_64=yes
-else
-  pgac_cv_type_long_int_64=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
-  conftest.$ac_objext conftest.beam conftest.$ac_ext
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_type_long_int_64" >&5
-$as_echo "$pgac_cv_type_long_int_64" >&6; }
-
-HAVE_LONG_INT_64=$pgac_cv_type_long_int_64
-if test x"$pgac_cv_type_long_int_64" = xyes ; then
-
-$as_echo "#define HAVE_LONG_INT_64 1" >>confdefs.h
-
-fi
-
-
-if test x"$HAVE_LONG_INT_64" = x"yes" ; then
-  pg_int64_type="long int"
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether long long int is 64 bits" >&5
-$as_echo_n "checking whether long long int is 64 bits... " >&6; }
-if ${pgac_cv_type_long_long_int_64+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test "$cross_compiling" = yes; then :
-  # If cross-compiling, check the size reported by the compiler and
-# trust that the arithmetic works.
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-static int test_array [1 - 2 * !(sizeof(long long int) == 8)];
-test_array [0] = 0;
-return test_array [0];
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  pgac_cv_type_long_long_int_64=yes
-else
-  pgac_cv_type_long_long_int_64=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-typedef long long int ac_int64;
-
-/*
- * These are globals to discourage the compiler from folding all the
- * arithmetic tests down to compile-time constants.
- */
-ac_int64 a = 20000001;
-ac_int64 b = 40000005;
-
-int does_int64_work()
-{
-  ac_int64 c,d;
-
-  if (sizeof(ac_int64) != 8)
-    return 0;			/* definitely not the right size */
-
-  /* Do perfunctory checks to see if 64-bit arithmetic seems to work */
-  c = a * b;
-  d = (c + b) / b;
-  if (d != a+1)
-    return 0;
-  return 1;
-}
-
-int
-main() {
-  return (! does_int64_work());
-}
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
-  pgac_cv_type_long_long_int_64=yes
-else
-  pgac_cv_type_long_long_int_64=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
-  conftest.$ac_objext conftest.beam conftest.$ac_ext
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_type_long_long_int_64" >&5
-$as_echo "$pgac_cv_type_long_long_int_64" >&6; }
-
-HAVE_LONG_LONG_INT_64=$pgac_cv_type_long_long_int_64
-if test x"$pgac_cv_type_long_long_int_64" = xyes ; then
-
-$as_echo "#define HAVE_LONG_LONG_INT_64 1" >>confdefs.h
-
-fi
-
-  if test x"$HAVE_LONG_LONG_INT_64" = x"yes" ; then
-    pg_int64_type="long long int"
-  else
-    as_fn_error $? "Cannot find a working 64-bit integer type." "$LINENO" 5
-  fi
-fi
-
-
-cat >>confdefs.h <<_ACEOF
-#define PG_INT64_TYPE $pg_int64_type
-_ACEOF
-
-
-# Select the printf length modifier that goes with that, too.
-if test x"$pg_int64_type" = x"long long int" ; then
-  INT64_MODIFIER='"ll"'
-else
-  INT64_MODIFIER='"l"'
-fi
-
-
-cat >>confdefs.h <<_ACEOF
-#define INT64_MODIFIER $INT64_MODIFIER
-_ACEOF
-
-
-# has to be down here, rather than with the other builtins, because
-# the test uses PG_INT64_TYPE.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_mul_overflow" >&5
-$as_echo_n "checking for __builtin_mul_overflow... " >&6; }
-if ${pgac_cv__builtin_op_overflow+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-PG_INT64_TYPE a = 1;
-PG_INT64_TYPE b = 1;
-PG_INT64_TYPE result;
-int oflo;
-
-int
-main ()
-{
-oflo = __builtin_mul_overflow(a, b, &result);
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-  pgac_cv__builtin_op_overflow=yes
-else
-  pgac_cv__builtin_op_overflow=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv__builtin_op_overflow" >&5
-$as_echo "$pgac_cv__builtin_op_overflow" >&6; }
-if test x"$pgac_cv__builtin_op_overflow" = xyes ; then
-
-$as_echo "#define HAVE__BUILTIN_OP_OVERFLOW 1" >>confdefs.h
-
-fi
-
 # Check size of void *, size_t (enables tweaks for > 32bit address space)
 # The cast to long int works around a bug in the HP C Compiler
 # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
@@ -16877,43 +16683,41 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
-if test x"$HAVE_LONG_LONG_INT_64" = x"yes" ; then
-  # The cast to long int works around a bug in the HP C Compiler,
+# The cast to long int works around a bug in the HP C Compiler,
 # see AC_CHECK_SIZEOF for more information.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking alignment of long long int" >&5
-$as_echo_n "checking alignment of long long int... " >&6; }
-if ${ac_cv_alignof_long_long_int+:} false; then :
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking alignment of int64_t" >&5
+$as_echo_n "checking alignment of int64_t... " >&6; }
+if ${ac_cv_alignof_int64_t+:} false; then :
   $as_echo_n "(cached) " >&6
 else
-  if ac_fn_c_compute_int "$LINENO" "(long int) offsetof (ac__type_alignof_, y)" "ac_cv_alignof_long_long_int"        "$ac_includes_default
+  if ac_fn_c_compute_int "$LINENO" "(long int) offsetof (ac__type_alignof_, y)" "ac_cv_alignof_int64_t"        "$ac_includes_default
 #ifndef offsetof
 # define offsetof(type, member) ((char *) &((type *) 0)->member - (char *) 0)
 #endif
-typedef struct { char x; long long int y; } ac__type_alignof_;"; then :
+typedef struct { char x; int64_t y; } ac__type_alignof_;"; then :
 
 else
-  if test "$ac_cv_type_long_long_int" = yes; then
+  if test "$ac_cv_type_int64_t" = yes; then
      { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error 77 "cannot compute alignment of long long int
+as_fn_error 77 "cannot compute alignment of int64_t
 See \`config.log' for more details" "$LINENO" 5; }
    else
-     ac_cv_alignof_long_long_int=0
+     ac_cv_alignof_int64_t=0
    fi
 fi
 
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_alignof_long_long_int" >&5
-$as_echo "$ac_cv_alignof_long_long_int" >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_alignof_int64_t" >&5
+$as_echo "$ac_cv_alignof_int64_t" >&6; }
 
 
 
 cat >>confdefs.h <<_ACEOF
-#define ALIGNOF_LONG_LONG_INT $ac_cv_alignof_long_long_int
+#define ALIGNOF_INT64_T $ac_cv_alignof_int64_t
 _ACEOF
 
 
-fi
 # The cast to long int works around a bug in the HP C Compiler,
 # see AC_CHECK_SIZEOF for more information.
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking alignment of double" >&5
@@ -16971,8 +16775,8 @@ MAX_ALIGNOF=$ac_cv_alignof_double
 if test $ac_cv_alignof_long -gt $MAX_ALIGNOF ; then
   as_fn_error $? "alignment of 'long' is greater than the alignment of 'double'" "$LINENO" 5
 fi
-if test x"$HAVE_LONG_LONG_INT_64" = xyes && test $ac_cv_alignof_long_long_int -gt $MAX_ALIGNOF ; then
-  as_fn_error $? "alignment of 'long long int' is greater than the alignment of 'double'" "$LINENO" 5
+if test $ac_cv_alignof_int64_t -gt $MAX_ALIGNOF ; then
+  as_fn_error $? "alignment of 'int64_t' is greater than the alignment of 'double'" "$LINENO" 5
 fi
 
 cat >>confdefs.h <<_ACEOF
@@ -16980,7 +16784,6 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
-
 # Some platforms predefine the types int8, int16, etc.  Only check
 # a (hopefully) representative subset.
 ac_fn_c_check_type "$LINENO" "int8" "ac_cv_type_int8" "#include <stdio.h>
@@ -17025,6 +16828,60 @@ _ACEOF
 fi
 
 
+# Check how to format int64_t without warnings from printf.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for printf int64_t modifier" >&5
+$as_echo_n "checking for printf int64_t modifier... " >&6; }
+if ${pgac_cv_int64_modifier+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+ac_save_c_werror_flag=$ac_c_werror_flag
+ac_c_werror_flag=yes
+if test "$ac_cv_sizeof_long" -lt 8; then
+  # long isn't wide enough, so use "ll"
+  pgac_cv_int64_modifier='"ll"'
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdint.h>
+int
+main ()
+{
+extern void emit_log(int ignore, const char *fmt,...) __attribute__((format(printf,2,3)));
+ void
+ f()
+ {
+     emit_log(0, "%lld", (int64_t) 42);
+ }
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  # this system understands the attribute, and accepted "ll" without
+  # warning, so go with that (example: macOS)
+  pgac_cv_int64_modifier='"ll"'
+else
+  # either this system doesn't understand the attribute at all (and
+  # "l" should be fine because now we only care about getting the
+  # right size), or it rejected "ll" with warnings because it expected
+  # "l" (example: FreeBSD)
+  pgac_cv_int64_modifier='"l"'
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+ac_c_werror_flag=$ac_save_c_werror_flag
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_int64_modifier" >&5
+$as_echo "$pgac_cv_int64_modifier" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define INT64_MODIFIER $pgac_cv_int64_modifier
+_ACEOF
+
+
+
 # Some compilers offer a 128-bit integer scalar type.
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __int128" >&5
 $as_echo_n "checking for __int128... " >&6; }
@@ -17279,12 +17136,12 @@ if ${pgac_cv_gcc_sync_int64_cas+:} false; then :
 else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
-
+#include <stdint.h>
 int
 main ()
 {
-PG_INT64_TYPE lock = 0;
-   __sync_val_compare_and_swap(&lock, 0, (PG_INT64_TYPE) 37);
+int64_t lock = 0;
+   __sync_val_compare_and_swap(&lock, 0, (int64_t) 37);
   ;
   return 0;
 }
@@ -17344,12 +17201,12 @@ if ${pgac_cv_gcc_atomic_int64_cas+:} false; then :
 else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
-
+#include <stdint.h>
 int
 main ()
 {
-PG_INT64_TYPE val = 0;
-   PG_INT64_TYPE expect = 0;
+int64_t val = 0;
+   int64_t expect = 0;
    __atomic_compare_exchange_n(&val, &expect, 37, 0, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);
   ;
   return 0;
@@ -17604,11 +17461,12 @@ CFLAGS="$pgac_save_CFLAGS "
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 #include <immintrin.h>
+                                 #include <stdint.h>
 int
 main ()
 {
 const char buf[sizeof(__m512i)];
-   PG_INT64_TYPE popcnt = 0;
+   int64_t popcnt = 0;
    __m512i accum = _mm512_setzero_si512();
    const __m512i val = _mm512_maskz_loadu_epi8((__mmask64) 0xf0f0f0f0f0f0f0f0, (const __m512i *) buf);
    const __m512i cnt = _mm512_popcnt_epi64(val);
@@ -17647,11 +17505,12 @@ CFLAGS="$pgac_save_CFLAGS -mavx512vpopcntdq -mavx512bw"
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 #include <immintrin.h>
+                                 #include <stdint.h>
 int
 main ()
 {
 const char buf[sizeof(__m512i)];
-   PG_INT64_TYPE popcnt = 0;
+   int64_t popcnt = 0;
    __m512i accum = _mm512_setzero_si512();
    const __m512i val = _mm512_maskz_loadu_epi8((__mmask64) 0xf0f0f0f0f0f0f0f0, (const __m512i *) buf);
    const __m512i cnt = _mm512_popcnt_epi64(val);
@@ -19272,9 +19131,6 @@ fi
 ac_config_headers="$ac_config_headers src/include/pg_config.h"
 
 
-ac_config_headers="$ac_config_headers src/include/pg_config_ext.h"
-
-
 ac_config_headers="$ac_config_headers src/interfaces/ecpg/include/ecpg_config.h"
 
 
@@ -19989,7 +19845,6 @@ do
     "src/Makefile.port") CONFIG_LINKS="$CONFIG_LINKS src/Makefile.port:src/makefiles/Makefile.${template}" ;;
     "check_win32_symlinks") CONFIG_COMMANDS="$CONFIG_COMMANDS check_win32_symlinks" ;;
     "src/include/pg_config.h") CONFIG_HEADERS="$CONFIG_HEADERS src/include/pg_config.h" ;;
-    "src/include/pg_config_ext.h") CONFIG_HEADERS="$CONFIG_HEADERS src/include/pg_config_ext.h" ;;
     "src/interfaces/ecpg/include/ecpg_config.h") CONFIG_HEADERS="$CONFIG_HEADERS src/interfaces/ecpg/include/ecpg_config.h" ;;
 
   *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
@@ -20597,10 +20452,6 @@ $as_echo "$as_me: WARNING: *** link for $FILE -- please fix by hand" >&2;}
     "src/include/pg_config.h":H)
 # Update timestamp for pg_config.h (see Makefile.global)
 echo >src/include/stamp-h
- ;;
-    "src/include/pg_config_ext.h":H)
-# Update timestamp for pg_config_ext.h (see Makefile.global)
-echo >src/include/stamp-ext-h
  ;;
     "src/interfaces/ecpg/include/ecpg_config.h":H) echo >src/interfaces/ecpg/include/stamp-h ;;
 
diff --git a/configure.ac b/configure.ac
index ab2d51c21ce..10bfb994d4f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1630,6 +1630,7 @@ PGAC_C_STATIC_ASSERT
 PGAC_C_TYPEOF
 PGAC_C_TYPES_COMPATIBLE
 PGAC_C_BUILTIN_CONSTANT_P
+PGAC_C_BUILTIN_OP_OVERFLOW
 PGAC_C_BUILTIN_UNREACHABLE
 PGAC_C_COMPUTED_GOTO
 PGAC_STRUCT_TIMEZONE
@@ -1945,41 +1946,6 @@ for the exact reason.]])],
 # Run tests below here
 # --------------------
 
-dnl Check to see if we have a working 64-bit integer type.
-dnl Since Postgres 8.4, we no longer support compilers without a working
-dnl 64-bit type; but we have to determine whether that type is called
-dnl "long int" or "long long int".
-
-PGAC_TYPE_64BIT_INT([long int])
-
-if test x"$HAVE_LONG_INT_64" = x"yes" ; then
-  pg_int64_type="long int"
-else
-  PGAC_TYPE_64BIT_INT([long long int])
-  if test x"$HAVE_LONG_LONG_INT_64" = x"yes" ; then
-    pg_int64_type="long long int"
-  else
-    AC_MSG_ERROR([Cannot find a working 64-bit integer type.])
-  fi
-fi
-
-AC_DEFINE_UNQUOTED(PG_INT64_TYPE, $pg_int64_type,
-  [Define to the name of a signed 64-bit integer type.])
-
-# Select the printf length modifier that goes with that, too.
-if test x"$pg_int64_type" = x"long long int" ; then
-  INT64_MODIFIER='"ll"'
-else
-  INT64_MODIFIER='"l"'
-fi
-
-AC_DEFINE_UNQUOTED(INT64_MODIFIER, $INT64_MODIFIER,
-                   [Define to the appropriate printf length modifier for 64-bit ints.])
-
-# has to be down here, rather than with the other builtins, because
-# the test uses PG_INT64_TYPE.
-PGAC_C_BUILTIN_OP_OVERFLOW
-
 # Check size of void *, size_t (enables tweaks for > 32bit address space)
 AC_CHECK_SIZEOF([void *])
 AC_CHECK_SIZEOF([size_t])
@@ -1990,9 +1956,7 @@ AC_CHECK_SIZEOF([long])
 AC_CHECK_ALIGNOF(short)
 AC_CHECK_ALIGNOF(int)
 AC_CHECK_ALIGNOF(long)
-if test x"$HAVE_LONG_LONG_INT_64" = x"yes" ; then
-  AC_CHECK_ALIGNOF(long long int)
-fi
+AC_CHECK_ALIGNOF(int64_t)
 AC_CHECK_ALIGNOF(double)
 
 # Compute maximum alignment of any basic type.
@@ -2016,17 +1980,19 @@ MAX_ALIGNOF=$ac_cv_alignof_double
 if test $ac_cv_alignof_long -gt $MAX_ALIGNOF ; then
   AC_MSG_ERROR([alignment of 'long' is greater than the alignment of 'double'])
 fi
-if test x"$HAVE_LONG_LONG_INT_64" = xyes && test $ac_cv_alignof_long_long_int -gt $MAX_ALIGNOF ; then
-  AC_MSG_ERROR([alignment of 'long long int' is greater than the alignment of 'double'])
+if test $ac_cv_alignof_int64_t -gt $MAX_ALIGNOF ; then
+  AC_MSG_ERROR([alignment of 'int64_t' is greater than the alignment of 'double'])
 fi
 AC_DEFINE_UNQUOTED(MAXIMUM_ALIGNOF, $MAX_ALIGNOF, [Define as the maximum alignment requirement of any C data type.])
 
-
 # Some platforms predefine the types int8, int16, etc.  Only check
 # a (hopefully) representative subset.
 AC_CHECK_TYPES([int8, uint8, int64, uint64], [], [],
 [#include <stdio.h>])
 
+# Check how to format int64_t without warnings from printf.
+PGAC_PRINTF_INT64_MODIFIER
+
 # Some compilers offer a 128-bit integer scalar type.
 PGAC_TYPE_128BIT_INT
 
@@ -2520,12 +2486,6 @@ AC_CONFIG_HEADERS([src/include/pg_config.h],
 echo >src/include/stamp-h
 ])
 
-AC_CONFIG_HEADERS([src/include/pg_config_ext.h],
-[
-# Update timestamp for pg_config_ext.h (see Makefile.global)
-echo >src/include/stamp-ext-h
-])
-
 AC_CONFIG_HEADERS([src/interfaces/ecpg/include/ecpg_config.h],
                   [echo >src/interfaces/ecpg/include/stamp-h])
 
diff --git a/meson.build b/meson.build
index 5387bb6d5fd..6534bf6e17d 100644
--- a/meson.build
+++ b/meson.build
@@ -1491,18 +1491,6 @@ endif
 
 sizeof_long = cc.sizeof('long', args: test_c_args)
 cdata.set('SIZEOF_LONG', sizeof_long)
-if sizeof_long == 8
-  cdata.set('HAVE_LONG_INT_64', 1)
-  pg_int64_type = 'long int'
-  cdata.set_quoted('INT64_MODIFIER', 'l')
-elif sizeof_long == 4 and cc.sizeof('long long', args: test_c_args) == 8
-  cdata.set('HAVE_LONG_LONG_INT_64', 1)
-  pg_int64_type = 'long long int'
-  cdata.set_quoted('INT64_MODIFIER', 'll')
-else
-  error('do not know how to get a 64bit int')
-endif
-cdata.set('PG_INT64_TYPE', pg_int64_type)
 
 if host_machine.endian() == 'big'
   cdata.set('WORDS_BIGENDIAN', 1)
@@ -1532,8 +1520,8 @@ endforeach
 # any types wider than 64 bits, as allowing MAXIMUM_ALIGNOF to exceed 8
 # would be too much of a penalty for disk and memory space.
 alignof_double = cdata.get('ALIGNOF_DOUBLE')
-if cc.alignment(pg_int64_type, args: test_c_args) > alignof_double
-  error('alignment of int64 is greater than the alignment of double')
+if cc.alignment('int64_t', args: test_c_args, prefix: '#include <stdint.h>') > alignof_double
+  error('alignment of int64_t is greater than the alignment of double')
 endif
 cdata.set('MAXIMUM_ALIGNOF', alignof_double)
 
@@ -1686,6 +1674,34 @@ foreach a : printf_attributes
 endforeach
 
 
+# Determine which printf format modifier to use for int64_t values, to avoid
+# warnings from the format string checker (if there is one).
+if cdata.get('SIZEOF_LONG') < 8
+  # long isn't wide enough, so use "ll"
+  cdata.set('INT64_MODIFIER', '"ll"')
+else
+  testsrc = '''
+#include <stdint.h>
+extern void emit_log(int ignore, const char *fmt,...) __attribute__((format(printf,2,3)));
+void
+f()
+{
+    emit_log(0, "%lld", (int64_t) 42);
+}
+'''
+  if cc.compiles(testsrc, args: test_c_args + attrib_error_args)
+	# this system understands the attribute, and accepted "ll" without warning,
+	# so go with that (example: macOS)
+    cdata.set('INT64_MODIFIER', '"ll"')
+  else
+	# either this system doesn't understand the attribute at all (and "l" should
+	# be fine because now we only care about getting the right size), or it
+	# rejected "ll" with warnings because it expected "l" (example: FreeBSD)
+    cdata.set('INT64_MODIFIER', '"l"')
+  endif
+endif
+
+
 if cc.has_function_attribute('visibility:default') and \
     cc.has_function_attribute('visibility:hidden')
   cdata.set('HAVE_VISIBILITY_ATTRIBUTE', 1)
@@ -1745,17 +1761,17 @@ endif
 # compile, and store the results in global variables so the compiler doesn't
 # optimize away the call.
 if cc.links('''
-    INT64 a = 1;
-    INT64 b = 1;
-    INT64 result;
+    #include <stdint.h>
+    int64_t a = 1;
+    int64_t b = 1;
+    int64_t result;
 
     int main(void)
     {
         return __builtin_mul_overflow(a, b, &result);
     }''',
     name: '__builtin_mul_overflow',
-    args: test_c_args + ['-DINT64=@0@'.format(cdata.get('PG_INT64_TYPE'))],
-    )
+    args: test_c_args)
   cdata.set('HAVE__BUILTIN_OP_OVERFLOW', 1)
 endif
 
@@ -2048,7 +2064,7 @@ int main(void)
     cdata.set(check['name'],
       cc.links(test,
         name: check['desc'],
-        args: test_c_args + ['-DINT64=@0@'.format(cdata.get('PG_INT64_TYPE'))]) ? 1 : false
+        args: test_c_args) ? 1 : false
     )
   endforeach
 
@@ -2092,11 +2108,12 @@ if host_cpu == 'x86_64'
 
   prog = '''
 #include <immintrin.h>
+#include <stdint.h>
 
 int main(void)
 {
     const char buf[sizeof(__m512i)];
-    INT64 popcnt = 0;
+    int64_t popcnt = 0;
     __m512i accum = _mm512_setzero_si512();
     const __m512i val = _mm512_maskz_loadu_epi8((__mmask64) 0xf0f0f0f0f0f0f0f0, (const __m512i *) buf);
     const __m512i cnt = _mm512_popcnt_epi64(val);
@@ -2108,10 +2125,10 @@ int main(void)
 '''
 
   if cc.links(prog, name: 'AVX-512 popcount without -mavx512vpopcntdq -mavx512bw',
-        args: test_c_args + ['-DINT64=@0@'.format(cdata.get('PG_INT64_TYPE'))])
+        args: test_c_args)
     cdata.set('USE_AVX512_POPCNT_WITH_RUNTIME_CHECK', 1)
   elif cc.links(prog, name: 'AVX-512 popcount with -mavx512vpopcntdq -mavx512bw',
-        args: test_c_args + ['-DINT64=@0@'.format(cdata.get('PG_INT64_TYPE'))] + ['-mavx512vpopcntdq'] + ['-mavx512bw'])
+        args: test_c_args + ['-mavx512vpopcntdq'] + ['-mavx512bw'])
     cdata.set('USE_AVX512_POPCNT_WITH_RUNTIME_CHECK', 1)
     cflags_popcnt += ['-mavx512vpopcntdq'] + ['-mavx512bw']
   endif
diff --git a/src/Makefile.global.in b/src/Makefile.global.in
index 83b91fe9167..5fa9f3d6748 100644
--- a/src/Makefile.global.in
+++ b/src/Makefile.global.in
@@ -834,12 +834,6 @@ $(top_builddir)/src/include/pg_config.h: $(top_builddir)/src/include/stamp-h ;
 $(top_builddir)/src/include/stamp-h: $(top_srcdir)/src/include/pg_config.h.in $(top_builddir)/config.status
 	cd $(top_builddir) && ./config.status src/include/pg_config.h
 
-# Also remake pg_config_ext.h from pg_config_ext.h.in, same logic as above.
-$(top_builddir)/src/include/pg_config_ext.h: $(top_builddir)/src/include/stamp-ext-h ;
-
-$(top_builddir)/src/include/stamp-ext-h: $(top_srcdir)/src/include/pg_config_ext.h.in $(top_builddir)/config.status
-	cd $(top_builddir) && ./config.status src/include/pg_config_ext.h
-
 # Also remake ecpg_config.h from ecpg_config.h.in if the latter changed, same
 # logic as above.
 $(top_builddir)/src/interfaces/ecpg/include/ecpg_config.h: $(top_builddir)/src/interfaces/ecpg/include/stamp-h ;
diff --git a/src/include/.gitignore b/src/include/.gitignore
index 51819fb4ddd..6e99e82fe0c 100644
--- a/src/include/.gitignore
+++ b/src/include/.gitignore
@@ -1,5 +1,3 @@
 /stamp-h
-/stamp-ext-h
 /pg_config.h
-/pg_config_ext.h
 /pg_config_os.h
diff --git a/src/include/Makefile b/src/include/Makefile
index b8b576a4de3..26332ff9cbc 100644
--- a/src/include/Makefile
+++ b/src/include/Makefile
@@ -13,7 +13,7 @@ top_builddir = ../..
 include $(top_builddir)/src/Makefile.global
 
 
-all: pg_config.h pg_config_ext.h pg_config_os.h
+all: pg_config.h pg_config_os.h
 
 
 # Subdirectories containing installable headers
@@ -32,7 +32,6 @@ install: all installdirs
 	$(INSTALL_DATA) $(srcdir)/postgres_ext.h   '$(DESTDIR)$(includedir)'
 	$(INSTALL_DATA) $(srcdir)/libpq/libpq-fs.h '$(DESTDIR)$(includedir)/libpq'
 	$(INSTALL_DATA) pg_config.h     '$(DESTDIR)$(includedir)'
-	$(INSTALL_DATA) pg_config_ext.h '$(DESTDIR)$(includedir)'
 	$(INSTALL_DATA) pg_config_os.h  '$(DESTDIR)$(includedir)'
 	$(INSTALL_DATA) $(srcdir)/pg_config_manual.h '$(DESTDIR)$(includedir)'
 # These headers are needed by the not-so-public headers of the interfaces.
@@ -43,7 +42,6 @@ install: all installdirs
 	$(INSTALL_DATA) $(srcdir)/libpq/protocol.h '$(DESTDIR)$(includedir_internal)/libpq'
 # These headers are needed for server-side development
 	$(INSTALL_DATA) pg_config.h     '$(DESTDIR)$(includedir_server)'
-	$(INSTALL_DATA) pg_config_ext.h '$(DESTDIR)$(includedir_server)'
 	$(INSTALL_DATA) pg_config_os.h  '$(DESTDIR)$(includedir_server)'
 	$(INSTALL_DATA) nodes/nodetags.h '$(DESTDIR)$(includedir_server)/nodes'
 	$(INSTALL_DATA) utils/errcodes.h '$(DESTDIR)$(includedir_server)/utils'
@@ -66,7 +64,7 @@ installdirs:
 
 
 uninstall:
-	rm -f $(addprefix '$(DESTDIR)$(includedir)'/, pg_config.h pg_config_ext.h pg_config_os.h pg_config_manual.h postgres_ext.h libpq/libpq-fs.h)
+	rm -f $(addprefix '$(DESTDIR)$(includedir)'/, pg_config.h pg_config_os.h pg_config_manual.h postgres_ext.h libpq/libpq-fs.h)
 	rm -f $(addprefix '$(DESTDIR)$(includedir_internal)'/, c.h port.h postgres_fe.h libpq/pqcomm.h libpq/protocol.h)
 # heuristic...
 	rm -rf $(addprefix '$(DESTDIR)$(includedir_server)'/, $(SUBDIRS) *.h)
@@ -80,4 +78,4 @@ clean:
 	$(MAKE) -C catalog clean
 
 distclean: clean
-	rm -f pg_config.h pg_config_ext.h pg_config_os.h stamp-h stamp-ext-h
+	rm -f pg_config.h pg_config_os.h stamp-h stamp-ext-h
diff --git a/src/include/c.h b/src/include/c.h
index dc1841346cd..024213f37f3 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -48,9 +48,6 @@
 
 #include "postgres_ext.h"
 
-/* Must undef pg_config_ext.h symbols before including pg_config.h */
-#undef PG_INT64_TYPE
-
 #include "pg_config.h"
 #include "pg_config_manual.h"	/* must be after pg_config.h */
 #include "pg_config_os.h"		/* must be before any system header files */
@@ -489,10 +486,13 @@ typedef char *Pointer;
  *		frontend/backend protocol.
  */
 #ifndef HAVE_INT8
-typedef signed char int8;		/* == 8 bits */
-typedef signed short int16;		/* == 16 bits */
-typedef signed int int32;		/* == 32 bits */
+typedef int8_t int8;			/* == 8 bits */
+typedef int16_t int16;			/* == 16 bits */
+typedef int32_t int32;			/* == 32 bits */
 #endif							/* not HAVE_INT8 */
+#ifndef HAVE_INT64
+typedef int64_t int64;			/* == 64 bits */
+#endif							/* not HAVE_INT64 */
 
 /*
  * uintN
@@ -501,10 +501,13 @@ typedef signed int int32;		/* == 32 bits */
  *		frontend/backend protocol.
  */
 #ifndef HAVE_UINT8
-typedef unsigned char uint8;	/* == 8 bits */
-typedef unsigned short uint16;	/* == 16 bits */
-typedef unsigned int uint32;	/* == 32 bits */
+typedef uint8_t uint8;			/* == 8 bits */
+typedef uint16_t uint16;		/* == 16 bits */
+typedef uint32_t uint32;		/* == 32 bits */
 #endif							/* not HAVE_UINT8 */
+#ifndef HAVE_UINT64
+typedef uint64_t uint64;		/* == 64 bits */
+#endif							/* not HAVE_UINT64 */
 
 /*
  * bitsN
@@ -517,32 +520,8 @@ typedef uint32 bits32;			/* >= 32 bits */
 /*
  * 64-bit integers
  */
-#ifdef HAVE_LONG_INT_64
-/* Plain "long int" fits, use it */
-
-#ifndef HAVE_INT64
-typedef long int int64;
-#endif
-#ifndef HAVE_UINT64
-typedef unsigned long int uint64;
-#endif
-#define INT64CONST(x)  (x##L)
-#define UINT64CONST(x) (x##UL)
-#elif defined(HAVE_LONG_LONG_INT_64)
-/* We have working support for "long long int", use that */
-
-#ifndef HAVE_INT64
-typedef long long int int64;
-#endif
-#ifndef HAVE_UINT64
-typedef unsigned long long int uint64;
-#endif
-#define INT64CONST(x)  (x##LL)
-#define UINT64CONST(x) (x##ULL)
-#else
-/* neither HAVE_LONG_INT_64 nor HAVE_LONG_LONG_INT_64 */
-#error must have a working 64-bit integer datatype
-#endif
+#define INT64CONST(x)  INT64_C(x)
+#define UINT64CONST(x) UINT64_C(x)
 
 /* snprintf format strings to use for 64-bit integers */
 #define INT64_FORMAT "%" INT64_MODIFIER "d"
@@ -575,22 +554,19 @@ typedef unsigned PG_INT128_TYPE uint128
 #endif
 #endif
 
-/*
- * stdint.h limits aren't guaranteed to have compatible types with our fixed
- * width types. So just define our own.
- */
-#define PG_INT8_MIN		(-0x7F-1)
-#define PG_INT8_MAX		(0x7F)
-#define PG_UINT8_MAX	(0xFF)
-#define PG_INT16_MIN	(-0x7FFF-1)
-#define PG_INT16_MAX	(0x7FFF)
-#define PG_UINT16_MAX	(0xFFFF)
-#define PG_INT32_MIN	(-0x7FFFFFFF-1)
-#define PG_INT32_MAX	(0x7FFFFFFF)
-#define PG_UINT32_MAX	(0xFFFFFFFFU)
-#define PG_INT64_MIN	(-INT64CONST(0x7FFFFFFFFFFFFFFF) - 1)
-#define PG_INT64_MAX	INT64CONST(0x7FFFFFFFFFFFFFFF)
-#define PG_UINT64_MAX	UINT64CONST(0xFFFFFFFFFFFFFFFF)
+/* Historical names for limits in stdint.h. */
+#define PG_INT8_MIN		INT8_MIN
+#define PG_INT8_MAX		INT8_MAX
+#define PG_UINT8_MAX	UINT8_MAX
+#define PG_INT16_MIN	INT16_MIN
+#define PG_INT16_MAX	INT16_MAX
+#define PG_UINT16_MAX	UINT16_MAX
+#define PG_INT32_MIN	INT32_MIN
+#define PG_INT32_MAX	INT32_MAX
+#define PG_UINT32_MAX	UINT32_MAX
+#define PG_INT64_MIN	INT64_MIN
+#define PG_INT64_MAX	INT64_MAX
+#define PG_UINT64_MAX	UINT64_MAX
 
 /*
  * We now always use int64 timestamps, but keep this symbol defined for the
diff --git a/src/include/meson.build b/src/include/meson.build
index 58b7a9c1e7e..e691b12b8a0 100644
--- a/src/include/meson.build
+++ b/src/include/meson.build
@@ -1,14 +1,5 @@
 # Copyright (c) 2022-2024, PostgreSQL Global Development Group
 
-pg_config_ext = configure_file(
-  input: 'pg_config_ext.h.meson',
-  output: 'pg_config_ext.h',
-  configuration: cdata,
-  install: true,
-  install_dir: dir_include,
-)
-configure_files += pg_config_ext
-
 pg_config_os = configure_file(
   output: 'pg_config_os.h',
   input: files('port/@0@.h'.format(portname)),
@@ -116,7 +107,6 @@ install_headers(
   'postgres_fe.h',
   'varatt.h',
   'windowapi.h',
-  pg_config_ext,
   pg_config_os,
   pg_config,
   install_dir: dir_include_server,
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index f8d3e3b6b84..3755eb69e24 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -9,12 +9,12 @@
 /* The normal alignment of `int', in bytes. */
 #undef ALIGNOF_INT
 
+/* The normal alignment of `int64_t', in bytes. */
+#undef ALIGNOF_INT64_T
+
 /* The normal alignment of `long', in bytes. */
 #undef ALIGNOF_LONG
 
-/* The normal alignment of `long long int', in bytes. */
-#undef ALIGNOF_LONG_LONG_INT
-
 /* The normal alignment of `PG_INT128_TYPE', in bytes. */
 #undef ALIGNOF_PG_INT128_TYPE
 
@@ -282,12 +282,6 @@
 /* Define to 1 if you have the `zstd' library (-lzstd). */
 #undef HAVE_LIBZSTD
 
-/* Define to 1 if `long int' works and is 64 bits. */
-#undef HAVE_LONG_INT_64
-
-/* Define to 1 if `long long int' works and is 64 bits. */
-#undef HAVE_LONG_LONG_INT_64
-
 /* Define to 1 if you have the <mbarrier.h> header file. */
 #undef HAVE_MBARRIER_H
 
@@ -570,7 +564,7 @@
 /* Define to 1 if your compiler understands _Static_assert. */
 #undef HAVE__STATIC_ASSERT
 
-/* Define to the appropriate printf length modifier for 64-bit ints. */
+/* Define to printf format modifier to use for int64_t. */
 #undef INT64_MODIFIER
 
 /* Define to 1 if `locale_t' requires <xlocale.h>. */
@@ -607,9 +601,6 @@
 /* Define to the name of a signed 128-bit integer type. */
 #undef PG_INT128_TYPE
 
-/* Define to the name of a signed 64-bit integer type. */
-#undef PG_INT64_TYPE
-
 /* Define to the name of the default PostgreSQL service principal in Kerberos
    (GSSAPI). (--with-krb-srvnam=NAME) */
 #undef PG_KRB_SRVNAM
diff --git a/src/include/pg_config_ext.h.in b/src/include/pg_config_ext.h.in
deleted file mode 100644
index 8acadbdafd4..00000000000
--- a/src/include/pg_config_ext.h.in
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
- * src/include/pg_config_ext.h.in.  This is generated manually, not by
- * autoheader, since we want to limit which symbols get defined here.
- */
-
-/* Define to the name of a signed 64-bit integer type. */
-#undef PG_INT64_TYPE
diff --git a/src/include/pg_config_ext.h.meson b/src/include/pg_config_ext.h.meson
deleted file mode 100644
index 57cdfca0cfd..00000000000
--- a/src/include/pg_config_ext.h.meson
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
- * src/include/pg_config_ext.h.in.  This is generated manually, not by
- * autoheader, since we want to limit which symbols get defined here.
- */
-
-/* Define to the name of a signed 64-bit integer type. */
-#mesondefine PG_INT64_TYPE
diff --git a/src/include/port/pg_bitutils.h b/src/include/port/pg_bitutils.h
index 4d88478c9c2..1c09bf0ff27 100644
--- a/src/include/port/pg_bitutils.h
+++ b/src/include/port/pg_bitutils.h
@@ -74,13 +74,12 @@ pg_leftmost_one_pos64(uint64 word)
 #ifdef HAVE__BUILTIN_CLZ
 	Assert(word != 0);
 
-#if defined(HAVE_LONG_INT_64)
+#if SIZEOF_LONG == 8
 	return 63 - __builtin_clzl(word);
-#elif defined(HAVE_LONG_LONG_INT_64)
-	return 63 - __builtin_clzll(word);
 #else
-#error must have a working 64-bit integer datatype
-#endif							/* HAVE_LONG_INT_64 */
+	StaticAssertStmt(sizeof(word) == sizeof(long long), "unexpected size");
+	return 63 - __builtin_clzll(word);
+#endif
 
 #elif defined(_MSC_VER) && (defined(_M_AMD64) || defined(_M_ARM64))
 	unsigned long result;
@@ -147,13 +146,12 @@ pg_rightmost_one_pos64(uint64 word)
 #ifdef HAVE__BUILTIN_CTZ
 	Assert(word != 0);
 
-#if defined(HAVE_LONG_INT_64)
+#if SIZEOF_LONG == 8
 	return __builtin_ctzl(word);
-#elif defined(HAVE_LONG_LONG_INT_64)
-	return __builtin_ctzll(word);
 #else
-#error must have a working 64-bit integer datatype
-#endif							/* HAVE_LONG_INT_64 */
+	StaticAssertStmt(sizeof(word) == sizeof(long long), "unexpected size");
+	return __builtin_ctzll(word);
+#endif
 
 #elif defined(_MSC_VER) && (defined(_M_AMD64) || defined(_M_ARM64))
 	unsigned long result;
diff --git a/src/include/postgres_ext.h b/src/include/postgres_ext.h
index 240ad4e93bf..034056e7d94 100644
--- a/src/include/postgres_ext.h
+++ b/src/include/postgres_ext.h
@@ -23,7 +23,7 @@
 #ifndef POSTGRES_EXT_H
 #define POSTGRES_EXT_H
 
-#include "pg_config_ext.h"
+#include <stdint.h>
 
 /*
  * Object ID is a fundamental type in Postgres.
@@ -36,15 +36,14 @@ typedef unsigned int Oid;
 #define InvalidOid		((Oid) 0)
 #endif
 
-#define OID_MAX  UINT_MAX
-/* you will need to include <limits.h> to use the above #define */
+#define OID_MAX  UINT32_MAX
 
 #define atooid(x) ((Oid) strtoul((x), NULL, 10))
 /* the above needs <stdlib.h> */
 
 
 /* Define a signed 64-bit integer type for use in client API declarations. */
-typedef PG_INT64_TYPE pg_int64;
+typedef int64_t pg_int64;
 
 /*
  * Identifiers of error message fields.  Kept here to keep common
diff --git a/src/interfaces/ecpg/ecpglib/typename.c b/src/interfaces/ecpg/ecpglib/typename.c
index 1d482c4fa61..1ab2cda8487 100644
--- a/src/interfaces/ecpg/ecpglib/typename.c
+++ b/src/interfaces/ecpg/ecpglib/typename.c
@@ -131,10 +131,9 @@ sqlda_dynamic_type(Oid type, enum COMPAT_MODE compat)
 		case INTERVALOID:
 			return ECPGt_interval;
 		case INT8OID:
-#ifdef HAVE_LONG_LONG_INT_64
+#if SIZEOF_LONG < 8
 			return ECPGt_long_long;
-#endif
-#ifdef HAVE_LONG_INT_64
+#else
 			return ECPGt_long;
 #endif
 			/* Unhandled types always return a string */
diff --git a/src/interfaces/ecpg/include/ecpg_config.h.in b/src/interfaces/ecpg/include/ecpg_config.h.in
index 824617b9175..48bce0878a7 100644
--- a/src/interfaces/ecpg/include/ecpg_config.h.in
+++ b/src/interfaces/ecpg/include/ecpg_config.h.in
@@ -1,14 +1,5 @@
 /* Define to 1 to build client libraries as thread-safe code. */
 #define ENABLE_THREAD_SAFETY 1
 
-/* Define to 1 if the system has the type `int64'. */
-#undef HAVE_INT64
-
-/* Define to 1 if `long int' works and is 64 bits. */
-#undef HAVE_LONG_INT_64
-
-/* Define to 1 if `long long int' works and is 64 bits. */
-#undef HAVE_LONG_LONG_INT_64
-
 /* Define to 1 to use <stdbool.h> to define type bool. */
 #undef PG_USE_STDBOOL
diff --git a/src/interfaces/ecpg/include/meson.build b/src/interfaces/ecpg/include/meson.build
index 31610fef589..d0234413fcd 100644
--- a/src/interfaces/ecpg/include/meson.build
+++ b/src/interfaces/ecpg/include/meson.build
@@ -3,9 +3,6 @@
 ecpg_inc = include_directories('.')
 
 ecpg_conf_keys = [
-  'HAVE_INT64',
-  'HAVE_LONG_INT_64',
-  'HAVE_LONG_LONG_INT_64',
   'PG_USE_STDBOOL',
 ]
 
diff --git a/src/interfaces/ecpg/include/pgtypes_interval.h b/src/interfaces/ecpg/include/pgtypes_interval.h
index 2809b356f73..d16f74970c9 100644
--- a/src/interfaces/ecpg/include/pgtypes_interval.h
+++ b/src/interfaces/ecpg/include/pgtypes_interval.h
@@ -8,18 +8,7 @@
 
 #ifndef C_H
 
-#ifdef HAVE_LONG_INT_64
-#ifndef HAVE_INT64
-typedef long int int64;
-#endif
-#elif defined(HAVE_LONG_LONG_INT_64)
-#ifndef HAVE_INT64
-typedef long long int int64;
-#endif
-#else
-/* neither HAVE_LONG_INT_64 nor HAVE_LONG_LONG_INT_64 */
-#error must have a working 64-bit integer datatype
-#endif
+typedef int64_t int64;
 
 #define HAVE_INT64_TIMESTAMP
 #endif							/* C_H */
diff --git a/src/interfaces/ecpg/include/sqltypes.h b/src/interfaces/ecpg/include/sqltypes.h
index e7cbfa47956..aed055eb4ab 100644
--- a/src/interfaces/ecpg/include/sqltypes.h
+++ b/src/interfaces/ecpg/include/sqltypes.h
@@ -46,7 +46,7 @@
 #define SQLINTERVAL		ECPGt_interval
 #define SQLNCHAR	ECPGt_char
 #define SQLNVCHAR	ECPGt_char
-#ifdef HAVE_LONG_LONG_INT_64
+#if SIZEOF_LONG < 8
 #define SQLINT8		ECPGt_long_long
 #define SQLSERIAL8	ECPGt_long_long
 #else
diff --git a/src/interfaces/ecpg/test/expected/compat_informix-sqlda.c b/src/interfaces/ecpg/test/expected/compat_informix-sqlda.c
index 7e19319d27f..02ec7b668d3 100644
--- a/src/interfaces/ecpg/test/expected/compat_informix-sqlda.c
+++ b/src/interfaces/ecpg/test/expected/compat_informix-sqlda.c
@@ -97,7 +97,7 @@ typedef struct sqlda_struct sqlda_t;
 #define SQLINTERVAL		ECPGt_interval
 #define SQLNCHAR	ECPGt_char
 #define SQLNVCHAR	ECPGt_char
-#ifdef HAVE_LONG_LONG_INT_64
+#if SIZEOF_LONG < 8
 #define SQLINT8		ECPGt_long_long
 #define SQLSERIAL8	ECPGt_long_long
 #else
diff --git a/src/port/pg_bitutils.c b/src/port/pg_bitutils.c
index 87f56e82b80..d4413a299a9 100644
--- a/src/port/pg_bitutils.c
+++ b/src/port/pg_bitutils.c
@@ -370,12 +370,11 @@ static inline int
 pg_popcount64_slow(uint64 word)
 {
 #ifdef HAVE__BUILTIN_POPCOUNT
-#if defined(HAVE_LONG_INT_64)
+#if SIZEOF_LONG == 8
 	return __builtin_popcountl(word);
-#elif defined(HAVE_LONG_LONG_INT_64)
-	return __builtin_popcountll(word);
 #else
-#error must have a working 64-bit integer datatype
+	StaticAssertStmt(sizeof(word) == sizeof(long long), "unexpected size");
+	return __builtin_popcountll(word);
 #endif
 #else							/* !HAVE__BUILTIN_POPCOUNT */
 	int			result = 0;
diff --git a/src/port/snprintf.c b/src/port/snprintf.c
index 884f0262dd1..291148b4e8b 100644
--- a/src/port/snprintf.c
+++ b/src/port/snprintf.c
@@ -568,12 +568,11 @@ nextch2:
 				goto nextch2;
 			case 'z':
 #if SIZEOF_SIZE_T == 8
-#ifdef HAVE_LONG_INT_64
+#if SIZEOF_LONG == 8
 				longflag = 1;
-#elif defined(HAVE_LONG_LONG_INT_64)
-				longlongflag = 1;
 #else
-#error "Don't know how to print 64bit integers"
+				StaticAssertStmt(sizeof(size_t) == sizeof(long long), "unexpected size");
+				longlongflag = 1;
 #endif
 #else
 				/* assume size_t is same size as int */
@@ -835,12 +834,11 @@ nextch1:
 				goto nextch1;
 			case 'z':
 #if SIZEOF_SIZE_T == 8
-#ifdef HAVE_LONG_INT_64
+#if SIZEOF_LONG == 8
 				longflag = 1;
-#elif defined(HAVE_LONG_LONG_INT_64)
-				longlongflag = 1;
 #else
-#error "Don't know how to print 64bit integers"
+				StaticAssertStmt(sizeof(size_t) == sizeof(long long), "unexpected size");
+				longlongflag = 1;
 #endif
 #else
 				/* assume size_t is same size as int */
-- 
2.45.2

v3-0002-Remove-traces-of-BeOS.patchtext/x-patch; charset=US-ASCII; name=v3-0002-Remove-traces-of-BeOS.patchDownload
From 2b3c15b079c5f8aebd2f6a8f861c9422db757c2b Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Thu, 18 Apr 2024 12:06:17 +1200
Subject: [PATCH v3 2/3] Remove traces of BeOS.

Commit 15abc7788e6 tolerated namespace pollution from BeOS system
headers.  Commit 44f902122 de-supported BeOS.  Since that stuff didn't
make it into the Meson build system, synchronize by removing from
configure.

Reviewed-by: Peter Eisentraut <peter@eisentraut.org>
Reviewed-by: Heikki Linnakangas <hlinnaka@iki.fi>
Reviewed-by: Japin Li <japinli@hotmail.com>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us> (the idea, not the patch)
Discussion: https://postgr.es/m/ME3P282MB3166F9D1F71F787929C0C7E7B6312%40ME3P282MB3166.AUSP282.PROD.OUTLOOK.COM
---
 configure                  | 44 --------------------------------------
 configure.ac               |  5 -----
 src/include/c.h            |  8 -------
 src/include/pg_config.h.in | 12 -----------
 4 files changed, 69 deletions(-)

diff --git a/configure b/configure
index cfec577a1c1..3bfbfdf6521 100755
--- a/configure
+++ b/configure
@@ -16784,50 +16784,6 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
-# Some platforms predefine the types int8, int16, etc.  Only check
-# a (hopefully) representative subset.
-ac_fn_c_check_type "$LINENO" "int8" "ac_cv_type_int8" "#include <stdio.h>
-"
-if test "x$ac_cv_type_int8" = xyes; then :
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_INT8 1
-_ACEOF
-
-
-fi
-ac_fn_c_check_type "$LINENO" "uint8" "ac_cv_type_uint8" "#include <stdio.h>
-"
-if test "x$ac_cv_type_uint8" = xyes; then :
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_UINT8 1
-_ACEOF
-
-
-fi
-ac_fn_c_check_type "$LINENO" "int64" "ac_cv_type_int64" "#include <stdio.h>
-"
-if test "x$ac_cv_type_int64" = xyes; then :
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_INT64 1
-_ACEOF
-
-
-fi
-ac_fn_c_check_type "$LINENO" "uint64" "ac_cv_type_uint64" "#include <stdio.h>
-"
-if test "x$ac_cv_type_uint64" = xyes; then :
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_UINT64 1
-_ACEOF
-
-
-fi
-
-
 # Check how to format int64_t without warnings from printf.
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for printf int64_t modifier" >&5
 $as_echo_n "checking for printf int64_t modifier... " >&6; }
diff --git a/configure.ac b/configure.ac
index 10bfb994d4f..0560b9ce1a7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1985,11 +1985,6 @@ if test $ac_cv_alignof_int64_t -gt $MAX_ALIGNOF ; then
 fi
 AC_DEFINE_UNQUOTED(MAXIMUM_ALIGNOF, $MAX_ALIGNOF, [Define as the maximum alignment requirement of any C data type.])
 
-# Some platforms predefine the types int8, int16, etc.  Only check
-# a (hopefully) representative subset.
-AC_CHECK_TYPES([int8, uint8, int64, uint64], [], [],
-[#include <stdio.h>])
-
 # Check how to format int64_t without warnings from printf.
 PGAC_PRINTF_INT64_MODIFIER
 
diff --git a/src/include/c.h b/src/include/c.h
index 024213f37f3..dd140d2ae57 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -485,14 +485,10 @@ typedef char *Pointer;
  *		used for numerical computations and the
  *		frontend/backend protocol.
  */
-#ifndef HAVE_INT8
 typedef int8_t int8;			/* == 8 bits */
 typedef int16_t int16;			/* == 16 bits */
 typedef int32_t int32;			/* == 32 bits */
-#endif							/* not HAVE_INT8 */
-#ifndef HAVE_INT64
 typedef int64_t int64;			/* == 64 bits */
-#endif							/* not HAVE_INT64 */
 
 /*
  * uintN
@@ -500,14 +496,10 @@ typedef int64_t int64;			/* == 64 bits */
  *		used for numerical computations and the
  *		frontend/backend protocol.
  */
-#ifndef HAVE_UINT8
 typedef uint8_t uint8;			/* == 8 bits */
 typedef uint16_t uint16;		/* == 16 bits */
 typedef uint32_t uint32;		/* == 32 bits */
-#endif							/* not HAVE_UINT8 */
-#ifndef HAVE_UINT64
 typedef uint64_t uint64;		/* == 64 bits */
-#endif							/* not HAVE_UINT64 */
 
 /*
  * bitsN
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index 3755eb69e24..797f6ba3d64 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -213,12 +213,6 @@
 /* Define to 1 if you have the `inet_pton' function. */
 #undef HAVE_INET_PTON
 
-/* Define to 1 if the system has the type `int64'. */
-#undef HAVE_INT64
-
-/* Define to 1 if the system has the type `int8'. */
-#undef HAVE_INT8
-
 /* Define to 1 if you have the <inttypes.h> header file. */
 #undef HAVE_INTTYPES_H
 
@@ -465,12 +459,6 @@
 /* Define to 1 if you have the <ucred.h> header file. */
 #undef HAVE_UCRED_H
 
-/* Define to 1 if the system has the type `uint64'. */
-#undef HAVE_UINT64
-
-/* Define to 1 if the system has the type `uint8'. */
-#undef HAVE_UINT8
-
 /* Define to 1 if the system has the type `union semun'. */
 #undef HAVE_UNION_SEMUN
 
-- 
2.45.2

v3-0003-Allow-tzcode-to-use-stdint.h-and-inttypes.h.patchtext/x-patch; charset=US-ASCII; name=v3-0003-Allow-tzcode-to-use-stdint.h-and-inttypes.h.patchDownload
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

#27Tom Lane
tgl@sss.pgh.pa.us
In reply to: Thomas Munro (#26)
Re: Cannot find a working 64-bit integer type on Illumos

Thomas Munro <thomas.munro@gmail.com> writes:

New version attached. This time I was brave enough to try to tackle
src/timezone too, which had comments planning to drop a lot of small
differences against the upstream tzcode once all supported branches
required C99.

Unless you've specifically checked that this reduces diffs against
upstream tzcode, I'd really prefer not to touch that code right now.
I know I'm overdue for a round of syncing src/timezone/ with upstream,
but I can't see how drive-by changes will make that easier.

IMHO it's a rather scary choice on tzcode's part to use int_fastN_t,

Yeah, I was never pleased with that choice of theirs. OTOH, I've
seen darn few portability complaints on their mailing list, so
it seems like they've got it right in isolation. The problem
from our standpoint is that I don't think we want int_fastN_t
to leak into APIs visible to the rest of Postgres, because then
we risk issues related to their configuration methods being
totally unlike ours.

regards, tom lane

#28Thomas Munro
thomas.munro@gmail.com
In reply to: Tom Lane (#27)
Re: Cannot find a working 64-bit integer type on Illumos

On Thu, Jul 4, 2024 at 3:10 PM Tom Lane <tgl@sss.pgh.pa.us> wrote:

Unless you've specifically checked that this reduces diffs against
upstream tzcode, I'd really prefer not to touch that code right now.
I know I'm overdue for a round of syncing src/timezone/ with upstream,
but I can't see how drive-by changes will make that easier.

Sure, I'll wait until you say it's a good time. It does remove a
dozen or so hunks of difference, which should hopefully make that job
easier eventually but I don't want to get in your way. I can see
there are a few more trivialities we could synchronise on, like const
keywords, to kill useless diffs (either dropping local improvements or
sending patches upstream).

IMHO it's a rather scary choice on tzcode's part to use int_fastN_t,

Yeah, I was never pleased with that choice of theirs. OTOH, I've
seen darn few portability complaints on their mailing list, so
it seems like they've got it right in isolation. The problem
from our standpoint is that I don't think we want int_fastN_t
to leak into APIs visible to the rest of Postgres, because then
we risk issues related to their configuration methods being
totally unlike ours.

Yeah. My first swing at this touched only .c files, no .h files, with
that in mind.

#29Peter Eisentraut
peter@eisentraut.org
In reply to: Thomas Munro (#26)
Re: Cannot find a working 64-bit integer type on Illumos

On 04.07.24 03:55, Thomas Munro wrote:

Unfortunately, that theory turned out to be wrong. The usual suspect,
Windows, uses something else: "I64" or something like that. We could
teach our snprintf to grok that, but I don't like the idea anymore.
So let's go back to INT64_MODIFIER, with just a small amount of
configure time work to pick the right value. I couldn't figure out
any header-only way to do that.

src/port/snprintf.c used to support I64 in the past, but it was later
removed. We could probably put it back.

Personally, I find "PRId64" pretty unreadable. "INT64_MODIFIER" wasn't
nice either, though, and following standards is good, so I'm sure I'll
get used to it.

Using PRId64 would be very beneficial because gettext understands it,
and so we would no longer need the various workarounds for not putting
INT64_FORMAT into the middle of a translated string.

But this could be a separate patch. What you have works for now.

Here are some other comments on this patch set:

* v3-0001-Use-int64_t-support-from-stdint.h.patch

- src/include/c.h:

Maybe add a comment that above all the int8_t -> int8 etc. typedefs
that these are for backward compatibility or something like that.
Actually, just move the comment

+/* Historical names for limits in stdint.h. */

up a bit to it covers the types as well.

Also, these /* == 8 bits */ comments could be removed, I think.

- src/include/port/pg_bitutils.h:
- src/port/pg_bitutils.c:
- src/port/snprintf.c:

These changes look functionally correct, but I think I like the old
code layout better, like

#if (using long)
...
#elif (using long long)
...
#else
#error
#endif

rather than

#if (using long)
...
#else
static assertion
... // long long
#endif

which seems a bit more complicated. I think you could leave the code
mostly alone and just change

defined(HAVE_LONG_INT_64) to SIZEOF_LONG == 8
defined(HAVE_LONG_LONG_INT_64) to SIZEOF_LONG_LONG == 8

in each case.

- src/include/postgres_ext.h:

-#define OID_MAX  UINT_MAX
-/* you will need to include <limits.h> to use the above #define */
+#define OID_MAX  UINT32_MAX

If the type Oid is unsigned int, then the OID_MAX should be UINT_MAX.
So this should not be changed. Also, is the comment about <limits.h>
no longer applicable?

- src/interfaces/ecpg/ecpglib/typename.c:
- src/interfaces/ecpg/include/sqltypes.h:
- .../test/expected/compat_informix-sqlda.c:

-#ifdef HAVE_LONG_LONG_INT_64
+#if SIZEOF_LONG < 8

These changes alter the library behavior unnecessarily. The old code
would always prefer to report back long long (ECPGt_long_long etc.),
but the new code will report back long (ECPGt_long etc.) if it is
64-bit. I don't know the impact of these changes, but it seems
preferable to keep the existing behavior.

- src/interfaces/ecpg/include/ecpg_config.h.in:
- src/interfaces/ecpg/include/meson.build:

In the past, we have kept obsolete symbols as always defined in
ecpg_config.h. We ought to do the same here.

* v3-0002-Remove-traces-of-BeOS.patch

This looks ok. This could also be committed before 0001.

* v3-0003-Allow-tzcode-to-use-stdint.h-and-inttypes.h.patch

- src/timezone/localtime.c:

Addition of #include <stdint.h> is unnecessary, since it's already
included in c.h, and it's also not in the upstream code.

This looks like a typo:

-                                * 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
-getsecs(const char *strp, int32 *const secsp)
+getsecs(const char *strp, int_fast32_t * const secsp)

Need to add int_fast32_t (and maybe the other types) to typedefs.list?

- src/timezone/zic.c:

+#include <inttypes.h>
+#include <stdint.h>

We don't need both of these. Also, this is not in the upstream code
AFAICT.

#30Tom Lane
tgl@sss.pgh.pa.us
In reply to: Peter Eisentraut (#29)
Re: Cannot find a working 64-bit integer type on Illumos

Peter Eisentraut <peter@eisentraut.org> writes:

On 04.07.24 03:55, Thomas Munro wrote:

Personally, I find "PRId64" pretty unreadable. "INT64_MODIFIER" wasn't
nice either, though, and following standards is good, so I'm sure I'll
get used to it.

Using PRId64 would be very beneficial because gettext understands it,
and so we would no longer need the various workarounds for not putting
INT64_FORMAT into the middle of a translated string.

Uh, really? The translated strings live in /usr/share, which is
expected to be architecture-independent, so how would they make
that work?

regards, tom lane

#31Peter Eisentraut
peter@eisentraut.org
In reply to: Tom Lane (#30)
Re: Cannot find a working 64-bit integer type on Illumos

On 14.07.24 16:51, Tom Lane wrote:

Peter Eisentraut <peter@eisentraut.org> writes:

On 04.07.24 03:55, Thomas Munro wrote:

Personally, I find "PRId64" pretty unreadable. "INT64_MODIFIER" wasn't
nice either, though, and following standards is good, so I'm sure I'll
get used to it.

Using PRId64 would be very beneficial because gettext understands it,
and so we would no longer need the various workarounds for not putting
INT64_FORMAT into the middle of a translated string.

Uh, really? The translated strings live in /usr/share, which is
expected to be architecture-independent, so how would they make
that work?

Gettext has some special run-time support for this. See here:
<https://www.gnu.org/software/gettext/manual/html_node/Preparing-Strings.html#No-string-concatenation&gt;

#32Peter Eisentraut
peter@eisentraut.org
In reply to: Thomas Munro (#26)
Re: Cannot find a working 64-bit integer type on Illumos

To move this along a bit, I have committed the "Remove traces of BeOS."
patch.

#33Thomas Munro
thomas.munro@gmail.com
In reply to: Peter Eisentraut (#32)
1 attachment(s)
Re: Cannot find a working 64-bit integer type on Illumos

On Tue, Jul 23, 2024 at 2:39 AM Peter Eisentraut <peter@eisentraut.org> wrote:

On 14.07.24 16:51, Tom Lane wrote:

Peter Eisentraut <peter@eisentraut.org> writes:

On 04.07.24 03:55, Thomas Munro wrote:

Personally, I find "PRId64" pretty unreadable. "INT64_MODIFIER" wasn't
nice either, though, and following standards is good, so I'm sure I'll
get used to it.

Using PRId64 would be very beneficial because gettext understands it,
and so we would no longer need the various workarounds for not putting
INT64_FORMAT into the middle of a translated string.

Uh, really? The translated strings live in /usr/share, which is
expected to be architecture-independent, so how would they make
that work?

Gettext has some special run-time support for this. See here:
<https://www.gnu.org/software/gettext/manual/html_node/Preparing-Strings.html#No-string-concatenation&gt;

Nice. I've never really looked into gettext() very seriously, so I
wondered about the portability of it all. In our docs, a long time
ago, you wrote "... you need an implementation of the Gettext API.
Some operating systems have this built-in (e.g., Linux, NetBSD,
Solaris),". It looks like we might still have those implementations
of libintl.so in our build farm today: mostly the GNU one, but also
NetBSD's, illumos's, and to the unknowable extent it is different
Solaris's. They might all be using GNU msgfmt though.

I want to move this forward, but we have to decide which way. I'm now
leaning back towards using <inttypes.h> macros, based on your
feedback. So here's a rebase of v2, with some improvements, and some
responses to your earlier email:

On Mon, Jul 15, 2024 at 2:47 AM Peter Eisentraut <peter@eisentraut.org> wrote:

On 04.07.24 03:55, Thomas Munro wrote:

Unfortunately, that theory turned out to be wrong. The usual suspect,
Windows, uses something else: "I64" or something like that. We could
teach our snprintf to grok that, but I don't like the idea anymore.
So let's go back to INT64_MODIFIER, with just a small amount of
configure time work to pick the right value. I couldn't figure out
any header-only way to do that.

src/port/snprintf.c used to support I64 in the past, but it was later
removed. We could probably put it back.

New idea: let's just redefine PRI...{32,64,PTR} on that platform,
instead of modifying snprintf.c.

- src/include/c.h:

Maybe add a comment that above all the int8_t -> int8 etc. typedefs
that these are for backward compatibility or something like that.
Actually, just move the comment

+/* Historical names for limits in stdint.h. */

up a bit to it covers the types as well.

Hmm I think it deserves a separate comment but yeah "EXACTLY N BITS"
and can be "used for numerical computations" can definitely go. I
guess that's a memory of some pre-standard system that had similarly
named types with the "at least" meaning, but it's not helping anybody
today.

Also, these /* == 8 bits */ comments could be removed, I think.

Yeah.

- src/include/port/pg_bitutils.h:
- src/port/pg_bitutils.c:
- src/port/snprintf.c:

These changes look functionally correct, but I think I like the old
code layout better, like

#if (using long)
...
#elif (using long long)
...
#else
#error
#endif

rather than

#if (using long)
...
#else
static assertion
... // long long
#endif

Fair point, that was all a bit ugly. Let's see...

which seems a bit more complicated. I think you could leave the code
mostly alone and just change

defined(HAVE_LONG_INT_64) to SIZEOF_LONG == 8
defined(HAVE_LONG_LONG_INT_64) to SIZEOF_LONG_LONG == 8

in each case.

What do you think about this approach?

case 'z':
#if SIZEOF_SIZE_T == SIZEOF_LONG
longflag = 1;
#elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG
longlongflag = 1;
#else
#error "cannot find integer type of the same size as size_t"
#endif

And then in the cases where the size is implied by the typename
(uint64_t -> 8) it's the same setup except with a number:

#if SIZEOF_LONG == 8
return 63 - __builtin_clzl(word);
#elif SIZEOF_LONG_LONG == 8
return 63 - __builtin_clzll(word);
#else
#error "cannot find integer type of the same size as uint64_t"
#endif

What I like about that is that it's very clear that the conditions
match the ...l() or ...ll() function. It's obviously correct, and
would fail on a Deathstation 9000 that is trying to trick us.

- src/include/postgres_ext.h:

-#define OID_MAX  UINT_MAX
-/* you will need to include <limits.h> to use the above #define */
+#define OID_MAX  UINT32_MAX

If the type Oid is unsigned int, then the OID_MAX should be UINT_MAX.
So this should not be changed. Also, is the comment about <limits.h>
no longer applicable?

Right, yeah, hunk nuked.

- src/interfaces/ecpg/ecpglib/typename.c:
- src/interfaces/ecpg/include/sqltypes.h:
- .../test/expected/compat_informix-sqlda.c:

-#ifdef HAVE_LONG_LONG_INT_64
+#if SIZEOF_LONG < 8

These changes alter the library behavior unnecessarily. The old code
would always prefer to report back long long (ECPGt_long_long etc.),
but the new code will report back long (ECPGt_long etc.) if it is
64-bit. I don't know the impact of these changes, but it seems
preferable to keep the existing behavior.

I agree that it should be better but I don't think that's right about
the preference. The order of the tests here didn't matter, because
only HAVE_LONG_INT_64 would have been defined if sizeof(long) == 8,
not both, so it would still have preferred the first of { long, long
long } that had size 8 in that order. But yeah that's confusing,
let's try changing it to the same form as the cases above (an
explicitly search for the integer type of the same size where the
conditions are obviously correct with a clear priority and no
default/fallback/assumption, just an error):

case INT8OID:
#if SIZEOF_LONG == 8
return ECPGt_long;
#elif SIZEOF_LONG_LONG == 8
return ECPGt_long_long;
#else
#error "cannot find integer type of the same size as INT8OID"
#endif

- src/interfaces/ecpg/include/ecpg_config.h.in:
- src/interfaces/ecpg/include/meson.build:

In the past, we have kept obsolete symbols as always defined in
ecpg_config.h. We ought to do the same here.

Normally we keep symbols that were once conditional and are now
constant, like ENABLE_THREAD_SAFETY. Should that include
HAVE_LONG_INT_64 and HAVE_LONG_LONG_INT_64? Only one would be
defined, but it might be that neither is true in the patch: it's a
typedef for int64_t, and the standard library might well have a
typedef to __internal_int64_type, which is neither long nor long long.
it seems like internal machinery for giving the client code an "int64"
type in the C89 days, and surely not part of our real API.

WIP patch attached.

(Let's leave that tzcode stuff far later.)

Attachments:

v4-0001-Use-types-and-support-stdint.h-and-inttypes.h.patchapplication/octet-stream; name=v4-0001-Use-types-and-support-stdint.h-and-inttypes.h.patchDownload
From 3fa302632a9280e248ed5fce926a3af5a7898f55 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Thu, 18 Apr 2024 07:53:10 +1200
Subject: [PATCH v4] Use types and support <stdint.h> and <inttypes.h>.

Rebase our 64 bit integer support onto modern C including int64_t,
INT64_MAX, INT64_C(), PRId64 etc.

One complication is that Windows' <inttypes.h> uses format strings like
$I64d for PRId64 that our own snprintf.c doesn't understand.  Define our
own replacement macros that it can deal with.

Work in progress...

Reviewed-by: Peter Eisentraut <peter@eisentraut.org>
Discussion: https://postgr.es/m/ME3P282MB3166F9D1F71F787929C0C7E7B6312%40ME3P282MB3166.AUSP282.PROD.OUTLOOK.COM
---
 configure                                     | 263 ++++--------------
 configure.ac                                  |  47 +---
 meson.build                                   |  45 ++-
 src/Makefile.global.in                        |   6 -
 src/bin/pg_waldump/pg_waldump.c               |  16 +-
 src/bin/pgbench/pgbench.c                     |   4 +-
 src/include/.gitignore                        |   2 -
 src/include/Makefile                          |   8 +-
 src/include/c.h                               | 101 +++----
 src/include/meson.build                       |  10 -
 src/include/pg_config.h.in                    |  21 +-
 src/include/pg_config_ext.h.in                |   7 -
 src/include/pg_config_ext.h.meson             |   7 -
 src/include/port/pg_bitutils.h                |  16 +-
 src/include/port/win32_port.h                 |  47 ++++
 src/include/postgres_ext.h                    |   4 +-
 src/include/utils/dsa.h                       |   2 +-
 src/interfaces/ecpg/ecpglib/typename.c        |   9 +-
 src/interfaces/ecpg/include/ecpg_config.h.in  |   8 +-
 src/interfaces/ecpg/include/meson.build       |   4 +-
 .../ecpg/include/pgtypes_interval.h           |  12 +-
 src/interfaces/ecpg/include/sqltypes.h        |   8 +-
 .../test/expected/compat_informix-sqlda.c     |   8 +-
 src/port/pg_bitutils.c                        |   6 +-
 src/port/snprintf.c                           |  20 +-
 25 files changed, 218 insertions(+), 463 deletions(-)
 delete mode 100644 src/include/pg_config_ext.h.in
 delete mode 100644 src/include/pg_config_ext.h.meson

diff --git a/configure b/configure
index ff59f1422d8..2c12d104f79 100755
--- a/configure
+++ b/configure
@@ -16196,197 +16196,6 @@ fi
 # Run tests below here
 # --------------------
 
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether long int is 64 bits" >&5
-$as_echo_n "checking whether long int is 64 bits... " >&6; }
-if ${pgac_cv_type_long_int_64+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test "$cross_compiling" = yes; then :
-  # If cross-compiling, check the size reported by the compiler and
-# trust that the arithmetic works.
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-static int test_array [1 - 2 * !(sizeof(long int) == 8)];
-test_array [0] = 0;
-return test_array [0];
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  pgac_cv_type_long_int_64=yes
-else
-  pgac_cv_type_long_int_64=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-typedef long int ac_int64;
-
-/*
- * These are globals to discourage the compiler from folding all the
- * arithmetic tests down to compile-time constants.
- */
-ac_int64 a = 20000001;
-ac_int64 b = 40000005;
-
-int does_int64_work()
-{
-  ac_int64 c,d;
-
-  if (sizeof(ac_int64) != 8)
-    return 0;			/* definitely not the right size */
-
-  /* Do perfunctory checks to see if 64-bit arithmetic seems to work */
-  c = a * b;
-  d = (c + b) / b;
-  if (d != a+1)
-    return 0;
-  return 1;
-}
-
-int
-main() {
-  return (! does_int64_work());
-}
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
-  pgac_cv_type_long_int_64=yes
-else
-  pgac_cv_type_long_int_64=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
-  conftest.$ac_objext conftest.beam conftest.$ac_ext
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_type_long_int_64" >&5
-$as_echo "$pgac_cv_type_long_int_64" >&6; }
-
-HAVE_LONG_INT_64=$pgac_cv_type_long_int_64
-if test x"$pgac_cv_type_long_int_64" = xyes ; then
-
-$as_echo "#define HAVE_LONG_INT_64 1" >>confdefs.h
-
-fi
-
-
-if test x"$HAVE_LONG_INT_64" = x"yes" ; then
-  pg_int64_type="long int"
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether long long int is 64 bits" >&5
-$as_echo_n "checking whether long long int is 64 bits... " >&6; }
-if ${pgac_cv_type_long_long_int_64+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test "$cross_compiling" = yes; then :
-  # If cross-compiling, check the size reported by the compiler and
-# trust that the arithmetic works.
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-static int test_array [1 - 2 * !(sizeof(long long int) == 8)];
-test_array [0] = 0;
-return test_array [0];
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  pgac_cv_type_long_long_int_64=yes
-else
-  pgac_cv_type_long_long_int_64=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-typedef long long int ac_int64;
-
-/*
- * These are globals to discourage the compiler from folding all the
- * arithmetic tests down to compile-time constants.
- */
-ac_int64 a = 20000001;
-ac_int64 b = 40000005;
-
-int does_int64_work()
-{
-  ac_int64 c,d;
-
-  if (sizeof(ac_int64) != 8)
-    return 0;			/* definitely not the right size */
-
-  /* Do perfunctory checks to see if 64-bit arithmetic seems to work */
-  c = a * b;
-  d = (c + b) / b;
-  if (d != a+1)
-    return 0;
-  return 1;
-}
-
-int
-main() {
-  return (! does_int64_work());
-}
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
-  pgac_cv_type_long_long_int_64=yes
-else
-  pgac_cv_type_long_long_int_64=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
-  conftest.$ac_objext conftest.beam conftest.$ac_ext
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_type_long_long_int_64" >&5
-$as_echo "$pgac_cv_type_long_long_int_64" >&6; }
-
-HAVE_LONG_LONG_INT_64=$pgac_cv_type_long_long_int_64
-if test x"$pgac_cv_type_long_long_int_64" = xyes ; then
-
-$as_echo "#define HAVE_LONG_LONG_INT_64 1" >>confdefs.h
-
-fi
-
-  if test x"$HAVE_LONG_LONG_INT_64" = x"yes" ; then
-    pg_int64_type="long long int"
-  else
-    as_fn_error $? "Cannot find a working 64-bit integer type." "$LINENO" 5
-  fi
-fi
-
-
-cat >>confdefs.h <<_ACEOF
-#define PG_INT64_TYPE $pg_int64_type
-_ACEOF
-
-
-# Select the printf length modifier that goes with that, too.
-if test x"$pg_int64_type" = x"long long int" ; then
-  INT64_MODIFIER='"ll"'
-else
-  INT64_MODIFIER='"l"'
-fi
-
-
-cat >>confdefs.h <<_ACEOF
-#define INT64_MODIFIER $INT64_MODIFIER
-_ACEOF
-
-
 # has to be down here, rather than with the other builtins, because
 # the test uses PG_INT64_TYPE.
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_mul_overflow" >&5
@@ -16526,6 +16335,39 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long long" >&5
+$as_echo_n "checking size of long long... " >&6; }
+if ${ac_cv_sizeof_long_long+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long long))" "ac_cv_sizeof_long_long"        "$ac_includes_default"; then :
+
+else
+  if test "$ac_cv_type_long_long" = yes; then
+     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (long long)
+See \`config.log' for more details" "$LINENO" 5; }
+   else
+     ac_cv_sizeof_long_long=0
+   fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long_long" >&5
+$as_echo "$ac_cv_sizeof_long_long" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_LONG_LONG $ac_cv_sizeof_long_long
+_ACEOF
+
+
 
 # Determine memory alignment requirements for the basic C data types.
 
@@ -16634,43 +16476,41 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
-if test x"$HAVE_LONG_LONG_INT_64" = x"yes" ; then
-  # The cast to long int works around a bug in the HP C Compiler,
+# The cast to long int works around a bug in the HP C Compiler,
 # see AC_CHECK_SIZEOF for more information.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking alignment of long long int" >&5
-$as_echo_n "checking alignment of long long int... " >&6; }
-if ${ac_cv_alignof_long_long_int+:} false; then :
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking alignment of int64_t" >&5
+$as_echo_n "checking alignment of int64_t... " >&6; }
+if ${ac_cv_alignof_int64_t+:} false; then :
   $as_echo_n "(cached) " >&6
 else
-  if ac_fn_c_compute_int "$LINENO" "(long int) offsetof (ac__type_alignof_, y)" "ac_cv_alignof_long_long_int"        "$ac_includes_default
+  if ac_fn_c_compute_int "$LINENO" "(long int) offsetof (ac__type_alignof_, y)" "ac_cv_alignof_int64_t"        "$ac_includes_default
 #ifndef offsetof
 # define offsetof(type, member) ((char *) &((type *) 0)->member - (char *) 0)
 #endif
-typedef struct { char x; long long int y; } ac__type_alignof_;"; then :
+typedef struct { char x; int64_t y; } ac__type_alignof_;"; then :
 
 else
-  if test "$ac_cv_type_long_long_int" = yes; then
+  if test "$ac_cv_type_int64_t" = yes; then
      { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error 77 "cannot compute alignment of long long int
+as_fn_error 77 "cannot compute alignment of int64_t
 See \`config.log' for more details" "$LINENO" 5; }
    else
-     ac_cv_alignof_long_long_int=0
+     ac_cv_alignof_int64_t=0
    fi
 fi
 
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_alignof_long_long_int" >&5
-$as_echo "$ac_cv_alignof_long_long_int" >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_alignof_int64_t" >&5
+$as_echo "$ac_cv_alignof_int64_t" >&6; }
 
 
 
 cat >>confdefs.h <<_ACEOF
-#define ALIGNOF_LONG_LONG_INT $ac_cv_alignof_long_long_int
+#define ALIGNOF_INT64_T $ac_cv_alignof_int64_t
 _ACEOF
 
 
-fi
 # The cast to long int works around a bug in the HP C Compiler,
 # see AC_CHECK_SIZEOF for more information.
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking alignment of double" >&5
@@ -16728,8 +16568,8 @@ MAX_ALIGNOF=$ac_cv_alignof_double
 if test $ac_cv_alignof_long -gt $MAX_ALIGNOF ; then
   as_fn_error $? "alignment of 'long' is greater than the alignment of 'double'" "$LINENO" 5
 fi
-if test x"$HAVE_LONG_LONG_INT_64" = xyes && test $ac_cv_alignof_long_long_int -gt $MAX_ALIGNOF ; then
-  as_fn_error $? "alignment of 'long long int' is greater than the alignment of 'double'" "$LINENO" 5
+if test $ac_cv_alignof_int64_t -gt $MAX_ALIGNOF ; then
+  as_fn_error $? "alignment of 'int64_t' is greater than the alignment of 'double'" "$LINENO" 5
 fi
 
 cat >>confdefs.h <<_ACEOF
@@ -16737,7 +16577,6 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
-
 # Some compilers offer a 128-bit integer scalar type.
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __int128" >&5
 $as_echo_n "checking for __int128... " >&6; }
@@ -18954,9 +18793,6 @@ fi
 ac_config_headers="$ac_config_headers src/include/pg_config.h"
 
 
-ac_config_headers="$ac_config_headers src/include/pg_config_ext.h"
-
-
 ac_config_headers="$ac_config_headers src/interfaces/ecpg/include/ecpg_config.h"
 
 
@@ -19671,7 +19507,6 @@ do
     "src/Makefile.port") CONFIG_LINKS="$CONFIG_LINKS src/Makefile.port:src/makefiles/Makefile.${template}" ;;
     "check_win32_symlinks") CONFIG_COMMANDS="$CONFIG_COMMANDS check_win32_symlinks" ;;
     "src/include/pg_config.h") CONFIG_HEADERS="$CONFIG_HEADERS src/include/pg_config.h" ;;
-    "src/include/pg_config_ext.h") CONFIG_HEADERS="$CONFIG_HEADERS src/include/pg_config_ext.h" ;;
     "src/interfaces/ecpg/include/ecpg_config.h") CONFIG_HEADERS="$CONFIG_HEADERS src/interfaces/ecpg/include/ecpg_config.h" ;;
 
   *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
@@ -20279,10 +20114,6 @@ $as_echo "$as_me: WARNING: *** link for $FILE -- please fix by hand" >&2;}
     "src/include/pg_config.h":H)
 # Update timestamp for pg_config.h (see Makefile.global)
 echo >src/include/stamp-h
- ;;
-    "src/include/pg_config_ext.h":H)
-# Update timestamp for pg_config_ext.h (see Makefile.global)
-echo >src/include/stamp-ext-h
  ;;
     "src/interfaces/ecpg/include/ecpg_config.h":H) echo >src/interfaces/ecpg/include/stamp-h ;;
 
diff --git a/configure.ac b/configure.ac
index 21817009642..0e6d5819a03 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1906,37 +1906,6 @@ for the exact reason.]])],
 # Run tests below here
 # --------------------
 
-dnl Check to see if we have a working 64-bit integer type.
-dnl Since Postgres 8.4, we no longer support compilers without a working
-dnl 64-bit type; but we have to determine whether that type is called
-dnl "long int" or "long long int".
-
-PGAC_TYPE_64BIT_INT([long int])
-
-if test x"$HAVE_LONG_INT_64" = x"yes" ; then
-  pg_int64_type="long int"
-else
-  PGAC_TYPE_64BIT_INT([long long int])
-  if test x"$HAVE_LONG_LONG_INT_64" = x"yes" ; then
-    pg_int64_type="long long int"
-  else
-    AC_MSG_ERROR([Cannot find a working 64-bit integer type.])
-  fi
-fi
-
-AC_DEFINE_UNQUOTED(PG_INT64_TYPE, $pg_int64_type,
-  [Define to the name of a signed 64-bit integer type.])
-
-# Select the printf length modifier that goes with that, too.
-if test x"$pg_int64_type" = x"long long int" ; then
-  INT64_MODIFIER='"ll"'
-else
-  INT64_MODIFIER='"l"'
-fi
-
-AC_DEFINE_UNQUOTED(INT64_MODIFIER, $INT64_MODIFIER,
-                   [Define to the appropriate printf length modifier for 64-bit ints.])
-
 # has to be down here, rather than with the other builtins, because
 # the test uses PG_INT64_TYPE.
 PGAC_C_BUILTIN_OP_OVERFLOW
@@ -1945,15 +1914,14 @@ PGAC_C_BUILTIN_OP_OVERFLOW
 AC_CHECK_SIZEOF([void *])
 AC_CHECK_SIZEOF([size_t])
 AC_CHECK_SIZEOF([long])
+AC_CHECK_SIZEOF([long long])
 
 # Determine memory alignment requirements for the basic C data types.
 
 AC_CHECK_ALIGNOF(short)
 AC_CHECK_ALIGNOF(int)
 AC_CHECK_ALIGNOF(long)
-if test x"$HAVE_LONG_LONG_INT_64" = x"yes" ; then
-  AC_CHECK_ALIGNOF(long long int)
-fi
+AC_CHECK_ALIGNOF(int64_t)
 AC_CHECK_ALIGNOF(double)
 
 # Compute maximum alignment of any basic type.
@@ -1977,12 +1945,11 @@ MAX_ALIGNOF=$ac_cv_alignof_double
 if test $ac_cv_alignof_long -gt $MAX_ALIGNOF ; then
   AC_MSG_ERROR([alignment of 'long' is greater than the alignment of 'double'])
 fi
-if test x"$HAVE_LONG_LONG_INT_64" = xyes && test $ac_cv_alignof_long_long_int -gt $MAX_ALIGNOF ; then
-  AC_MSG_ERROR([alignment of 'long long int' is greater than the alignment of 'double'])
+if test $ac_cv_alignof_int64_t -gt $MAX_ALIGNOF ; then
+  AC_MSG_ERROR([alignment of 'int64_t' is greater than the alignment of 'double'])
 fi
 AC_DEFINE_UNQUOTED(MAXIMUM_ALIGNOF, $MAX_ALIGNOF, [Define as the maximum alignment requirement of any C data type.])
 
-
 # Some compilers offer a 128-bit integer scalar type.
 PGAC_TYPE_128BIT_INT
 
@@ -2472,12 +2439,6 @@ AC_CONFIG_HEADERS([src/include/pg_config.h],
 echo >src/include/stamp-h
 ])
 
-AC_CONFIG_HEADERS([src/include/pg_config_ext.h],
-[
-# Update timestamp for pg_config_ext.h (see Makefile.global)
-echo >src/include/stamp-ext-h
-])
-
 AC_CONFIG_HEADERS([src/interfaces/ecpg/include/ecpg_config.h],
                   [echo >src/interfaces/ecpg/include/stamp-h])
 
diff --git a/meson.build b/meson.build
index 451c3f6d851..bc47c7e5676 100644
--- a/meson.build
+++ b/meson.build
@@ -1588,21 +1588,6 @@ if not cc.compiles(c99_test, name: 'c99', args: test_c_args)
   endif
 endif
 
-sizeof_long = cc.sizeof('long', args: test_c_args)
-cdata.set('SIZEOF_LONG', sizeof_long)
-if sizeof_long == 8
-  cdata.set('HAVE_LONG_INT_64', 1)
-  pg_int64_type = 'long int'
-  cdata.set_quoted('INT64_MODIFIER', 'l')
-elif sizeof_long == 4 and cc.sizeof('long long', args: test_c_args) == 8
-  cdata.set('HAVE_LONG_LONG_INT_64', 1)
-  pg_int64_type = 'long long int'
-  cdata.set_quoted('INT64_MODIFIER', 'll')
-else
-  error('do not know how to get a 64bit int')
-endif
-cdata.set('PG_INT64_TYPE', pg_int64_type)
-
 if host_machine.endian() == 'big'
   cdata.set('WORDS_BIGENDIAN', 1)
 endif
@@ -1631,11 +1616,19 @@ endforeach
 # any types wider than 64 bits, as allowing MAXIMUM_ALIGNOF to exceed 8
 # would be too much of a penalty for disk and memory space.
 alignof_double = cdata.get('ALIGNOF_DOUBLE')
-if cc.alignment(pg_int64_type, args: test_c_args) > alignof_double
-  error('alignment of int64 is greater than the alignment of double')
+if cc.alignment('int64_t', args: test_c_args, prefix: '#include <stdint.h>') > alignof_double
+  error('alignment of int64_t is greater than the alignment of double')
 endif
 cdata.set('MAXIMUM_ALIGNOF', alignof_double)
 
+cdata.set('SIZEOF_LONG', cc.sizeof('long', args: test_c_args))
+cdata.set('SIZEOF_LONG_LONG', cc.sizeof('long long', args: test_c_args))
+cdata.set('SIZEOF_VOID_P', cc.sizeof('void *', args: test_c_args))
+cdata.set('SIZEOF_SIZE_T', cc.sizeof('size_t', args: test_c_args))
+
+
+# Check if __int128 is a working 128 bit integer type, and if so
+# define PG_INT128_TYPE to that typename.
 cdata.set('SIZEOF_VOID_P', cc.sizeof('void *', args: test_c_args))
 cdata.set('SIZEOF_SIZE_T', cc.sizeof('size_t', args: test_c_args))
 
@@ -1834,17 +1827,17 @@ endif
 # compile, and store the results in global variables so the compiler doesn't
 # optimize away the call.
 if cc.links('''
-    INT64 a = 1;
-    INT64 b = 1;
-    INT64 result;
+    #include <stdint.h>
+    int64_t a = 1;
+    int64_t b = 1;
+    int64_t result;
 
     int main(void)
     {
         return __builtin_mul_overflow(a, b, &result);
     }''',
     name: '__builtin_mul_overflow',
-    args: test_c_args + ['-DINT64=@0@'.format(cdata.get('PG_INT64_TYPE'))],
-    )
+    args: test_c_args)
   cdata.set('HAVE__BUILTIN_OP_OVERFLOW', 1)
 endif
 
@@ -2134,7 +2127,7 @@ int main(void)
   cdata.set(check['name'],
     cc.links(test,
       name: check['desc'],
-      args: test_c_args + ['-DINT64=@0@'.format(cdata.get('PG_INT64_TYPE'))]) ? 1 : false
+      args: test_c_args) ? 1 : false
   )
 endforeach
 
@@ -2172,6 +2165,7 @@ if host_cpu == 'x86_64'
 
   prog = '''
 #include <immintrin.h>
+#include <stdint.h>
 
 #if defined(__has_attribute) && __has_attribute (target)
 __attribute__((target("avx512vpopcntdq,avx512bw")))
@@ -2179,7 +2173,7 @@ __attribute__((target("avx512vpopcntdq,avx512bw")))
 int main(void)
 {
     const char buf[sizeof(__m512i)];
-    INT64 popcnt = 0;
+    int64_t popcnt = 0;
     __m512i accum = _mm512_setzero_si512();
     const __m512i val = _mm512_maskz_loadu_epi8((__mmask64) 0xf0f0f0f0f0f0f0f0, (const __m512i *) buf);
     const __m512i cnt = _mm512_popcnt_epi64(val);
@@ -2190,8 +2184,7 @@ int main(void)
 }
 '''
 
-  if cc.links(prog, name: 'AVX-512 popcount',
-        args: test_c_args + ['-DINT64=@0@'.format(cdata.get('PG_INT64_TYPE'))])
+  if cc.links(prog, name: 'AVX-512 popcount', args: test_c_args)
     cdata.set('USE_AVX512_POPCNT_WITH_RUNTIME_CHECK', 1)
   endif
 
diff --git a/src/Makefile.global.in b/src/Makefile.global.in
index 0f38d712d15..eac3d001211 100644
--- a/src/Makefile.global.in
+++ b/src/Makefile.global.in
@@ -840,12 +840,6 @@ $(top_builddir)/src/include/pg_config.h: $(top_builddir)/src/include/stamp-h ;
 $(top_builddir)/src/include/stamp-h: $(top_srcdir)/src/include/pg_config.h.in $(top_builddir)/config.status
 	cd $(top_builddir) && ./config.status src/include/pg_config.h
 
-# Also remake pg_config_ext.h from pg_config_ext.h.in, same logic as above.
-$(top_builddir)/src/include/pg_config_ext.h: $(top_builddir)/src/include/stamp-ext-h ;
-
-$(top_builddir)/src/include/stamp-ext-h: $(top_srcdir)/src/include/pg_config_ext.h.in $(top_builddir)/config.status
-	cd $(top_builddir) && ./config.status src/include/pg_config_ext.h
-
 # Also remake ecpg_config.h from ecpg_config.h.in if the latter changed, same
 # logic as above.
 $(top_builddir)/src/interfaces/ecpg/include/ecpg_config.h: $(top_builddir)/src/interfaces/ecpg/include/stamp-h ;
diff --git a/src/bin/pg_waldump/pg_waldump.c b/src/bin/pg_waldump/pg_waldump.c
index 1f9403fc5cf..c4b04d62965 100644
--- a/src/bin/pg_waldump/pg_waldump.c
+++ b/src/bin/pg_waldump/pg_waldump.c
@@ -610,10 +610,10 @@ XLogDumpStatsRow(const char *name,
 		tot_len_pct = 100 * (double) tot_len / total_len;
 
 	printf("%-27s "
-		   "%20" INT64_MODIFIER "u (%6.02f) "
-		   "%20" INT64_MODIFIER "u (%6.02f) "
-		   "%20" INT64_MODIFIER "u (%6.02f) "
-		   "%20" INT64_MODIFIER "u (%6.02f)\n",
+		   "%20" PRIu64 " (%6.02f) "
+		   "%20" PRIu64 " (%6.02f) "
+		   "%20" PRIu64 " (%6.02f) "
+		   "%20" PRIu64 " (%6.02f)\n",
 		   name, n, n_pct, rec_len, rec_len_pct, fpi_len, fpi_len_pct,
 		   tot_len, tot_len_pct);
 }
@@ -742,10 +742,10 @@ XLogDumpDisplayStats(XLogDumpConfig *config, XLogStats *stats)
 		fpi_len_pct = 100 * (double) total_fpi_len / total_len;
 
 	printf("%-27s "
-		   "%20" INT64_MODIFIER "u %-9s"
-		   "%20" INT64_MODIFIER "u %-9s"
-		   "%20" INT64_MODIFIER "u %-9s"
-		   "%20" INT64_MODIFIER "u %-6s\n",
+		   "%20" PRIu64 " %-9s"
+		   "%20" PRIu64 " %-9s"
+		   "%20" PRIu64 " %-9s"
+		   "%20" PRIu64 " %-6s\n",
 		   "Total", stats->count, "",
 		   total_rec_len, psprintf("[%.02f%%]", rec_len_pct),
 		   total_fpi_len, psprintf("[%.02f%%]", fpi_len_pct),
diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c
index 85e7b68baa3..c4c38099c5b 100644
--- a/src/bin/pgbench/pgbench.c
+++ b/src/bin/pgbench/pgbench.c
@@ -6568,13 +6568,13 @@ printResults(StatsData *total,
 					SimpleStats *cstats = &(*commands)->stats;
 
 					if (max_tries == 1)
-						printf("   %11.3f  %10" INT64_MODIFIER "d  %s\n",
+						printf("   %11.3f  %10" PRId64 " %s\n",
 							   (cstats->count > 0) ?
 							   1000.0 * cstats->sum / cstats->count : 0.0,
 							   (*commands)->failures,
 							   (*commands)->first_line);
 					else
-						printf("   %11.3f  %10" INT64_MODIFIER "d  %10" INT64_MODIFIER "d  %s\n",
+						printf("   %11.3f  %10" PRId64 " %10" PRId64 " %s\n",
 							   (cstats->count > 0) ?
 							   1000.0 * cstats->sum / cstats->count : 0.0,
 							   (*commands)->failures,
diff --git a/src/include/.gitignore b/src/include/.gitignore
index 51819fb4ddd..6e99e82fe0c 100644
--- a/src/include/.gitignore
+++ b/src/include/.gitignore
@@ -1,5 +1,3 @@
 /stamp-h
-/stamp-ext-h
 /pg_config.h
-/pg_config_ext.h
 /pg_config_os.h
diff --git a/src/include/Makefile b/src/include/Makefile
index b8b576a4de3..26332ff9cbc 100644
--- a/src/include/Makefile
+++ b/src/include/Makefile
@@ -13,7 +13,7 @@ top_builddir = ../..
 include $(top_builddir)/src/Makefile.global
 
 
-all: pg_config.h pg_config_ext.h pg_config_os.h
+all: pg_config.h pg_config_os.h
 
 
 # Subdirectories containing installable headers
@@ -32,7 +32,6 @@ install: all installdirs
 	$(INSTALL_DATA) $(srcdir)/postgres_ext.h   '$(DESTDIR)$(includedir)'
 	$(INSTALL_DATA) $(srcdir)/libpq/libpq-fs.h '$(DESTDIR)$(includedir)/libpq'
 	$(INSTALL_DATA) pg_config.h     '$(DESTDIR)$(includedir)'
-	$(INSTALL_DATA) pg_config_ext.h '$(DESTDIR)$(includedir)'
 	$(INSTALL_DATA) pg_config_os.h  '$(DESTDIR)$(includedir)'
 	$(INSTALL_DATA) $(srcdir)/pg_config_manual.h '$(DESTDIR)$(includedir)'
 # These headers are needed by the not-so-public headers of the interfaces.
@@ -43,7 +42,6 @@ install: all installdirs
 	$(INSTALL_DATA) $(srcdir)/libpq/protocol.h '$(DESTDIR)$(includedir_internal)/libpq'
 # These headers are needed for server-side development
 	$(INSTALL_DATA) pg_config.h     '$(DESTDIR)$(includedir_server)'
-	$(INSTALL_DATA) pg_config_ext.h '$(DESTDIR)$(includedir_server)'
 	$(INSTALL_DATA) pg_config_os.h  '$(DESTDIR)$(includedir_server)'
 	$(INSTALL_DATA) nodes/nodetags.h '$(DESTDIR)$(includedir_server)/nodes'
 	$(INSTALL_DATA) utils/errcodes.h '$(DESTDIR)$(includedir_server)/utils'
@@ -66,7 +64,7 @@ installdirs:
 
 
 uninstall:
-	rm -f $(addprefix '$(DESTDIR)$(includedir)'/, pg_config.h pg_config_ext.h pg_config_os.h pg_config_manual.h postgres_ext.h libpq/libpq-fs.h)
+	rm -f $(addprefix '$(DESTDIR)$(includedir)'/, pg_config.h pg_config_os.h pg_config_manual.h postgres_ext.h libpq/libpq-fs.h)
 	rm -f $(addprefix '$(DESTDIR)$(includedir_internal)'/, c.h port.h postgres_fe.h libpq/pqcomm.h libpq/protocol.h)
 # heuristic...
 	rm -rf $(addprefix '$(DESTDIR)$(includedir_server)'/, $(SUBDIRS) *.h)
@@ -80,4 +78,4 @@ clean:
 	$(MAKE) -C catalog clean
 
 distclean: clean
-	rm -f pg_config.h pg_config_ext.h pg_config_os.h stamp-h stamp-ext-h
+	rm -f pg_config.h pg_config_os.h stamp-h stamp-ext-h
diff --git a/src/include/c.h b/src/include/c.h
index 304dff27e34..734626e75a8 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -48,14 +48,12 @@
 
 #include "postgres_ext.h"
 
-/* Must undef pg_config_ext.h symbols before including pg_config.h */
-#undef PG_INT64_TYPE
-
 #include "pg_config.h"
 #include "pg_config_manual.h"	/* must be after pg_config.h */
 #include "pg_config_os.h"		/* must be before any system header files */
 
 /* System header files that should be available everywhere in Postgres */
+#include <inttypes.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -471,25 +469,15 @@ typedef void (*pg_funcptr_t) (void);
  */
 typedef char *Pointer;
 
-/*
- * intN
- *		Signed integer, EXACTLY N BITS IN SIZE,
- *		used for numerical computations and the
- *		frontend/backend protocol.
- */
-typedef signed char int8;		/* == 8 bits */
-typedef signed short int16;		/* == 16 bits */
-typedef signed int int32;		/* == 32 bits */
-
-/*
- * uintN
- *		Unsigned integer, EXACTLY N BITS IN SIZE,
- *		used for numerical computations and the
- *		frontend/backend protocol.
- */
-typedef unsigned char uint8;	/* == 8 bits */
-typedef unsigned short uint16;	/* == 16 bits */
-typedef unsigned int uint32;	/* == 32 bits */
+/* Historical names for types in <stdint.h>. */
+typedef int8_t int8;
+typedef int16_t int16;
+typedef int32_t int32;
+typedef int64_t int64;
+typedef uint8_t uint8;
+typedef uint16_t uint16;
+typedef uint32_t uint32;
+typedef uint64_t uint64;
 
 /*
  * bitsN
@@ -502,30 +490,14 @@ typedef uint32 bits32;			/* >= 32 bits */
 /*
  * 64-bit integers
  */
-#ifdef HAVE_LONG_INT_64
-/* Plain "long int" fits, use it */
-
-typedef long int int64;
-typedef unsigned long int uint64;
-#define INT64CONST(x)  (x##L)
-#define UINT64CONST(x) (x##UL)
-#elif defined(HAVE_LONG_LONG_INT_64)
-/* We have working support for "long long int", use that */
-
-typedef long long int int64;
-typedef unsigned long long int uint64;
-#define INT64CONST(x)  (x##LL)
-#define UINT64CONST(x) (x##ULL)
-#else
-/* neither HAVE_LONG_INT_64 nor HAVE_LONG_LONG_INT_64 */
-#error must have a working 64-bit integer datatype
-#endif
+#define INT64CONST(x)  INT64_C(x)
+#define UINT64CONST(x) UINT64_C(x)
 
 /* snprintf format strings to use for 64-bit integers */
-#define INT64_FORMAT "%" INT64_MODIFIER "d"
-#define UINT64_FORMAT "%" INT64_MODIFIER "u"
-#define INT64_HEX_FORMAT "%" INT64_MODIFIER "x"
-#define UINT64_HEX_FORMAT "%" INT64_MODIFIER "x"
+#define INT64_FORMAT "%" PRId64
+#define UINT64_FORMAT "%" PRIu64
+#define INT64_HEX_FORMAT "%" PRIx64
+#define UINT64_HEX_FORMAT "%" PRIx64
 
 /*
  * 128-bit signed and unsigned integers
@@ -554,22 +526,19 @@ typedef unsigned PG_INT128_TYPE uint128
 #endif
 #endif
 
-/*
- * stdint.h limits aren't guaranteed to have compatible types with our fixed
- * width types. So just define our own.
- */
-#define PG_INT8_MIN		(-0x7F-1)
-#define PG_INT8_MAX		(0x7F)
-#define PG_UINT8_MAX	(0xFF)
-#define PG_INT16_MIN	(-0x7FFF-1)
-#define PG_INT16_MAX	(0x7FFF)
-#define PG_UINT16_MAX	(0xFFFF)
-#define PG_INT32_MIN	(-0x7FFFFFFF-1)
-#define PG_INT32_MAX	(0x7FFFFFFF)
-#define PG_UINT32_MAX	(0xFFFFFFFFU)
-#define PG_INT64_MIN	(-INT64CONST(0x7FFFFFFFFFFFFFFF) - 1)
-#define PG_INT64_MAX	INT64CONST(0x7FFFFFFFFFFFFFFF)
-#define PG_UINT64_MAX	UINT64CONST(0xFFFFFFFFFFFFFFFF)
+/* Historical names for limits in <stdint.h>. */
+#define PG_INT8_MIN		INT8_MIN
+#define PG_INT8_MAX		INT8_MAX
+#define PG_UINT8_MAX	UINT8_MAX
+#define PG_INT16_MIN	INT16_MIN
+#define PG_INT16_MAX	INT16_MAX
+#define PG_UINT16_MAX	UINT16_MAX
+#define PG_INT32_MIN	INT32_MIN
+#define PG_INT32_MAX	INT32_MAX
+#define PG_UINT32_MAX	UINT32_MAX
+#define PG_INT64_MIN	INT64_MIN
+#define PG_INT64_MAX	INT64_MAX
+#define PG_UINT64_MAX	UINT64_MAX
 
 /*
  * We now always use int64 timestamps, but keep this symbol defined for the
@@ -1272,21 +1241,25 @@ extern int	fdatasync(int fildes);
  * definition of int64.  (For the naming, compare that POSIX has
  * strtoimax()/strtoumax() which return intmax_t/uintmax_t.)
  */
-#ifdef HAVE_LONG_INT_64
+#if SIZEOF_LONG == 8
 #define strtoi64(str, endptr, base) ((int64) strtol(str, endptr, base))
 #define strtou64(str, endptr, base) ((uint64) strtoul(str, endptr, base))
-#else
+#elif SIZEOF_LONG_LONG == 8
 #define strtoi64(str, endptr, base) ((int64) strtoll(str, endptr, base))
 #define strtou64(str, endptr, base) ((uint64) strtoull(str, endptr, base))
+#else
+#error "cannot find integer type of the same size as int64_t"
 #endif
 
 /*
  * Similarly, wrappers around labs()/llabs() matching our int64.
  */
-#ifdef HAVE_LONG_INT_64
+#if SIZEOF_LONG == 8
 #define i64abs(i) labs(i)
-#else
+#elif SIZEOF_LONG_LONG == 8
 #define i64abs(i) llabs(i)
+#else
+#error "cannot find integer type of the same size as int64_t"
 #endif
 
 /*
diff --git a/src/include/meson.build b/src/include/meson.build
index 58b7a9c1e7e..e691b12b8a0 100644
--- a/src/include/meson.build
+++ b/src/include/meson.build
@@ -1,14 +1,5 @@
 # Copyright (c) 2022-2024, PostgreSQL Global Development Group
 
-pg_config_ext = configure_file(
-  input: 'pg_config_ext.h.meson',
-  output: 'pg_config_ext.h',
-  configuration: cdata,
-  install: true,
-  install_dir: dir_include,
-)
-configure_files += pg_config_ext
-
 pg_config_os = configure_file(
   output: 'pg_config_os.h',
   input: files('port/@0@.h'.format(portname)),
@@ -116,7 +107,6 @@ install_headers(
   'postgres_fe.h',
   'varatt.h',
   'windowapi.h',
-  pg_config_ext,
   pg_config_os,
   pg_config,
   install_dir: dir_include_server,
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index ab0f8cc2b4a..55b73e74feb 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -9,12 +9,12 @@
 /* The normal alignment of `int', in bytes. */
 #undef ALIGNOF_INT
 
+/* The normal alignment of `int64_t', in bytes. */
+#undef ALIGNOF_INT64_T
+
 /* The normal alignment of `long', in bytes. */
 #undef ALIGNOF_LONG
 
-/* The normal alignment of `long long int', in bytes. */
-#undef ALIGNOF_LONG_LONG_INT
-
 /* The normal alignment of `PG_INT128_TYPE', in bytes. */
 #undef ALIGNOF_PG_INT128_TYPE
 
@@ -265,12 +265,6 @@
 /* Define to 1 if you have the `zstd' library (-lzstd). */
 #undef HAVE_LIBZSTD
 
-/* Define to 1 if `long int' works and is 64 bits. */
-#undef HAVE_LONG_INT_64
-
-/* Define to 1 if `long long int' works and is 64 bits. */
-#undef HAVE_LONG_LONG_INT_64
-
 /* Define to 1 if you have the <mbarrier.h> header file. */
 #undef HAVE_MBARRIER_H
 
@@ -544,9 +538,6 @@
 /* Define to 1 if your compiler understands _Static_assert. */
 #undef HAVE__STATIC_ASSERT
 
-/* Define to the appropriate printf length modifier for 64-bit ints. */
-#undef INT64_MODIFIER
-
 /* Define as the maximum alignment requirement of any C data type. */
 #undef MAXIMUM_ALIGNOF
 
@@ -578,9 +569,6 @@
 /* Define to the name of a signed 128-bit integer type. */
 #undef PG_INT128_TYPE
 
-/* Define to the name of a signed 64-bit integer type. */
-#undef PG_INT64_TYPE
-
 /* Define to the name of the default PostgreSQL service principal in Kerberos
    (GSSAPI). (--with-krb-srvnam=NAME) */
 #undef PG_KRB_SRVNAM
@@ -630,6 +618,9 @@
 /* The size of `long', as computed by sizeof. */
 #undef SIZEOF_LONG
 
+/* The size of `long long', as computed by sizeof. */
+#undef SIZEOF_LONG_LONG
+
 /* The size of `off_t', as computed by sizeof. */
 #undef SIZEOF_OFF_T
 
diff --git a/src/include/pg_config_ext.h.in b/src/include/pg_config_ext.h.in
deleted file mode 100644
index 8acadbdafd4..00000000000
--- a/src/include/pg_config_ext.h.in
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
- * src/include/pg_config_ext.h.in.  This is generated manually, not by
- * autoheader, since we want to limit which symbols get defined here.
- */
-
-/* Define to the name of a signed 64-bit integer type. */
-#undef PG_INT64_TYPE
diff --git a/src/include/pg_config_ext.h.meson b/src/include/pg_config_ext.h.meson
deleted file mode 100644
index 57cdfca0cfd..00000000000
--- a/src/include/pg_config_ext.h.meson
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
- * src/include/pg_config_ext.h.in.  This is generated manually, not by
- * autoheader, since we want to limit which symbols get defined here.
- */
-
-/* Define to the name of a signed 64-bit integer type. */
-#mesondefine PG_INT64_TYPE
diff --git a/src/include/port/pg_bitutils.h b/src/include/port/pg_bitutils.h
index 4d88478c9c2..a3cad46afe9 100644
--- a/src/include/port/pg_bitutils.h
+++ b/src/include/port/pg_bitutils.h
@@ -74,13 +74,13 @@ pg_leftmost_one_pos64(uint64 word)
 #ifdef HAVE__BUILTIN_CLZ
 	Assert(word != 0);
 
-#if defined(HAVE_LONG_INT_64)
+#if SIZEOF_LONG == 8
 	return 63 - __builtin_clzl(word);
-#elif defined(HAVE_LONG_LONG_INT_64)
+#elif SIZEOF_LONG_LONG == 8
 	return 63 - __builtin_clzll(word);
 #else
-#error must have a working 64-bit integer datatype
-#endif							/* HAVE_LONG_INT_64 */
+#error "cannot find integer type of the same size as uint64_t"
+#endif
 
 #elif defined(_MSC_VER) && (defined(_M_AMD64) || defined(_M_ARM64))
 	unsigned long result;
@@ -147,13 +147,13 @@ pg_rightmost_one_pos64(uint64 word)
 #ifdef HAVE__BUILTIN_CTZ
 	Assert(word != 0);
 
-#if defined(HAVE_LONG_INT_64)
+#if SIZEOF_LONG == 8
 	return __builtin_ctzl(word);
-#elif defined(HAVE_LONG_LONG_INT_64)
+#elif SIZEOF_LONG_LONG == 8
 	return __builtin_ctzll(word);
 #else
-#error must have a working 64-bit integer datatype
-#endif							/* HAVE_LONG_INT_64 */
+#error "cannot find integer type of the same size as uint64_t"
+#endif
 
 #elif defined(_MSC_VER) && (defined(_M_AMD64) || defined(_M_ARM64))
 	unsigned long result;
diff --git a/src/include/port/win32_port.h b/src/include/port/win32_port.h
index 7789e0431aa..8cc1e1bd4be 100644
--- a/src/include/port/win32_port.h
+++ b/src/include/port/win32_port.h
@@ -415,6 +415,53 @@ extern int	_pglstat64(const char *name, struct stat *buf);
 #undef ETIMEDOUT
 #define ETIMEDOUT WSAETIMEDOUT
 
+/*
+ * Adjustments to <inttypes.h>.  Windows has size prefixes "I64", "I32", "I"
+ * (intptr_t), but our snprintf.c is not expecting those.  Redefine them using
+ * traditional values that have the same effect.
+ */
+
+#undef PRId64
+#undef PRIu64
+#undef PRIx64
+#undef PRIX64
+#undef PRIo64
+#define PRId64 "lld"
+#define PRIu64 "llu"
+#define PRIx64 "llx"
+#define PRIX64 "llX"
+#define PRIo64 "llo"
+
+#undef PRId32
+#undef PRIu32
+#undef PRIx32
+#undef PRIX32
+#undef PRIo32
+#define PRId32 "d"
+#define PRIu32 "u"
+#define PRIx32 "x"
+#define PRIX32 "X"
+#define PRIo32 "o"
+
+#undef PRIdPTR
+#undef PRIuPTR
+#undef PRIxPTR
+#undef PRIXPTR
+#undef PRIoPTR
+#if SIZEOF_VOID_P == 8
+#define PRIdPTR PRId64
+#define PRIuPTR PRIu64
+#define PRIxPTR PRIx64
+#define PRIXPTR PRIX64
+#define PRIoPTR PRIo64
+#else
+#define PRIdPTR PRId32
+#define PRIuPTR PRIu32
+#define PRIxPTR PRIx32
+#define PRIXPTR PRIX32
+#define PRIoPTR PRIo32
+#endif
+
 /*
  * Supplement to <string.h>.
  */
diff --git a/src/include/postgres_ext.h b/src/include/postgres_ext.h
index 240ad4e93bf..202eb049622 100644
--- a/src/include/postgres_ext.h
+++ b/src/include/postgres_ext.h
@@ -23,7 +23,7 @@
 #ifndef POSTGRES_EXT_H
 #define POSTGRES_EXT_H
 
-#include "pg_config_ext.h"
+#include <stdint.h>
 
 /*
  * Object ID is a fundamental type in Postgres.
@@ -44,7 +44,7 @@ typedef unsigned int Oid;
 
 
 /* Define a signed 64-bit integer type for use in client API declarations. */
-typedef PG_INT64_TYPE pg_int64;
+typedef int64_t pg_int64;
 
 /*
  * Identifiers of error message fields.  Kept here to keep common
diff --git a/src/include/utils/dsa.h b/src/include/utils/dsa.h
index 8dff964bf33..6c952a43f79 100644
--- a/src/include/utils/dsa.h
+++ b/src/include/utils/dsa.h
@@ -66,7 +66,7 @@ typedef pg_atomic_uint64 dsa_pointer_atomic;
 #define dsa_pointer_atomic_write pg_atomic_write_u64
 #define dsa_pointer_atomic_fetch_add pg_atomic_fetch_add_u64
 #define dsa_pointer_atomic_compare_exchange pg_atomic_compare_exchange_u64
-#define DSA_POINTER_FORMAT "%016" INT64_MODIFIER "x"
+#define DSA_POINTER_FORMAT "%016" PRIx64
 #endif
 
 /* Flags for dsa_allocate_extended. */
diff --git a/src/interfaces/ecpg/ecpglib/typename.c b/src/interfaces/ecpg/ecpglib/typename.c
index 1d482c4fa61..1fb9860371b 100644
--- a/src/interfaces/ecpg/ecpglib/typename.c
+++ b/src/interfaces/ecpg/ecpglib/typename.c
@@ -131,11 +131,12 @@ sqlda_dynamic_type(Oid type, enum COMPAT_MODE compat)
 		case INTERVALOID:
 			return ECPGt_interval;
 		case INT8OID:
-#ifdef HAVE_LONG_LONG_INT_64
-			return ECPGt_long_long;
-#endif
-#ifdef HAVE_LONG_INT_64
+#if SIZEOF_LONG == 8
 			return ECPGt_long;
+#elif SIZEOF_LONG_LONG == 8
+			return ECPGt_long_long;
+#else
+#error "cannot find integer type of the same size as INT8OID"
 #endif
 			/* Unhandled types always return a string */
 		default:
diff --git a/src/interfaces/ecpg/include/ecpg_config.h.in b/src/interfaces/ecpg/include/ecpg_config.h.in
index 75f542f263b..4af45930b61 100644
--- a/src/interfaces/ecpg/include/ecpg_config.h.in
+++ b/src/interfaces/ecpg/include/ecpg_config.h.in
@@ -1,8 +1,8 @@
 /* Define to 1 to build client libraries as thread-safe code. */
 #define ENABLE_THREAD_SAFETY 1
 
-/* Define to 1 if `long int' works and is 64 bits. */
-#undef HAVE_LONG_INT_64
+/* The size of `long', as computed by sizeof. */
+#undef SIZEOF_LONG
 
-/* Define to 1 if `long long int' works and is 64 bits. */
-#undef HAVE_LONG_LONG_INT_64
+/* The size of `long long', as computed by sizeof. */
+#undef SIZEOF_LONG_LONG
diff --git a/src/interfaces/ecpg/include/meson.build b/src/interfaces/ecpg/include/meson.build
index a3beb3cc7be..c1a88e73fb8 100644
--- a/src/interfaces/ecpg/include/meson.build
+++ b/src/interfaces/ecpg/include/meson.build
@@ -3,8 +3,8 @@
 ecpg_inc = include_directories('.')
 
 ecpg_conf_keys = [
-  'HAVE_LONG_INT_64',
-  'HAVE_LONG_LONG_INT_64',
+  'SIZEOF_LONG',
+  'SIZEOF_LONG_LONG',
 ]
 
 ecpg_conf_data = configuration_data()
diff --git a/src/interfaces/ecpg/include/pgtypes_interval.h b/src/interfaces/ecpg/include/pgtypes_interval.h
index 46cfce65517..f0acbb4512a 100644
--- a/src/interfaces/ecpg/include/pgtypes_interval.h
+++ b/src/interfaces/ecpg/include/pgtypes_interval.h
@@ -3,21 +3,17 @@
 #ifndef PGTYPES_INTERVAL
 #define PGTYPES_INTERVAL
 
+#include <stdint.h>
+
 #include <ecpg_config.h>
 #include <pgtypes.h>
 
 #ifndef C_H
 
-#ifdef HAVE_LONG_INT_64
-typedef long int int64;
-#elif defined(HAVE_LONG_LONG_INT_64)
-typedef long long int int64;
-#else
-/* neither HAVE_LONG_INT_64 nor HAVE_LONG_LONG_INT_64 */
-#error must have a working 64-bit integer datatype
-#endif
+typedef int64_t int64;
 
 #define HAVE_INT64_TIMESTAMP
+
 #endif							/* C_H */
 
 typedef struct
diff --git a/src/interfaces/ecpg/include/sqltypes.h b/src/interfaces/ecpg/include/sqltypes.h
index e7cbfa47956..498840458c4 100644
--- a/src/interfaces/ecpg/include/sqltypes.h
+++ b/src/interfaces/ecpg/include/sqltypes.h
@@ -46,12 +46,14 @@
 #define SQLINTERVAL		ECPGt_interval
 #define SQLNCHAR	ECPGt_char
 #define SQLNVCHAR	ECPGt_char
-#ifdef HAVE_LONG_LONG_INT_64
+#if SIZEOF_LONG == 8
+#define SQLINT8		ECPGt_long
+#define SQLSERIAL8	ECPGt_long
+#elif SIZEOF_LONG_LONG == 8
 #define SQLINT8		ECPGt_long_long
 #define SQLSERIAL8	ECPGt_long_long
 #else
-#define SQLINT8		ECPGt_long
-#define SQLSERIAL8	ECPGt_long
+#error "cannot find integer type of the same size as SQLINT8"
 #endif
 
 #endif							/* ndef ECPG_SQLTYPES_H */
diff --git a/src/interfaces/ecpg/test/expected/compat_informix-sqlda.c b/src/interfaces/ecpg/test/expected/compat_informix-sqlda.c
index 7e19319d27f..8eebc51664e 100644
--- a/src/interfaces/ecpg/test/expected/compat_informix-sqlda.c
+++ b/src/interfaces/ecpg/test/expected/compat_informix-sqlda.c
@@ -97,12 +97,14 @@ typedef struct sqlda_struct sqlda_t;
 #define SQLINTERVAL		ECPGt_interval
 #define SQLNCHAR	ECPGt_char
 #define SQLNVCHAR	ECPGt_char
-#ifdef HAVE_LONG_LONG_INT_64
+#if SIZEOF_LONG == 8
+#define SQLINT8		ECPGt_long
+#define SQLSERIAL8	ECPGt_long
+#elif SIZEOF_LONG_LONG == 8
 #define SQLINT8		ECPGt_long_long
 #define SQLSERIAL8	ECPGt_long_long
 #else
-#define SQLINT8		ECPGt_long
-#define SQLSERIAL8	ECPGt_long
+#error "cannot find integer type of the same size as SQLINT8"
 #endif
 
 #endif							/* ndef ECPG_SQLTYPES_H */
diff --git a/src/port/pg_bitutils.c b/src/port/pg_bitutils.c
index 87f56e82b80..c8399981ee0 100644
--- a/src/port/pg_bitutils.c
+++ b/src/port/pg_bitutils.c
@@ -370,12 +370,12 @@ static inline int
 pg_popcount64_slow(uint64 word)
 {
 #ifdef HAVE__BUILTIN_POPCOUNT
-#if defined(HAVE_LONG_INT_64)
+#if SIZEOF_LONG == 8
 	return __builtin_popcountl(word);
-#elif defined(HAVE_LONG_LONG_INT_64)
+#elif SIZEOF_LONG_LONG == 8
 	return __builtin_popcountll(word);
 #else
-#error must have a working 64-bit integer datatype
+#error "cannot find integer of the same size as uint64_t"
 #endif
 #else							/* !HAVE__BUILTIN_POPCOUNT */
 	int			result = 0;
diff --git a/src/port/snprintf.c b/src/port/snprintf.c
index 884f0262dd1..eba6437cceb 100644
--- a/src/port/snprintf.c
+++ b/src/port/snprintf.c
@@ -567,16 +567,12 @@ nextch2:
 					longflag = 1;
 				goto nextch2;
 			case 'z':
-#if SIZEOF_SIZE_T == 8
-#ifdef HAVE_LONG_INT_64
+#if SIZEOF_SIZE_T == SIZEOF_LONG
 				longflag = 1;
-#elif defined(HAVE_LONG_LONG_INT_64)
+#elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG
 				longlongflag = 1;
 #else
-#error "Don't know how to print 64bit integers"
-#endif
-#else
-				/* assume size_t is same size as int */
+#error "cannot find integer type of the same size as size_t"
 #endif
 				goto nextch2;
 			case 'h':
@@ -834,16 +830,12 @@ nextch1:
 					longflag = 1;
 				goto nextch1;
 			case 'z':
-#if SIZEOF_SIZE_T == 8
-#ifdef HAVE_LONG_INT_64
+#if SIZEOF_SIZE_T == SIZEOF_LONG
 				longflag = 1;
-#elif defined(HAVE_LONG_LONG_INT_64)
+#elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG
 				longlongflag = 1;
 #else
-#error "Don't know how to print 64bit integers"
-#endif
-#else
-				/* assume size_t is same size as int */
+#error "cannot find integer type of the same size as size_t"
 #endif
 				goto nextch1;
 			case 'h':
-- 
2.39.5 (Apple Git-154)

#34Thomas Munro
thomas.munro@gmail.com
In reply to: Thomas Munro (#33)
1 attachment(s)
Re: Cannot find a working 64-bit integer type on Illumos

On Fri, Nov 29, 2024 at 11:12 PM Thomas Munro <thomas.munro@gmail.com> wrote:

WIP patch attached.

Slightly better version. I'd missed some configure stuff that could
be removed, and tidied up a few minor typos and mistakes.

I was thinking about that ECPG stuff: I bet real applications prefer
to use int64_t etc directly too instead of long, the worst type in C.
I wondered if the embedded SQL standard might know about that these
days (ECPGt_int64_t?), but I don't have the standard to hand. DB2's
embedded SQL seems to have a type sqlint64, but I didn't look too
closely and of course even if we wanted to do something like that as
an optional API option, that'd be a later change.

BTW I forgot to mention earlier, I peeked at the source of gettext on
NetBSD and illumos, and both appear to handle those special
<inttypes.h> tokens when loading message catalogues.

Attachments:

v5-0001-Use-stdint.h-and-inttypes.h-for-integer-types.patchapplication/octet-stream; name=v5-0001-Use-stdint.h-and-inttypes.h-for-integer-types.patchDownload
From 90839bef67527935f190893d04be9430fb6b9b2e Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Thu, 18 Apr 2024 07:53:10 +1200
Subject: [PATCH v5] Use <stdint.h> and <inttypes.h> for integer types.

Use standard types and support for 64 bit integers, including int64_t,
INT64_MAX, INT64_C(), PRId64 etc.  Also use standard definitions of the
smaller integers.

One complication is that Windows' <inttypes.h> uses format strings like
%I64d for PRId64 that our own snprintf.c doesn't understand.  Define our
own replacement macros that it can deal with.

Work in progress...

Reviewed-by: Peter Eisentraut <peter@eisentraut.org>
Discussion: https://postgr.es/m/ME3P282MB3166F9D1F71F787929C0C7E7B6312%40ME3P282MB3166.AUSP282.PROD.OUTLOOK.COM
---
 config/c-compiler.m4                          |  78 +---
 configure                                     | 354 +++++-------------
 configure.ac                                  |  52 +--
 meson.build                                   |  44 +--
 src/Makefile.global.in                        |   6 -
 src/bin/pg_waldump/pg_waldump.c               |  16 +-
 src/bin/pgbench/pgbench.c                     |   4 +-
 src/include/.gitignore                        |   2 -
 src/include/Makefile                          |   8 +-
 src/include/c.h                               | 101 ++---
 src/include/meson.build                       |  10 -
 src/include/pg_config.h.in                    |  25 +-
 src/include/pg_config_ext.h.in                |   7 -
 src/include/pg_config_ext.h.meson             |   7 -
 src/include/port/pg_bitutils.h                |  16 +-
 src/include/port/win32_port.h                 |  47 +++
 src/include/postgres_ext.h                    |   4 +-
 src/include/utils/dsa.h                       |   2 +-
 src/interfaces/ecpg/ecpglib/typename.c        |   9 +-
 src/interfaces/ecpg/include/ecpg_config.h.in  |   8 +-
 src/interfaces/ecpg/include/meson.build       |   4 +-
 .../ecpg/include/pgtypes_interval.h           |  12 +-
 src/interfaces/ecpg/include/sqltypes.h        |   8 +-
 .../test/expected/compat_informix-sqlda.c     |   8 +-
 src/port/pg_bitutils.c                        |   6 +-
 src/port/snprintf.c                           |  20 +-
 26 files changed, 277 insertions(+), 581 deletions(-)
 delete mode 100644 src/include/pg_config_ext.h.in
 delete mode 100644 src/include/pg_config_ext.h.meson

diff --git a/config/c-compiler.m4 b/config/c-compiler.m4
index 309d5b04b46..e112fd45d48 100644
--- a/config/c-compiler.m4
+++ b/config/c-compiler.m4
@@ -38,60 +38,6 @@ ac_c_werror_flag=$ac_save_c_werror_flag
 ])# PGAC_TEST_PRINTF_ARCHETYPE
 
 
-# PGAC_TYPE_64BIT_INT(TYPE)
-# -------------------------
-# Check if TYPE is a working 64 bit integer type. Set HAVE_TYPE_64 to
-# yes or no respectively, and define HAVE_TYPE_64 if yes.
-AC_DEFUN([PGAC_TYPE_64BIT_INT],
-[define([Ac_define], [translit([have_$1_64], [a-z *], [A-Z_P])])dnl
-define([Ac_cachevar], [translit([pgac_cv_type_$1_64], [ *], [_p])])dnl
-AC_CACHE_CHECK([whether $1 is 64 bits], [Ac_cachevar],
-[AC_RUN_IFELSE([AC_LANG_SOURCE(
-[typedef $1 ac_int64;
-
-/*
- * These are globals to discourage the compiler from folding all the
- * arithmetic tests down to compile-time constants.
- */
-ac_int64 a = 20000001;
-ac_int64 b = 40000005;
-
-int does_int64_work()
-{
-  ac_int64 c,d;
-
-  if (sizeof(ac_int64) != 8)
-    return 0;			/* definitely not the right size */
-
-  /* Do perfunctory checks to see if 64-bit arithmetic seems to work */
-  c = a * b;
-  d = (c + b) / b;
-  if (d != a+1)
-    return 0;
-  return 1;
-}
-
-int
-main() {
-  return (! does_int64_work());
-}])],
-[Ac_cachevar=yes],
-[Ac_cachevar=no],
-[# If cross-compiling, check the size reported by the compiler and
-# trust that the arithmetic works.
-AC_COMPILE_IFELSE([AC_LANG_BOOL_COMPILE_TRY([], [sizeof($1) == 8])],
-                  Ac_cachevar=yes,
-                  Ac_cachevar=no)])])
-
-Ac_define=$Ac_cachevar
-if test x"$Ac_cachevar" = xyes ; then
-  AC_DEFINE(Ac_define, 1, [Define to 1 if `]$1[' works and is 64 bits.])
-fi
-undefine([Ac_define])dnl
-undefine([Ac_cachevar])dnl
-])# PGAC_TYPE_64BIT_INT
-
-
 # PGAC_TYPE_128BIT_INT
 # --------------------
 # Check if __int128 is a working 128 bit integer type, and if so
@@ -270,9 +216,10 @@ fi])# PGAC_C_BUILTIN_CONSTANT_P
 AC_DEFUN([PGAC_C_BUILTIN_OP_OVERFLOW],
 [AC_CACHE_CHECK(for __builtin_mul_overflow, pgac_cv__builtin_op_overflow,
 [AC_LINK_IFELSE([AC_LANG_PROGRAM([
-PG_INT64_TYPE a = 1;
-PG_INT64_TYPE b = 1;
-PG_INT64_TYPE result;
+#include <stdint.h>
+int64_t a = 1;
+int64_t b = 1;
+int64_t result;
 int oflo;
 ],
 [oflo = __builtin_mul_overflow(a, b, &result);])],
@@ -557,13 +504,13 @@ fi])# PGAC_HAVE_GCC__SYNC_INT32_CAS
 # types, and define HAVE_GCC__SYNC_INT64_CAS if so.
 AC_DEFUN([PGAC_HAVE_GCC__SYNC_INT64_CAS],
 [AC_CACHE_CHECK(for builtin __sync int64 atomic operations, pgac_cv_gcc_sync_int64_cas,
-[AC_LINK_IFELSE([AC_LANG_PROGRAM([],
-  [PG_INT64_TYPE lock = 0;
-   __sync_val_compare_and_swap(&lock, 0, (PG_INT64_TYPE) 37);])],
+[AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <stdint.h>],
+  [int64_t lock = 0;
+   __sync_val_compare_and_swap(&lock, 0, (int64_t) 37);])],
   [pgac_cv_gcc_sync_int64_cas="yes"],
   [pgac_cv_gcc_sync_int64_cas="no"])])
 if test x"$pgac_cv_gcc_sync_int64_cas" = x"yes"; then
-  AC_DEFINE(HAVE_GCC__SYNC_INT64_CAS, 1, [Define to 1 if you have __sync_val_compare_and_swap(int64 *, int64, int64).])
+  AC_DEFINE(HAVE_GCC__SYNC_INT64_CAS, 1, [Define to 1 if you have __sync_val_compare_and_swap(int64_t *, int64_t, int64_t).])
 fi])# PGAC_HAVE_GCC__SYNC_INT64_CAS
 
 # PGAC_HAVE_GCC__ATOMIC_INT32_CAS
@@ -588,9 +535,9 @@ fi])# PGAC_HAVE_GCC__ATOMIC_INT32_CAS
 # types, and define HAVE_GCC__ATOMIC_INT64_CAS if so.
 AC_DEFUN([PGAC_HAVE_GCC__ATOMIC_INT64_CAS],
 [AC_CACHE_CHECK(for builtin __atomic int64 atomic operations, pgac_cv_gcc_atomic_int64_cas,
-[AC_LINK_IFELSE([AC_LANG_PROGRAM([],
-  [PG_INT64_TYPE val = 0;
-   PG_INT64_TYPE expect = 0;
+[AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <stdint.h>],
+  [int64_t val = 0;
+   int64_t expect = 0;
    __atomic_compare_exchange_n(&val, &expect, 37, 0, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);])],
   [pgac_cv_gcc_atomic_int64_cas="yes"],
   [pgac_cv_gcc_atomic_int64_cas="no"])])
@@ -734,13 +681,14 @@ AC_DEFUN([PGAC_AVX512_POPCNT_INTRINSICS],
 [define([Ac_cachevar], [AS_TR_SH([pgac_cv_avx512_popcnt_intrinsics])])dnl
 AC_CACHE_CHECK([for _mm512_popcnt_epi64], [Ac_cachevar],
 [AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <immintrin.h>
+    #include <stdint.h>
     #if defined(__has_attribute) && __has_attribute (target)
     __attribute__((target("avx512vpopcntdq,avx512bw")))
     #endif
     static int popcount_test(void)
     {
       const char buf@<:@sizeof(__m512i)@:>@;
-      PG_INT64_TYPE popcnt = 0;
+      int64_t popcnt = 0;
       __m512i accum = _mm512_setzero_si512();
       const __m512i val = _mm512_maskz_loadu_epi8((__mmask64) 0xf0f0f0f0f0f0f0f0, (const __m512i *) buf);
       const __m512i cnt = _mm512_popcnt_epi64(val);
diff --git a/configure b/configure
index ff59f1422d8..bc49cebc990 100755
--- a/configure
+++ b/configure
@@ -14436,6 +14436,43 @@ if test x"$pgac_cv__builtin_constant_p" = xyes ; then
 
 $as_echo "#define HAVE__BUILTIN_CONSTANT_P 1" >>confdefs.h
 
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_mul_overflow" >&5
+$as_echo_n "checking for __builtin_mul_overflow... " >&6; }
+if ${pgac_cv__builtin_op_overflow+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <stdint.h>
+int64_t a = 1;
+int64_t b = 1;
+int64_t result;
+int oflo;
+
+int
+main ()
+{
+oflo = __builtin_mul_overflow(a, b, &result);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  pgac_cv__builtin_op_overflow=yes
+else
+  pgac_cv__builtin_op_overflow=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv__builtin_op_overflow" >&5
+$as_echo "$pgac_cv__builtin_op_overflow" >&6; }
+if test x"$pgac_cv__builtin_op_overflow" = xyes ; then
+
+$as_echo "#define HAVE__BUILTIN_OP_OVERFLOW 1" >>confdefs.h
+
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_unreachable" >&5
 $as_echo_n "checking for __builtin_unreachable... " >&6; }
@@ -16196,236 +16233,6 @@ fi
 # Run tests below here
 # --------------------
 
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether long int is 64 bits" >&5
-$as_echo_n "checking whether long int is 64 bits... " >&6; }
-if ${pgac_cv_type_long_int_64+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test "$cross_compiling" = yes; then :
-  # If cross-compiling, check the size reported by the compiler and
-# trust that the arithmetic works.
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-static int test_array [1 - 2 * !(sizeof(long int) == 8)];
-test_array [0] = 0;
-return test_array [0];
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  pgac_cv_type_long_int_64=yes
-else
-  pgac_cv_type_long_int_64=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-typedef long int ac_int64;
-
-/*
- * These are globals to discourage the compiler from folding all the
- * arithmetic tests down to compile-time constants.
- */
-ac_int64 a = 20000001;
-ac_int64 b = 40000005;
-
-int does_int64_work()
-{
-  ac_int64 c,d;
-
-  if (sizeof(ac_int64) != 8)
-    return 0;			/* definitely not the right size */
-
-  /* Do perfunctory checks to see if 64-bit arithmetic seems to work */
-  c = a * b;
-  d = (c + b) / b;
-  if (d != a+1)
-    return 0;
-  return 1;
-}
-
-int
-main() {
-  return (! does_int64_work());
-}
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
-  pgac_cv_type_long_int_64=yes
-else
-  pgac_cv_type_long_int_64=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
-  conftest.$ac_objext conftest.beam conftest.$ac_ext
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_type_long_int_64" >&5
-$as_echo "$pgac_cv_type_long_int_64" >&6; }
-
-HAVE_LONG_INT_64=$pgac_cv_type_long_int_64
-if test x"$pgac_cv_type_long_int_64" = xyes ; then
-
-$as_echo "#define HAVE_LONG_INT_64 1" >>confdefs.h
-
-fi
-
-
-if test x"$HAVE_LONG_INT_64" = x"yes" ; then
-  pg_int64_type="long int"
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether long long int is 64 bits" >&5
-$as_echo_n "checking whether long long int is 64 bits... " >&6; }
-if ${pgac_cv_type_long_long_int_64+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test "$cross_compiling" = yes; then :
-  # If cross-compiling, check the size reported by the compiler and
-# trust that the arithmetic works.
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-static int test_array [1 - 2 * !(sizeof(long long int) == 8)];
-test_array [0] = 0;
-return test_array [0];
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  pgac_cv_type_long_long_int_64=yes
-else
-  pgac_cv_type_long_long_int_64=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-typedef long long int ac_int64;
-
-/*
- * These are globals to discourage the compiler from folding all the
- * arithmetic tests down to compile-time constants.
- */
-ac_int64 a = 20000001;
-ac_int64 b = 40000005;
-
-int does_int64_work()
-{
-  ac_int64 c,d;
-
-  if (sizeof(ac_int64) != 8)
-    return 0;			/* definitely not the right size */
-
-  /* Do perfunctory checks to see if 64-bit arithmetic seems to work */
-  c = a * b;
-  d = (c + b) / b;
-  if (d != a+1)
-    return 0;
-  return 1;
-}
-
-int
-main() {
-  return (! does_int64_work());
-}
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
-  pgac_cv_type_long_long_int_64=yes
-else
-  pgac_cv_type_long_long_int_64=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
-  conftest.$ac_objext conftest.beam conftest.$ac_ext
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_type_long_long_int_64" >&5
-$as_echo "$pgac_cv_type_long_long_int_64" >&6; }
-
-HAVE_LONG_LONG_INT_64=$pgac_cv_type_long_long_int_64
-if test x"$pgac_cv_type_long_long_int_64" = xyes ; then
-
-$as_echo "#define HAVE_LONG_LONG_INT_64 1" >>confdefs.h
-
-fi
-
-  if test x"$HAVE_LONG_LONG_INT_64" = x"yes" ; then
-    pg_int64_type="long long int"
-  else
-    as_fn_error $? "Cannot find a working 64-bit integer type." "$LINENO" 5
-  fi
-fi
-
-
-cat >>confdefs.h <<_ACEOF
-#define PG_INT64_TYPE $pg_int64_type
-_ACEOF
-
-
-# Select the printf length modifier that goes with that, too.
-if test x"$pg_int64_type" = x"long long int" ; then
-  INT64_MODIFIER='"ll"'
-else
-  INT64_MODIFIER='"l"'
-fi
-
-
-cat >>confdefs.h <<_ACEOF
-#define INT64_MODIFIER $INT64_MODIFIER
-_ACEOF
-
-
-# has to be down here, rather than with the other builtins, because
-# the test uses PG_INT64_TYPE.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_mul_overflow" >&5
-$as_echo_n "checking for __builtin_mul_overflow... " >&6; }
-if ${pgac_cv__builtin_op_overflow+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-PG_INT64_TYPE a = 1;
-PG_INT64_TYPE b = 1;
-PG_INT64_TYPE result;
-int oflo;
-
-int
-main ()
-{
-oflo = __builtin_mul_overflow(a, b, &result);
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-  pgac_cv__builtin_op_overflow=yes
-else
-  pgac_cv__builtin_op_overflow=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv__builtin_op_overflow" >&5
-$as_echo "$pgac_cv__builtin_op_overflow" >&6; }
-if test x"$pgac_cv__builtin_op_overflow" = xyes ; then
-
-$as_echo "#define HAVE__BUILTIN_OP_OVERFLOW 1" >>confdefs.h
-
-fi
-
 # Check size of void *, size_t (enables tweaks for > 32bit address space)
 # The cast to long int works around a bug in the HP C Compiler
 # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
@@ -16526,6 +16333,39 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long long" >&5
+$as_echo_n "checking size of long long... " >&6; }
+if ${ac_cv_sizeof_long_long+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long long))" "ac_cv_sizeof_long_long"        "$ac_includes_default"; then :
+
+else
+  if test "$ac_cv_type_long_long" = yes; then
+     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (long long)
+See \`config.log' for more details" "$LINENO" 5; }
+   else
+     ac_cv_sizeof_long_long=0
+   fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long_long" >&5
+$as_echo "$ac_cv_sizeof_long_long" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_LONG_LONG $ac_cv_sizeof_long_long
+_ACEOF
+
+
 
 # Determine memory alignment requirements for the basic C data types.
 
@@ -16634,43 +16474,41 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
-if test x"$HAVE_LONG_LONG_INT_64" = x"yes" ; then
-  # The cast to long int works around a bug in the HP C Compiler,
+# The cast to long int works around a bug in the HP C Compiler,
 # see AC_CHECK_SIZEOF for more information.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking alignment of long long int" >&5
-$as_echo_n "checking alignment of long long int... " >&6; }
-if ${ac_cv_alignof_long_long_int+:} false; then :
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking alignment of int64_t" >&5
+$as_echo_n "checking alignment of int64_t... " >&6; }
+if ${ac_cv_alignof_int64_t+:} false; then :
   $as_echo_n "(cached) " >&6
 else
-  if ac_fn_c_compute_int "$LINENO" "(long int) offsetof (ac__type_alignof_, y)" "ac_cv_alignof_long_long_int"        "$ac_includes_default
+  if ac_fn_c_compute_int "$LINENO" "(long int) offsetof (ac__type_alignof_, y)" "ac_cv_alignof_int64_t"        "$ac_includes_default
 #ifndef offsetof
 # define offsetof(type, member) ((char *) &((type *) 0)->member - (char *) 0)
 #endif
-typedef struct { char x; long long int y; } ac__type_alignof_;"; then :
+typedef struct { char x; int64_t y; } ac__type_alignof_;"; then :
 
 else
-  if test "$ac_cv_type_long_long_int" = yes; then
+  if test "$ac_cv_type_int64_t" = yes; then
      { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error 77 "cannot compute alignment of long long int
+as_fn_error 77 "cannot compute alignment of int64_t
 See \`config.log' for more details" "$LINENO" 5; }
    else
-     ac_cv_alignof_long_long_int=0
+     ac_cv_alignof_int64_t=0
    fi
 fi
 
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_alignof_long_long_int" >&5
-$as_echo "$ac_cv_alignof_long_long_int" >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_alignof_int64_t" >&5
+$as_echo "$ac_cv_alignof_int64_t" >&6; }
 
 
 
 cat >>confdefs.h <<_ACEOF
-#define ALIGNOF_LONG_LONG_INT $ac_cv_alignof_long_long_int
+#define ALIGNOF_INT64_T $ac_cv_alignof_int64_t
 _ACEOF
 
 
-fi
 # The cast to long int works around a bug in the HP C Compiler,
 # see AC_CHECK_SIZEOF for more information.
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking alignment of double" >&5
@@ -16728,8 +16566,8 @@ MAX_ALIGNOF=$ac_cv_alignof_double
 if test $ac_cv_alignof_long -gt $MAX_ALIGNOF ; then
   as_fn_error $? "alignment of 'long' is greater than the alignment of 'double'" "$LINENO" 5
 fi
-if test x"$HAVE_LONG_LONG_INT_64" = xyes && test $ac_cv_alignof_long_long_int -gt $MAX_ALIGNOF ; then
-  as_fn_error $? "alignment of 'long long int' is greater than the alignment of 'double'" "$LINENO" 5
+if test $ac_cv_alignof_int64_t -gt $MAX_ALIGNOF ; then
+  as_fn_error $? "alignment of 'int64_t' is greater than the alignment of 'double'" "$LINENO" 5
 fi
 
 cat >>confdefs.h <<_ACEOF
@@ -16737,7 +16575,6 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
-
 # Some compilers offer a 128-bit integer scalar type.
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __int128" >&5
 $as_echo_n "checking for __int128... " >&6; }
@@ -16992,12 +16829,12 @@ if ${pgac_cv_gcc_sync_int64_cas+:} false; then :
 else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
-
+#include <stdint.h>
 int
 main ()
 {
-PG_INT64_TYPE lock = 0;
-   __sync_val_compare_and_swap(&lock, 0, (PG_INT64_TYPE) 37);
+int64_t lock = 0;
+   __sync_val_compare_and_swap(&lock, 0, (int64_t) 37);
   ;
   return 0;
 }
@@ -17057,12 +16894,12 @@ if ${pgac_cv_gcc_atomic_int64_cas+:} false; then :
 else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
-
+#include <stdint.h>
 int
 main ()
 {
-PG_INT64_TYPE val = 0;
-   PG_INT64_TYPE expect = 0;
+int64_t val = 0;
+   int64_t expect = 0;
    __atomic_compare_exchange_n(&val, &expect, 37, 0, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);
   ;
   return 0;
@@ -17278,13 +17115,14 @@ else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 #include <immintrin.h>
+    #include <stdint.h>
     #if defined(__has_attribute) && __has_attribute (target)
     __attribute__((target("avx512vpopcntdq,avx512bw")))
     #endif
     static int popcount_test(void)
     {
       const char buf[sizeof(__m512i)];
-      PG_INT64_TYPE popcnt = 0;
+      int64_t popcnt = 0;
       __m512i accum = _mm512_setzero_si512();
       const __m512i val = _mm512_maskz_loadu_epi8((__mmask64) 0xf0f0f0f0f0f0f0f0, (const __m512i *) buf);
       const __m512i cnt = _mm512_popcnt_epi64(val);
@@ -18954,9 +18792,6 @@ fi
 ac_config_headers="$ac_config_headers src/include/pg_config.h"
 
 
-ac_config_headers="$ac_config_headers src/include/pg_config_ext.h"
-
-
 ac_config_headers="$ac_config_headers src/interfaces/ecpg/include/ecpg_config.h"
 
 
@@ -19671,7 +19506,6 @@ do
     "src/Makefile.port") CONFIG_LINKS="$CONFIG_LINKS src/Makefile.port:src/makefiles/Makefile.${template}" ;;
     "check_win32_symlinks") CONFIG_COMMANDS="$CONFIG_COMMANDS check_win32_symlinks" ;;
     "src/include/pg_config.h") CONFIG_HEADERS="$CONFIG_HEADERS src/include/pg_config.h" ;;
-    "src/include/pg_config_ext.h") CONFIG_HEADERS="$CONFIG_HEADERS src/include/pg_config_ext.h" ;;
     "src/interfaces/ecpg/include/ecpg_config.h") CONFIG_HEADERS="$CONFIG_HEADERS src/interfaces/ecpg/include/ecpg_config.h" ;;
 
   *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
@@ -20279,10 +20113,6 @@ $as_echo "$as_me: WARNING: *** link for $FILE -- please fix by hand" >&2;}
     "src/include/pg_config.h":H)
 # Update timestamp for pg_config.h (see Makefile.global)
 echo >src/include/stamp-h
- ;;
-    "src/include/pg_config_ext.h":H)
-# Update timestamp for pg_config_ext.h (see Makefile.global)
-echo >src/include/stamp-ext-h
  ;;
     "src/interfaces/ecpg/include/ecpg_config.h":H) echo >src/interfaces/ecpg/include/stamp-h ;;
 
diff --git a/configure.ac b/configure.ac
index 21817009642..074ecc62d20 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1604,6 +1604,7 @@ PGAC_C_STATIC_ASSERT
 PGAC_C_TYPEOF
 PGAC_C_TYPES_COMPATIBLE
 PGAC_C_BUILTIN_CONSTANT_P
+PGAC_C_BUILTIN_OP_OVERFLOW
 PGAC_C_BUILTIN_UNREACHABLE
 PGAC_C_COMPUTED_GOTO
 PGAC_STRUCT_TIMEZONE
@@ -1906,54 +1907,18 @@ for the exact reason.]])],
 # Run tests below here
 # --------------------
 
-dnl Check to see if we have a working 64-bit integer type.
-dnl Since Postgres 8.4, we no longer support compilers without a working
-dnl 64-bit type; but we have to determine whether that type is called
-dnl "long int" or "long long int".
-
-PGAC_TYPE_64BIT_INT([long int])
-
-if test x"$HAVE_LONG_INT_64" = x"yes" ; then
-  pg_int64_type="long int"
-else
-  PGAC_TYPE_64BIT_INT([long long int])
-  if test x"$HAVE_LONG_LONG_INT_64" = x"yes" ; then
-    pg_int64_type="long long int"
-  else
-    AC_MSG_ERROR([Cannot find a working 64-bit integer type.])
-  fi
-fi
-
-AC_DEFINE_UNQUOTED(PG_INT64_TYPE, $pg_int64_type,
-  [Define to the name of a signed 64-bit integer type.])
-
-# Select the printf length modifier that goes with that, too.
-if test x"$pg_int64_type" = x"long long int" ; then
-  INT64_MODIFIER='"ll"'
-else
-  INT64_MODIFIER='"l"'
-fi
-
-AC_DEFINE_UNQUOTED(INT64_MODIFIER, $INT64_MODIFIER,
-                   [Define to the appropriate printf length modifier for 64-bit ints.])
-
-# has to be down here, rather than with the other builtins, because
-# the test uses PG_INT64_TYPE.
-PGAC_C_BUILTIN_OP_OVERFLOW
-
 # Check size of void *, size_t (enables tweaks for > 32bit address space)
 AC_CHECK_SIZEOF([void *])
 AC_CHECK_SIZEOF([size_t])
 AC_CHECK_SIZEOF([long])
+AC_CHECK_SIZEOF([long long])
 
 # Determine memory alignment requirements for the basic C data types.
 
 AC_CHECK_ALIGNOF(short)
 AC_CHECK_ALIGNOF(int)
 AC_CHECK_ALIGNOF(long)
-if test x"$HAVE_LONG_LONG_INT_64" = x"yes" ; then
-  AC_CHECK_ALIGNOF(long long int)
-fi
+AC_CHECK_ALIGNOF(int64_t)
 AC_CHECK_ALIGNOF(double)
 
 # Compute maximum alignment of any basic type.
@@ -1977,12 +1942,11 @@ MAX_ALIGNOF=$ac_cv_alignof_double
 if test $ac_cv_alignof_long -gt $MAX_ALIGNOF ; then
   AC_MSG_ERROR([alignment of 'long' is greater than the alignment of 'double'])
 fi
-if test x"$HAVE_LONG_LONG_INT_64" = xyes && test $ac_cv_alignof_long_long_int -gt $MAX_ALIGNOF ; then
-  AC_MSG_ERROR([alignment of 'long long int' is greater than the alignment of 'double'])
+if test $ac_cv_alignof_int64_t -gt $MAX_ALIGNOF ; then
+  AC_MSG_ERROR([alignment of 'int64_t' is greater than the alignment of 'double'])
 fi
 AC_DEFINE_UNQUOTED(MAXIMUM_ALIGNOF, $MAX_ALIGNOF, [Define as the maximum alignment requirement of any C data type.])
 
-
 # Some compilers offer a 128-bit integer scalar type.
 PGAC_TYPE_128BIT_INT
 
@@ -2472,12 +2436,6 @@ AC_CONFIG_HEADERS([src/include/pg_config.h],
 echo >src/include/stamp-h
 ])
 
-AC_CONFIG_HEADERS([src/include/pg_config_ext.h],
-[
-# Update timestamp for pg_config_ext.h (see Makefile.global)
-echo >src/include/stamp-ext-h
-])
-
 AC_CONFIG_HEADERS([src/interfaces/ecpg/include/ecpg_config.h],
                   [echo >src/interfaces/ecpg/include/stamp-h])
 
diff --git a/meson.build b/meson.build
index 451c3f6d851..a2e35bca077 100644
--- a/meson.build
+++ b/meson.build
@@ -1588,21 +1588,6 @@ if not cc.compiles(c99_test, name: 'c99', args: test_c_args)
   endif
 endif
 
-sizeof_long = cc.sizeof('long', args: test_c_args)
-cdata.set('SIZEOF_LONG', sizeof_long)
-if sizeof_long == 8
-  cdata.set('HAVE_LONG_INT_64', 1)
-  pg_int64_type = 'long int'
-  cdata.set_quoted('INT64_MODIFIER', 'l')
-elif sizeof_long == 4 and cc.sizeof('long long', args: test_c_args) == 8
-  cdata.set('HAVE_LONG_LONG_INT_64', 1)
-  pg_int64_type = 'long long int'
-  cdata.set_quoted('INT64_MODIFIER', 'll')
-else
-  error('do not know how to get a 64bit int')
-endif
-cdata.set('PG_INT64_TYPE', pg_int64_type)
-
 if host_machine.endian() == 'big'
   cdata.set('WORDS_BIGENDIAN', 1)
 endif
@@ -1626,16 +1611,21 @@ endforeach
 # of MAXIMUM_ALIGNOF to avoid that, but we no longer support any platforms
 # where TYPALIGN_DOUBLE != MAXIMUM_ALIGNOF.
 #
-# We assume without checking that int64's alignment is at least as strong
+# We assume without checking that int64_t's alignment is at least as strong
 # as long, char, short, or int.  Note that we intentionally do not consider
 # any types wider than 64 bits, as allowing MAXIMUM_ALIGNOF to exceed 8
 # would be too much of a penalty for disk and memory space.
 alignof_double = cdata.get('ALIGNOF_DOUBLE')
-if cc.alignment(pg_int64_type, args: test_c_args) > alignof_double
-  error('alignment of int64 is greater than the alignment of double')
+if cc.alignment('int64_t', args: test_c_args, prefix: '#include <stdint.h>') > alignof_double
+  error('alignment of int64_t is greater than the alignment of double')
 endif
 cdata.set('MAXIMUM_ALIGNOF', alignof_double)
 
+cdata.set('SIZEOF_LONG', cc.sizeof('long', args: test_c_args))
+cdata.set('SIZEOF_LONG_LONG', cc.sizeof('long long', args: test_c_args))
+
+# Check if __int128 is a working 128 bit integer type, and if so
+# define PG_INT128_TYPE to that typename.
 cdata.set('SIZEOF_VOID_P', cc.sizeof('void *', args: test_c_args))
 cdata.set('SIZEOF_SIZE_T', cc.sizeof('size_t', args: test_c_args))
 
@@ -1834,17 +1824,17 @@ endif
 # compile, and store the results in global variables so the compiler doesn't
 # optimize away the call.
 if cc.links('''
-    INT64 a = 1;
-    INT64 b = 1;
-    INT64 result;
+    #include <stdint.h>
+    int64_t a = 1;
+    int64_t b = 1;
+    int64_t result;
 
     int main(void)
     {
         return __builtin_mul_overflow(a, b, &result);
     }''',
     name: '__builtin_mul_overflow',
-    args: test_c_args + ['-DINT64=@0@'.format(cdata.get('PG_INT64_TYPE'))],
-    )
+    args: test_c_args)
   cdata.set('HAVE__BUILTIN_OP_OVERFLOW', 1)
 endif
 
@@ -2134,7 +2124,7 @@ int main(void)
   cdata.set(check['name'],
     cc.links(test,
       name: check['desc'],
-      args: test_c_args + ['-DINT64=@0@'.format(cdata.get('PG_INT64_TYPE'))]) ? 1 : false
+      args: test_c_args) ? 1 : false
   )
 endforeach
 
@@ -2172,6 +2162,7 @@ if host_cpu == 'x86_64'
 
   prog = '''
 #include <immintrin.h>
+#include <stdint.h>
 
 #if defined(__has_attribute) && __has_attribute (target)
 __attribute__((target("avx512vpopcntdq,avx512bw")))
@@ -2179,7 +2170,7 @@ __attribute__((target("avx512vpopcntdq,avx512bw")))
 int main(void)
 {
     const char buf[sizeof(__m512i)];
-    INT64 popcnt = 0;
+    int64_t popcnt = 0;
     __m512i accum = _mm512_setzero_si512();
     const __m512i val = _mm512_maskz_loadu_epi8((__mmask64) 0xf0f0f0f0f0f0f0f0, (const __m512i *) buf);
     const __m512i cnt = _mm512_popcnt_epi64(val);
@@ -2190,8 +2181,7 @@ int main(void)
 }
 '''
 
-  if cc.links(prog, name: 'AVX-512 popcount',
-        args: test_c_args + ['-DINT64=@0@'.format(cdata.get('PG_INT64_TYPE'))])
+  if cc.links(prog, name: 'AVX-512 popcount', args: test_c_args)
     cdata.set('USE_AVX512_POPCNT_WITH_RUNTIME_CHECK', 1)
   endif
 
diff --git a/src/Makefile.global.in b/src/Makefile.global.in
index 0f38d712d15..eac3d001211 100644
--- a/src/Makefile.global.in
+++ b/src/Makefile.global.in
@@ -840,12 +840,6 @@ $(top_builddir)/src/include/pg_config.h: $(top_builddir)/src/include/stamp-h ;
 $(top_builddir)/src/include/stamp-h: $(top_srcdir)/src/include/pg_config.h.in $(top_builddir)/config.status
 	cd $(top_builddir) && ./config.status src/include/pg_config.h
 
-# Also remake pg_config_ext.h from pg_config_ext.h.in, same logic as above.
-$(top_builddir)/src/include/pg_config_ext.h: $(top_builddir)/src/include/stamp-ext-h ;
-
-$(top_builddir)/src/include/stamp-ext-h: $(top_srcdir)/src/include/pg_config_ext.h.in $(top_builddir)/config.status
-	cd $(top_builddir) && ./config.status src/include/pg_config_ext.h
-
 # Also remake ecpg_config.h from ecpg_config.h.in if the latter changed, same
 # logic as above.
 $(top_builddir)/src/interfaces/ecpg/include/ecpg_config.h: $(top_builddir)/src/interfaces/ecpg/include/stamp-h ;
diff --git a/src/bin/pg_waldump/pg_waldump.c b/src/bin/pg_waldump/pg_waldump.c
index 1f9403fc5cf..c4b04d62965 100644
--- a/src/bin/pg_waldump/pg_waldump.c
+++ b/src/bin/pg_waldump/pg_waldump.c
@@ -610,10 +610,10 @@ XLogDumpStatsRow(const char *name,
 		tot_len_pct = 100 * (double) tot_len / total_len;
 
 	printf("%-27s "
-		   "%20" INT64_MODIFIER "u (%6.02f) "
-		   "%20" INT64_MODIFIER "u (%6.02f) "
-		   "%20" INT64_MODIFIER "u (%6.02f) "
-		   "%20" INT64_MODIFIER "u (%6.02f)\n",
+		   "%20" PRIu64 " (%6.02f) "
+		   "%20" PRIu64 " (%6.02f) "
+		   "%20" PRIu64 " (%6.02f) "
+		   "%20" PRIu64 " (%6.02f)\n",
 		   name, n, n_pct, rec_len, rec_len_pct, fpi_len, fpi_len_pct,
 		   tot_len, tot_len_pct);
 }
@@ -742,10 +742,10 @@ XLogDumpDisplayStats(XLogDumpConfig *config, XLogStats *stats)
 		fpi_len_pct = 100 * (double) total_fpi_len / total_len;
 
 	printf("%-27s "
-		   "%20" INT64_MODIFIER "u %-9s"
-		   "%20" INT64_MODIFIER "u %-9s"
-		   "%20" INT64_MODIFIER "u %-9s"
-		   "%20" INT64_MODIFIER "u %-6s\n",
+		   "%20" PRIu64 " %-9s"
+		   "%20" PRIu64 " %-9s"
+		   "%20" PRIu64 " %-9s"
+		   "%20" PRIu64 " %-6s\n",
 		   "Total", stats->count, "",
 		   total_rec_len, psprintf("[%.02f%%]", rec_len_pct),
 		   total_fpi_len, psprintf("[%.02f%%]", fpi_len_pct),
diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c
index 85e7b68baa3..c4c38099c5b 100644
--- a/src/bin/pgbench/pgbench.c
+++ b/src/bin/pgbench/pgbench.c
@@ -6568,13 +6568,13 @@ printResults(StatsData *total,
 					SimpleStats *cstats = &(*commands)->stats;
 
 					if (max_tries == 1)
-						printf("   %11.3f  %10" INT64_MODIFIER "d  %s\n",
+						printf("   %11.3f  %10" PRId64 " %s\n",
 							   (cstats->count > 0) ?
 							   1000.0 * cstats->sum / cstats->count : 0.0,
 							   (*commands)->failures,
 							   (*commands)->first_line);
 					else
-						printf("   %11.3f  %10" INT64_MODIFIER "d  %10" INT64_MODIFIER "d  %s\n",
+						printf("   %11.3f  %10" PRId64 " %10" PRId64 " %s\n",
 							   (cstats->count > 0) ?
 							   1000.0 * cstats->sum / cstats->count : 0.0,
 							   (*commands)->failures,
diff --git a/src/include/.gitignore b/src/include/.gitignore
index 51819fb4ddd..6e99e82fe0c 100644
--- a/src/include/.gitignore
+++ b/src/include/.gitignore
@@ -1,5 +1,3 @@
 /stamp-h
-/stamp-ext-h
 /pg_config.h
-/pg_config_ext.h
 /pg_config_os.h
diff --git a/src/include/Makefile b/src/include/Makefile
index b8b576a4de3..26332ff9cbc 100644
--- a/src/include/Makefile
+++ b/src/include/Makefile
@@ -13,7 +13,7 @@ top_builddir = ../..
 include $(top_builddir)/src/Makefile.global
 
 
-all: pg_config.h pg_config_ext.h pg_config_os.h
+all: pg_config.h pg_config_os.h
 
 
 # Subdirectories containing installable headers
@@ -32,7 +32,6 @@ install: all installdirs
 	$(INSTALL_DATA) $(srcdir)/postgres_ext.h   '$(DESTDIR)$(includedir)'
 	$(INSTALL_DATA) $(srcdir)/libpq/libpq-fs.h '$(DESTDIR)$(includedir)/libpq'
 	$(INSTALL_DATA) pg_config.h     '$(DESTDIR)$(includedir)'
-	$(INSTALL_DATA) pg_config_ext.h '$(DESTDIR)$(includedir)'
 	$(INSTALL_DATA) pg_config_os.h  '$(DESTDIR)$(includedir)'
 	$(INSTALL_DATA) $(srcdir)/pg_config_manual.h '$(DESTDIR)$(includedir)'
 # These headers are needed by the not-so-public headers of the interfaces.
@@ -43,7 +42,6 @@ install: all installdirs
 	$(INSTALL_DATA) $(srcdir)/libpq/protocol.h '$(DESTDIR)$(includedir_internal)/libpq'
 # These headers are needed for server-side development
 	$(INSTALL_DATA) pg_config.h     '$(DESTDIR)$(includedir_server)'
-	$(INSTALL_DATA) pg_config_ext.h '$(DESTDIR)$(includedir_server)'
 	$(INSTALL_DATA) pg_config_os.h  '$(DESTDIR)$(includedir_server)'
 	$(INSTALL_DATA) nodes/nodetags.h '$(DESTDIR)$(includedir_server)/nodes'
 	$(INSTALL_DATA) utils/errcodes.h '$(DESTDIR)$(includedir_server)/utils'
@@ -66,7 +64,7 @@ installdirs:
 
 
 uninstall:
-	rm -f $(addprefix '$(DESTDIR)$(includedir)'/, pg_config.h pg_config_ext.h pg_config_os.h pg_config_manual.h postgres_ext.h libpq/libpq-fs.h)
+	rm -f $(addprefix '$(DESTDIR)$(includedir)'/, pg_config.h pg_config_os.h pg_config_manual.h postgres_ext.h libpq/libpq-fs.h)
 	rm -f $(addprefix '$(DESTDIR)$(includedir_internal)'/, c.h port.h postgres_fe.h libpq/pqcomm.h libpq/protocol.h)
 # heuristic...
 	rm -rf $(addprefix '$(DESTDIR)$(includedir_server)'/, $(SUBDIRS) *.h)
@@ -80,4 +78,4 @@ clean:
 	$(MAKE) -C catalog clean
 
 distclean: clean
-	rm -f pg_config.h pg_config_ext.h pg_config_os.h stamp-h stamp-ext-h
+	rm -f pg_config.h pg_config_os.h stamp-h stamp-ext-h
diff --git a/src/include/c.h b/src/include/c.h
index 304dff27e34..734626e75a8 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -48,14 +48,12 @@
 
 #include "postgres_ext.h"
 
-/* Must undef pg_config_ext.h symbols before including pg_config.h */
-#undef PG_INT64_TYPE
-
 #include "pg_config.h"
 #include "pg_config_manual.h"	/* must be after pg_config.h */
 #include "pg_config_os.h"		/* must be before any system header files */
 
 /* System header files that should be available everywhere in Postgres */
+#include <inttypes.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -471,25 +469,15 @@ typedef void (*pg_funcptr_t) (void);
  */
 typedef char *Pointer;
 
-/*
- * intN
- *		Signed integer, EXACTLY N BITS IN SIZE,
- *		used for numerical computations and the
- *		frontend/backend protocol.
- */
-typedef signed char int8;		/* == 8 bits */
-typedef signed short int16;		/* == 16 bits */
-typedef signed int int32;		/* == 32 bits */
-
-/*
- * uintN
- *		Unsigned integer, EXACTLY N BITS IN SIZE,
- *		used for numerical computations and the
- *		frontend/backend protocol.
- */
-typedef unsigned char uint8;	/* == 8 bits */
-typedef unsigned short uint16;	/* == 16 bits */
-typedef unsigned int uint32;	/* == 32 bits */
+/* Historical names for types in <stdint.h>. */
+typedef int8_t int8;
+typedef int16_t int16;
+typedef int32_t int32;
+typedef int64_t int64;
+typedef uint8_t uint8;
+typedef uint16_t uint16;
+typedef uint32_t uint32;
+typedef uint64_t uint64;
 
 /*
  * bitsN
@@ -502,30 +490,14 @@ typedef uint32 bits32;			/* >= 32 bits */
 /*
  * 64-bit integers
  */
-#ifdef HAVE_LONG_INT_64
-/* Plain "long int" fits, use it */
-
-typedef long int int64;
-typedef unsigned long int uint64;
-#define INT64CONST(x)  (x##L)
-#define UINT64CONST(x) (x##UL)
-#elif defined(HAVE_LONG_LONG_INT_64)
-/* We have working support for "long long int", use that */
-
-typedef long long int int64;
-typedef unsigned long long int uint64;
-#define INT64CONST(x)  (x##LL)
-#define UINT64CONST(x) (x##ULL)
-#else
-/* neither HAVE_LONG_INT_64 nor HAVE_LONG_LONG_INT_64 */
-#error must have a working 64-bit integer datatype
-#endif
+#define INT64CONST(x)  INT64_C(x)
+#define UINT64CONST(x) UINT64_C(x)
 
 /* snprintf format strings to use for 64-bit integers */
-#define INT64_FORMAT "%" INT64_MODIFIER "d"
-#define UINT64_FORMAT "%" INT64_MODIFIER "u"
-#define INT64_HEX_FORMAT "%" INT64_MODIFIER "x"
-#define UINT64_HEX_FORMAT "%" INT64_MODIFIER "x"
+#define INT64_FORMAT "%" PRId64
+#define UINT64_FORMAT "%" PRIu64
+#define INT64_HEX_FORMAT "%" PRIx64
+#define UINT64_HEX_FORMAT "%" PRIx64
 
 /*
  * 128-bit signed and unsigned integers
@@ -554,22 +526,19 @@ typedef unsigned PG_INT128_TYPE uint128
 #endif
 #endif
 
-/*
- * stdint.h limits aren't guaranteed to have compatible types with our fixed
- * width types. So just define our own.
- */
-#define PG_INT8_MIN		(-0x7F-1)
-#define PG_INT8_MAX		(0x7F)
-#define PG_UINT8_MAX	(0xFF)
-#define PG_INT16_MIN	(-0x7FFF-1)
-#define PG_INT16_MAX	(0x7FFF)
-#define PG_UINT16_MAX	(0xFFFF)
-#define PG_INT32_MIN	(-0x7FFFFFFF-1)
-#define PG_INT32_MAX	(0x7FFFFFFF)
-#define PG_UINT32_MAX	(0xFFFFFFFFU)
-#define PG_INT64_MIN	(-INT64CONST(0x7FFFFFFFFFFFFFFF) - 1)
-#define PG_INT64_MAX	INT64CONST(0x7FFFFFFFFFFFFFFF)
-#define PG_UINT64_MAX	UINT64CONST(0xFFFFFFFFFFFFFFFF)
+/* Historical names for limits in <stdint.h>. */
+#define PG_INT8_MIN		INT8_MIN
+#define PG_INT8_MAX		INT8_MAX
+#define PG_UINT8_MAX	UINT8_MAX
+#define PG_INT16_MIN	INT16_MIN
+#define PG_INT16_MAX	INT16_MAX
+#define PG_UINT16_MAX	UINT16_MAX
+#define PG_INT32_MIN	INT32_MIN
+#define PG_INT32_MAX	INT32_MAX
+#define PG_UINT32_MAX	UINT32_MAX
+#define PG_INT64_MIN	INT64_MIN
+#define PG_INT64_MAX	INT64_MAX
+#define PG_UINT64_MAX	UINT64_MAX
 
 /*
  * We now always use int64 timestamps, but keep this symbol defined for the
@@ -1272,21 +1241,25 @@ extern int	fdatasync(int fildes);
  * definition of int64.  (For the naming, compare that POSIX has
  * strtoimax()/strtoumax() which return intmax_t/uintmax_t.)
  */
-#ifdef HAVE_LONG_INT_64
+#if SIZEOF_LONG == 8
 #define strtoi64(str, endptr, base) ((int64) strtol(str, endptr, base))
 #define strtou64(str, endptr, base) ((uint64) strtoul(str, endptr, base))
-#else
+#elif SIZEOF_LONG_LONG == 8
 #define strtoi64(str, endptr, base) ((int64) strtoll(str, endptr, base))
 #define strtou64(str, endptr, base) ((uint64) strtoull(str, endptr, base))
+#else
+#error "cannot find integer type of the same size as int64_t"
 #endif
 
 /*
  * Similarly, wrappers around labs()/llabs() matching our int64.
  */
-#ifdef HAVE_LONG_INT_64
+#if SIZEOF_LONG == 8
 #define i64abs(i) labs(i)
-#else
+#elif SIZEOF_LONG_LONG == 8
 #define i64abs(i) llabs(i)
+#else
+#error "cannot find integer type of the same size as int64_t"
 #endif
 
 /*
diff --git a/src/include/meson.build b/src/include/meson.build
index 58b7a9c1e7e..e691b12b8a0 100644
--- a/src/include/meson.build
+++ b/src/include/meson.build
@@ -1,14 +1,5 @@
 # Copyright (c) 2022-2024, PostgreSQL Global Development Group
 
-pg_config_ext = configure_file(
-  input: 'pg_config_ext.h.meson',
-  output: 'pg_config_ext.h',
-  configuration: cdata,
-  install: true,
-  install_dir: dir_include,
-)
-configure_files += pg_config_ext
-
 pg_config_os = configure_file(
   output: 'pg_config_os.h',
   input: files('port/@0@.h'.format(portname)),
@@ -116,7 +107,6 @@ install_headers(
   'postgres_fe.h',
   'varatt.h',
   'windowapi.h',
-  pg_config_ext,
   pg_config_os,
   pg_config,
   install_dir: dir_include_server,
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index ab0f8cc2b4a..07b2f798abd 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -9,12 +9,12 @@
 /* The normal alignment of `int', in bytes. */
 #undef ALIGNOF_INT
 
+/* The normal alignment of `int64_t', in bytes. */
+#undef ALIGNOF_INT64_T
+
 /* The normal alignment of `long', in bytes. */
 #undef ALIGNOF_LONG
 
-/* The normal alignment of `long long int', in bytes. */
-#undef ALIGNOF_LONG_LONG_INT
-
 /* The normal alignment of `PG_INT128_TYPE', in bytes. */
 #undef ALIGNOF_PG_INT128_TYPE
 
@@ -153,8 +153,8 @@
 /* Define to 1 if you have __sync_lock_test_and_set(int *) and friends. */
 #undef HAVE_GCC__SYNC_INT32_TAS
 
-/* Define to 1 if you have __sync_val_compare_and_swap(int64 *, int64, int64).
-   */
+/* Define to 1 if you have __sync_val_compare_and_swap(int64_t *, int64_t,
+   int64_t). */
 #undef HAVE_GCC__SYNC_INT64_CAS
 
 /* Define to 1 if you have the `getauxval' function. */
@@ -265,12 +265,6 @@
 /* Define to 1 if you have the `zstd' library (-lzstd). */
 #undef HAVE_LIBZSTD
 
-/* Define to 1 if `long int' works and is 64 bits. */
-#undef HAVE_LONG_INT_64
-
-/* Define to 1 if `long long int' works and is 64 bits. */
-#undef HAVE_LONG_LONG_INT_64
-
 /* Define to 1 if you have the <mbarrier.h> header file. */
 #undef HAVE_MBARRIER_H
 
@@ -544,9 +538,6 @@
 /* Define to 1 if your compiler understands _Static_assert. */
 #undef HAVE__STATIC_ASSERT
 
-/* Define to the appropriate printf length modifier for 64-bit ints. */
-#undef INT64_MODIFIER
-
 /* Define as the maximum alignment requirement of any C data type. */
 #undef MAXIMUM_ALIGNOF
 
@@ -578,9 +569,6 @@
 /* Define to the name of a signed 128-bit integer type. */
 #undef PG_INT128_TYPE
 
-/* Define to the name of a signed 64-bit integer type. */
-#undef PG_INT64_TYPE
-
 /* Define to the name of the default PostgreSQL service principal in Kerberos
    (GSSAPI). (--with-krb-srvnam=NAME) */
 #undef PG_KRB_SRVNAM
@@ -630,6 +618,9 @@
 /* The size of `long', as computed by sizeof. */
 #undef SIZEOF_LONG
 
+/* The size of `long long', as computed by sizeof. */
+#undef SIZEOF_LONG_LONG
+
 /* The size of `off_t', as computed by sizeof. */
 #undef SIZEOF_OFF_T
 
diff --git a/src/include/pg_config_ext.h.in b/src/include/pg_config_ext.h.in
deleted file mode 100644
index 8acadbdafd4..00000000000
--- a/src/include/pg_config_ext.h.in
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
- * src/include/pg_config_ext.h.in.  This is generated manually, not by
- * autoheader, since we want to limit which symbols get defined here.
- */
-
-/* Define to the name of a signed 64-bit integer type. */
-#undef PG_INT64_TYPE
diff --git a/src/include/pg_config_ext.h.meson b/src/include/pg_config_ext.h.meson
deleted file mode 100644
index 57cdfca0cfd..00000000000
--- a/src/include/pg_config_ext.h.meson
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
- * src/include/pg_config_ext.h.in.  This is generated manually, not by
- * autoheader, since we want to limit which symbols get defined here.
- */
-
-/* Define to the name of a signed 64-bit integer type. */
-#mesondefine PG_INT64_TYPE
diff --git a/src/include/port/pg_bitutils.h b/src/include/port/pg_bitutils.h
index 4d88478c9c2..a3cad46afe9 100644
--- a/src/include/port/pg_bitutils.h
+++ b/src/include/port/pg_bitutils.h
@@ -74,13 +74,13 @@ pg_leftmost_one_pos64(uint64 word)
 #ifdef HAVE__BUILTIN_CLZ
 	Assert(word != 0);
 
-#if defined(HAVE_LONG_INT_64)
+#if SIZEOF_LONG == 8
 	return 63 - __builtin_clzl(word);
-#elif defined(HAVE_LONG_LONG_INT_64)
+#elif SIZEOF_LONG_LONG == 8
 	return 63 - __builtin_clzll(word);
 #else
-#error must have a working 64-bit integer datatype
-#endif							/* HAVE_LONG_INT_64 */
+#error "cannot find integer type of the same size as uint64_t"
+#endif
 
 #elif defined(_MSC_VER) && (defined(_M_AMD64) || defined(_M_ARM64))
 	unsigned long result;
@@ -147,13 +147,13 @@ pg_rightmost_one_pos64(uint64 word)
 #ifdef HAVE__BUILTIN_CTZ
 	Assert(word != 0);
 
-#if defined(HAVE_LONG_INT_64)
+#if SIZEOF_LONG == 8
 	return __builtin_ctzl(word);
-#elif defined(HAVE_LONG_LONG_INT_64)
+#elif SIZEOF_LONG_LONG == 8
 	return __builtin_ctzll(word);
 #else
-#error must have a working 64-bit integer datatype
-#endif							/* HAVE_LONG_INT_64 */
+#error "cannot find integer type of the same size as uint64_t"
+#endif
 
 #elif defined(_MSC_VER) && (defined(_M_AMD64) || defined(_M_ARM64))
 	unsigned long result;
diff --git a/src/include/port/win32_port.h b/src/include/port/win32_port.h
index 7789e0431aa..9bcaba65624 100644
--- a/src/include/port/win32_port.h
+++ b/src/include/port/win32_port.h
@@ -415,6 +415,53 @@ extern int	_pglstat64(const char *name, struct stat *buf);
 #undef ETIMEDOUT
 #define ETIMEDOUT WSAETIMEDOUT
 
+/*
+ * Adjustments to <inttypes.h>.  Windows has size prefixes "I64", "I32", "I"
+ * (intptr_t), but our snprintf.c is not expecting those.  Redefine them using
+ * standard strings that have the same effect since we know the sizes.
+ */
+
+#undef PRId64
+#undef PRIu64
+#undef PRIx64
+#undef PRIX64
+#undef PRIo64
+#define PRId64 "lld"
+#define PRIu64 "llu"
+#define PRIx64 "llx"
+#define PRIX64 "llX"
+#define PRIo64 "llo"
+
+#undef PRId32
+#undef PRIu32
+#undef PRIx32
+#undef PRIX32
+#undef PRIo32
+#define PRId32 "d"
+#define PRIu32 "u"
+#define PRIx32 "x"
+#define PRIX32 "X"
+#define PRIo32 "o"
+
+#undef PRIdPTR
+#undef PRIuPTR
+#undef PRIxPTR
+#undef PRIXPTR
+#undef PRIoPTR
+#if SIZEOF_VOID_P == 8
+#define PRIdPTR PRId64
+#define PRIuPTR PRIu64
+#define PRIxPTR PRIx64
+#define PRIXPTR PRIX64
+#define PRIoPTR PRIo64
+#else
+#define PRIdPTR PRId32
+#define PRIuPTR PRIu32
+#define PRIxPTR PRIx32
+#define PRIXPTR PRIX32
+#define PRIoPTR PRIo32
+#endif
+
 /*
  * Supplement to <string.h>.
  */
diff --git a/src/include/postgres_ext.h b/src/include/postgres_ext.h
index 240ad4e93bf..202eb049622 100644
--- a/src/include/postgres_ext.h
+++ b/src/include/postgres_ext.h
@@ -23,7 +23,7 @@
 #ifndef POSTGRES_EXT_H
 #define POSTGRES_EXT_H
 
-#include "pg_config_ext.h"
+#include <stdint.h>
 
 /*
  * Object ID is a fundamental type in Postgres.
@@ -44,7 +44,7 @@ typedef unsigned int Oid;
 
 
 /* Define a signed 64-bit integer type for use in client API declarations. */
-typedef PG_INT64_TYPE pg_int64;
+typedef int64_t pg_int64;
 
 /*
  * Identifiers of error message fields.  Kept here to keep common
diff --git a/src/include/utils/dsa.h b/src/include/utils/dsa.h
index 8dff964bf33..6c952a43f79 100644
--- a/src/include/utils/dsa.h
+++ b/src/include/utils/dsa.h
@@ -66,7 +66,7 @@ typedef pg_atomic_uint64 dsa_pointer_atomic;
 #define dsa_pointer_atomic_write pg_atomic_write_u64
 #define dsa_pointer_atomic_fetch_add pg_atomic_fetch_add_u64
 #define dsa_pointer_atomic_compare_exchange pg_atomic_compare_exchange_u64
-#define DSA_POINTER_FORMAT "%016" INT64_MODIFIER "x"
+#define DSA_POINTER_FORMAT "%016" PRIx64
 #endif
 
 /* Flags for dsa_allocate_extended. */
diff --git a/src/interfaces/ecpg/ecpglib/typename.c b/src/interfaces/ecpg/ecpglib/typename.c
index 1d482c4fa61..1fb9860371b 100644
--- a/src/interfaces/ecpg/ecpglib/typename.c
+++ b/src/interfaces/ecpg/ecpglib/typename.c
@@ -131,11 +131,12 @@ sqlda_dynamic_type(Oid type, enum COMPAT_MODE compat)
 		case INTERVALOID:
 			return ECPGt_interval;
 		case INT8OID:
-#ifdef HAVE_LONG_LONG_INT_64
-			return ECPGt_long_long;
-#endif
-#ifdef HAVE_LONG_INT_64
+#if SIZEOF_LONG == 8
 			return ECPGt_long;
+#elif SIZEOF_LONG_LONG == 8
+			return ECPGt_long_long;
+#else
+#error "cannot find integer type of the same size as INT8OID"
 #endif
 			/* Unhandled types always return a string */
 		default:
diff --git a/src/interfaces/ecpg/include/ecpg_config.h.in b/src/interfaces/ecpg/include/ecpg_config.h.in
index 75f542f263b..4af45930b61 100644
--- a/src/interfaces/ecpg/include/ecpg_config.h.in
+++ b/src/interfaces/ecpg/include/ecpg_config.h.in
@@ -1,8 +1,8 @@
 /* Define to 1 to build client libraries as thread-safe code. */
 #define ENABLE_THREAD_SAFETY 1
 
-/* Define to 1 if `long int' works and is 64 bits. */
-#undef HAVE_LONG_INT_64
+/* The size of `long', as computed by sizeof. */
+#undef SIZEOF_LONG
 
-/* Define to 1 if `long long int' works and is 64 bits. */
-#undef HAVE_LONG_LONG_INT_64
+/* The size of `long long', as computed by sizeof. */
+#undef SIZEOF_LONG_LONG
diff --git a/src/interfaces/ecpg/include/meson.build b/src/interfaces/ecpg/include/meson.build
index a3beb3cc7be..c1a88e73fb8 100644
--- a/src/interfaces/ecpg/include/meson.build
+++ b/src/interfaces/ecpg/include/meson.build
@@ -3,8 +3,8 @@
 ecpg_inc = include_directories('.')
 
 ecpg_conf_keys = [
-  'HAVE_LONG_INT_64',
-  'HAVE_LONG_LONG_INT_64',
+  'SIZEOF_LONG',
+  'SIZEOF_LONG_LONG',
 ]
 
 ecpg_conf_data = configuration_data()
diff --git a/src/interfaces/ecpg/include/pgtypes_interval.h b/src/interfaces/ecpg/include/pgtypes_interval.h
index 46cfce65517..f0acbb4512a 100644
--- a/src/interfaces/ecpg/include/pgtypes_interval.h
+++ b/src/interfaces/ecpg/include/pgtypes_interval.h
@@ -3,21 +3,17 @@
 #ifndef PGTYPES_INTERVAL
 #define PGTYPES_INTERVAL
 
+#include <stdint.h>
+
 #include <ecpg_config.h>
 #include <pgtypes.h>
 
 #ifndef C_H
 
-#ifdef HAVE_LONG_INT_64
-typedef long int int64;
-#elif defined(HAVE_LONG_LONG_INT_64)
-typedef long long int int64;
-#else
-/* neither HAVE_LONG_INT_64 nor HAVE_LONG_LONG_INT_64 */
-#error must have a working 64-bit integer datatype
-#endif
+typedef int64_t int64;
 
 #define HAVE_INT64_TIMESTAMP
+
 #endif							/* C_H */
 
 typedef struct
diff --git a/src/interfaces/ecpg/include/sqltypes.h b/src/interfaces/ecpg/include/sqltypes.h
index e7cbfa47956..498840458c4 100644
--- a/src/interfaces/ecpg/include/sqltypes.h
+++ b/src/interfaces/ecpg/include/sqltypes.h
@@ -46,12 +46,14 @@
 #define SQLINTERVAL		ECPGt_interval
 #define SQLNCHAR	ECPGt_char
 #define SQLNVCHAR	ECPGt_char
-#ifdef HAVE_LONG_LONG_INT_64
+#if SIZEOF_LONG == 8
+#define SQLINT8		ECPGt_long
+#define SQLSERIAL8	ECPGt_long
+#elif SIZEOF_LONG_LONG == 8
 #define SQLINT8		ECPGt_long_long
 #define SQLSERIAL8	ECPGt_long_long
 #else
-#define SQLINT8		ECPGt_long
-#define SQLSERIAL8	ECPGt_long
+#error "cannot find integer type of the same size as SQLINT8"
 #endif
 
 #endif							/* ndef ECPG_SQLTYPES_H */
diff --git a/src/interfaces/ecpg/test/expected/compat_informix-sqlda.c b/src/interfaces/ecpg/test/expected/compat_informix-sqlda.c
index 7e19319d27f..8eebc51664e 100644
--- a/src/interfaces/ecpg/test/expected/compat_informix-sqlda.c
+++ b/src/interfaces/ecpg/test/expected/compat_informix-sqlda.c
@@ -97,12 +97,14 @@ typedef struct sqlda_struct sqlda_t;
 #define SQLINTERVAL		ECPGt_interval
 #define SQLNCHAR	ECPGt_char
 #define SQLNVCHAR	ECPGt_char
-#ifdef HAVE_LONG_LONG_INT_64
+#if SIZEOF_LONG == 8
+#define SQLINT8		ECPGt_long
+#define SQLSERIAL8	ECPGt_long
+#elif SIZEOF_LONG_LONG == 8
 #define SQLINT8		ECPGt_long_long
 #define SQLSERIAL8	ECPGt_long_long
 #else
-#define SQLINT8		ECPGt_long
-#define SQLSERIAL8	ECPGt_long
+#error "cannot find integer type of the same size as SQLINT8"
 #endif
 
 #endif							/* ndef ECPG_SQLTYPES_H */
diff --git a/src/port/pg_bitutils.c b/src/port/pg_bitutils.c
index 87f56e82b80..c8399981ee0 100644
--- a/src/port/pg_bitutils.c
+++ b/src/port/pg_bitutils.c
@@ -370,12 +370,12 @@ static inline int
 pg_popcount64_slow(uint64 word)
 {
 #ifdef HAVE__BUILTIN_POPCOUNT
-#if defined(HAVE_LONG_INT_64)
+#if SIZEOF_LONG == 8
 	return __builtin_popcountl(word);
-#elif defined(HAVE_LONG_LONG_INT_64)
+#elif SIZEOF_LONG_LONG == 8
 	return __builtin_popcountll(word);
 #else
-#error must have a working 64-bit integer datatype
+#error "cannot find integer of the same size as uint64_t"
 #endif
 #else							/* !HAVE__BUILTIN_POPCOUNT */
 	int			result = 0;
diff --git a/src/port/snprintf.c b/src/port/snprintf.c
index 884f0262dd1..eba6437cceb 100644
--- a/src/port/snprintf.c
+++ b/src/port/snprintf.c
@@ -567,16 +567,12 @@ nextch2:
 					longflag = 1;
 				goto nextch2;
 			case 'z':
-#if SIZEOF_SIZE_T == 8
-#ifdef HAVE_LONG_INT_64
+#if SIZEOF_SIZE_T == SIZEOF_LONG
 				longflag = 1;
-#elif defined(HAVE_LONG_LONG_INT_64)
+#elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG
 				longlongflag = 1;
 #else
-#error "Don't know how to print 64bit integers"
-#endif
-#else
-				/* assume size_t is same size as int */
+#error "cannot find integer type of the same size as size_t"
 #endif
 				goto nextch2;
 			case 'h':
@@ -834,16 +830,12 @@ nextch1:
 					longflag = 1;
 				goto nextch1;
 			case 'z':
-#if SIZEOF_SIZE_T == 8
-#ifdef HAVE_LONG_INT_64
+#if SIZEOF_SIZE_T == SIZEOF_LONG
 				longflag = 1;
-#elif defined(HAVE_LONG_LONG_INT_64)
+#elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG
 				longlongflag = 1;
 #else
-#error "Don't know how to print 64bit integers"
-#endif
-#else
-				/* assume size_t is same size as int */
+#error "cannot find integer type of the same size as size_t"
 #endif
 				goto nextch1;
 			case 'h':
-- 
2.39.5 (Apple Git-154)

#35Thomas Munro
thomas.munro@gmail.com
In reply to: Thomas Munro (#33)
1 attachment(s)
Re: Cannot find a working 64-bit integer type on Illumos

On Fri, Nov 29, 2024 at 11:12 PM Thomas Munro <thomas.munro@gmail.com> wrote:

New idea: let's just redefine PRI...{32,64,PTR} on that platform,
instead of modifying snprintf.c.

D'oh, that's not going to fly. gettext() would replace %<PRId64> with
the system's PRId64, so we can't avoid teaching our snprintf.c to
understand Windowsian format strings. Here's a first attempt at that.
Tested a bit by removing the #ifdef WIN32 locally and playing around
with it. CI passes on Windows, and I think that should be exercising
it via existing [U]INT64_FORMAT in various places that would break if
it didn't work.

It would be nice to see it working via gettext() too, but NLS seems to
be disabled on that OS in CI (and also the BF). Huh, that seems
non-ideal. Transcripts on pgsql-bugs show it working on that OS
though (with occasional encoding glitches, apparently), so I guess the
EDB build must have it enabled.

I tried out the gettext() support for this on Unix. I didn't bother
with xgettext etc, I just manually added a message to fr.po to test
the runtime based on an example in another project, and it worked
unsurprisingly:

-                                errmsg("REJECT_LIMIT (%lld) must be
greater than zero",
-                                               (long long) reject_limit)));
+                                errmsg("REJECT_LIMIT (%" PRId64 ")
must be greater than zero",
+                                               reject_limit)));
+#, c-format
+msgid "REJECT_LIMIT (%<PRId64>) must be greater than zero"
+msgstr "REJECT_LIMIT (%<PRId64>) doit être supérieure à zéro"

postgres=# copy t from '/dev/null' with (reject_limit -1);
ERREUR: REJECT_LIMIT (-1) doit être supérieure à zéro

Attachments:

v6-0001-Use-stdint.h-and-inttypes.h-for-integer-types.patchtext/x-patch; charset=US-ASCII; name=v6-0001-Use-stdint.h-and-inttypes.h-for-integer-types.patchDownload
From 22e6601f345285e0b823771d5f8acde5d59709e7 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Thu, 18 Apr 2024 07:53:10 +1200
Subject: [PATCH v6] Use <stdint.h> and <inttypes.h> for integer types.

Use standard types and support for 64 bit integers, including int64_t,
INT64_MAX, INT64_C(), PRId64 etc.  Also use standard definitions of the
smaller integers.

One complication is that Windows' <inttypes.h> uses format strings like
%I64d, %I32, %I for PRI*64, PRI*32, PTR*PTR, rather than standard format
strings like %ld as seen on other systems.  We have to teach our own
snprintf.c to recognize them.

Work in progress...

Reviewed-by: Peter Eisentraut <peter@eisentraut.org>
Discussion: https://postgr.es/m/ME3P282MB3166F9D1F71F787929C0C7E7B6312%40ME3P282MB3166.AUSP282.PROD.OUTLOOK.COM
---
 config/c-compiler.m4                          |  78 +---
 configure                                     | 354 +++++-------------
 configure.ac                                  |  52 +--
 meson.build                                   |  44 +--
 src/Makefile.global.in                        |   6 -
 src/bin/pg_waldump/pg_waldump.c               |  16 +-
 src/bin/pgbench/pgbench.c                     |   4 +-
 src/include/.gitignore                        |   2 -
 src/include/Makefile                          |   8 +-
 src/include/c.h                               | 101 ++---
 src/include/meson.build                       |  10 -
 src/include/pg_config.h.in                    |  25 +-
 src/include/pg_config_ext.h.in                |   7 -
 src/include/pg_config_ext.h.meson             |   7 -
 src/include/port/pg_bitutils.h                |  16 +-
 src/include/postgres_ext.h                    |   4 +-
 src/include/utils/dsa.h                       |   2 +-
 src/interfaces/ecpg/ecpglib/typename.c        |   9 +-
 src/interfaces/ecpg/include/ecpg_config.h.in  |   8 +-
 src/interfaces/ecpg/include/meson.build       |   4 +-
 .../ecpg/include/pgtypes_interval.h           |  12 +-
 src/interfaces/ecpg/include/sqltypes.h        |   8 +-
 .../test/expected/compat_informix-sqlda.c     |   8 +-
 src/port/pg_bitutils.c                        |   6 +-
 src/port/snprintf.c                           |  64 +++-
 25 files changed, 274 insertions(+), 581 deletions(-)
 delete mode 100644 src/include/pg_config_ext.h.in
 delete mode 100644 src/include/pg_config_ext.h.meson

diff --git a/config/c-compiler.m4 b/config/c-compiler.m4
index 309d5b04b46..e112fd45d48 100644
--- a/config/c-compiler.m4
+++ b/config/c-compiler.m4
@@ -38,60 +38,6 @@ ac_c_werror_flag=$ac_save_c_werror_flag
 ])# PGAC_TEST_PRINTF_ARCHETYPE
 
 
-# PGAC_TYPE_64BIT_INT(TYPE)
-# -------------------------
-# Check if TYPE is a working 64 bit integer type. Set HAVE_TYPE_64 to
-# yes or no respectively, and define HAVE_TYPE_64 if yes.
-AC_DEFUN([PGAC_TYPE_64BIT_INT],
-[define([Ac_define], [translit([have_$1_64], [a-z *], [A-Z_P])])dnl
-define([Ac_cachevar], [translit([pgac_cv_type_$1_64], [ *], [_p])])dnl
-AC_CACHE_CHECK([whether $1 is 64 bits], [Ac_cachevar],
-[AC_RUN_IFELSE([AC_LANG_SOURCE(
-[typedef $1 ac_int64;
-
-/*
- * These are globals to discourage the compiler from folding all the
- * arithmetic tests down to compile-time constants.
- */
-ac_int64 a = 20000001;
-ac_int64 b = 40000005;
-
-int does_int64_work()
-{
-  ac_int64 c,d;
-
-  if (sizeof(ac_int64) != 8)
-    return 0;			/* definitely not the right size */
-
-  /* Do perfunctory checks to see if 64-bit arithmetic seems to work */
-  c = a * b;
-  d = (c + b) / b;
-  if (d != a+1)
-    return 0;
-  return 1;
-}
-
-int
-main() {
-  return (! does_int64_work());
-}])],
-[Ac_cachevar=yes],
-[Ac_cachevar=no],
-[# If cross-compiling, check the size reported by the compiler and
-# trust that the arithmetic works.
-AC_COMPILE_IFELSE([AC_LANG_BOOL_COMPILE_TRY([], [sizeof($1) == 8])],
-                  Ac_cachevar=yes,
-                  Ac_cachevar=no)])])
-
-Ac_define=$Ac_cachevar
-if test x"$Ac_cachevar" = xyes ; then
-  AC_DEFINE(Ac_define, 1, [Define to 1 if `]$1[' works and is 64 bits.])
-fi
-undefine([Ac_define])dnl
-undefine([Ac_cachevar])dnl
-])# PGAC_TYPE_64BIT_INT
-
-
 # PGAC_TYPE_128BIT_INT
 # --------------------
 # Check if __int128 is a working 128 bit integer type, and if so
@@ -270,9 +216,10 @@ fi])# PGAC_C_BUILTIN_CONSTANT_P
 AC_DEFUN([PGAC_C_BUILTIN_OP_OVERFLOW],
 [AC_CACHE_CHECK(for __builtin_mul_overflow, pgac_cv__builtin_op_overflow,
 [AC_LINK_IFELSE([AC_LANG_PROGRAM([
-PG_INT64_TYPE a = 1;
-PG_INT64_TYPE b = 1;
-PG_INT64_TYPE result;
+#include <stdint.h>
+int64_t a = 1;
+int64_t b = 1;
+int64_t result;
 int oflo;
 ],
 [oflo = __builtin_mul_overflow(a, b, &result);])],
@@ -557,13 +504,13 @@ fi])# PGAC_HAVE_GCC__SYNC_INT32_CAS
 # types, and define HAVE_GCC__SYNC_INT64_CAS if so.
 AC_DEFUN([PGAC_HAVE_GCC__SYNC_INT64_CAS],
 [AC_CACHE_CHECK(for builtin __sync int64 atomic operations, pgac_cv_gcc_sync_int64_cas,
-[AC_LINK_IFELSE([AC_LANG_PROGRAM([],
-  [PG_INT64_TYPE lock = 0;
-   __sync_val_compare_and_swap(&lock, 0, (PG_INT64_TYPE) 37);])],
+[AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <stdint.h>],
+  [int64_t lock = 0;
+   __sync_val_compare_and_swap(&lock, 0, (int64_t) 37);])],
   [pgac_cv_gcc_sync_int64_cas="yes"],
   [pgac_cv_gcc_sync_int64_cas="no"])])
 if test x"$pgac_cv_gcc_sync_int64_cas" = x"yes"; then
-  AC_DEFINE(HAVE_GCC__SYNC_INT64_CAS, 1, [Define to 1 if you have __sync_val_compare_and_swap(int64 *, int64, int64).])
+  AC_DEFINE(HAVE_GCC__SYNC_INT64_CAS, 1, [Define to 1 if you have __sync_val_compare_and_swap(int64_t *, int64_t, int64_t).])
 fi])# PGAC_HAVE_GCC__SYNC_INT64_CAS
 
 # PGAC_HAVE_GCC__ATOMIC_INT32_CAS
@@ -588,9 +535,9 @@ fi])# PGAC_HAVE_GCC__ATOMIC_INT32_CAS
 # types, and define HAVE_GCC__ATOMIC_INT64_CAS if so.
 AC_DEFUN([PGAC_HAVE_GCC__ATOMIC_INT64_CAS],
 [AC_CACHE_CHECK(for builtin __atomic int64 atomic operations, pgac_cv_gcc_atomic_int64_cas,
-[AC_LINK_IFELSE([AC_LANG_PROGRAM([],
-  [PG_INT64_TYPE val = 0;
-   PG_INT64_TYPE expect = 0;
+[AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <stdint.h>],
+  [int64_t val = 0;
+   int64_t expect = 0;
    __atomic_compare_exchange_n(&val, &expect, 37, 0, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);])],
   [pgac_cv_gcc_atomic_int64_cas="yes"],
   [pgac_cv_gcc_atomic_int64_cas="no"])])
@@ -734,13 +681,14 @@ AC_DEFUN([PGAC_AVX512_POPCNT_INTRINSICS],
 [define([Ac_cachevar], [AS_TR_SH([pgac_cv_avx512_popcnt_intrinsics])])dnl
 AC_CACHE_CHECK([for _mm512_popcnt_epi64], [Ac_cachevar],
 [AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <immintrin.h>
+    #include <stdint.h>
     #if defined(__has_attribute) && __has_attribute (target)
     __attribute__((target("avx512vpopcntdq,avx512bw")))
     #endif
     static int popcount_test(void)
     {
       const char buf@<:@sizeof(__m512i)@:>@;
-      PG_INT64_TYPE popcnt = 0;
+      int64_t popcnt = 0;
       __m512i accum = _mm512_setzero_si512();
       const __m512i val = _mm512_maskz_loadu_epi8((__mmask64) 0xf0f0f0f0f0f0f0f0, (const __m512i *) buf);
       const __m512i cnt = _mm512_popcnt_epi64(val);
diff --git a/configure b/configure
index ff59f1422d8..bc49cebc990 100755
--- a/configure
+++ b/configure
@@ -14436,6 +14436,43 @@ if test x"$pgac_cv__builtin_constant_p" = xyes ; then
 
 $as_echo "#define HAVE__BUILTIN_CONSTANT_P 1" >>confdefs.h
 
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_mul_overflow" >&5
+$as_echo_n "checking for __builtin_mul_overflow... " >&6; }
+if ${pgac_cv__builtin_op_overflow+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <stdint.h>
+int64_t a = 1;
+int64_t b = 1;
+int64_t result;
+int oflo;
+
+int
+main ()
+{
+oflo = __builtin_mul_overflow(a, b, &result);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  pgac_cv__builtin_op_overflow=yes
+else
+  pgac_cv__builtin_op_overflow=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv__builtin_op_overflow" >&5
+$as_echo "$pgac_cv__builtin_op_overflow" >&6; }
+if test x"$pgac_cv__builtin_op_overflow" = xyes ; then
+
+$as_echo "#define HAVE__BUILTIN_OP_OVERFLOW 1" >>confdefs.h
+
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_unreachable" >&5
 $as_echo_n "checking for __builtin_unreachable... " >&6; }
@@ -16196,236 +16233,6 @@ fi
 # Run tests below here
 # --------------------
 
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether long int is 64 bits" >&5
-$as_echo_n "checking whether long int is 64 bits... " >&6; }
-if ${pgac_cv_type_long_int_64+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test "$cross_compiling" = yes; then :
-  # If cross-compiling, check the size reported by the compiler and
-# trust that the arithmetic works.
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-static int test_array [1 - 2 * !(sizeof(long int) == 8)];
-test_array [0] = 0;
-return test_array [0];
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  pgac_cv_type_long_int_64=yes
-else
-  pgac_cv_type_long_int_64=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-typedef long int ac_int64;
-
-/*
- * These are globals to discourage the compiler from folding all the
- * arithmetic tests down to compile-time constants.
- */
-ac_int64 a = 20000001;
-ac_int64 b = 40000005;
-
-int does_int64_work()
-{
-  ac_int64 c,d;
-
-  if (sizeof(ac_int64) != 8)
-    return 0;			/* definitely not the right size */
-
-  /* Do perfunctory checks to see if 64-bit arithmetic seems to work */
-  c = a * b;
-  d = (c + b) / b;
-  if (d != a+1)
-    return 0;
-  return 1;
-}
-
-int
-main() {
-  return (! does_int64_work());
-}
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
-  pgac_cv_type_long_int_64=yes
-else
-  pgac_cv_type_long_int_64=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
-  conftest.$ac_objext conftest.beam conftest.$ac_ext
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_type_long_int_64" >&5
-$as_echo "$pgac_cv_type_long_int_64" >&6; }
-
-HAVE_LONG_INT_64=$pgac_cv_type_long_int_64
-if test x"$pgac_cv_type_long_int_64" = xyes ; then
-
-$as_echo "#define HAVE_LONG_INT_64 1" >>confdefs.h
-
-fi
-
-
-if test x"$HAVE_LONG_INT_64" = x"yes" ; then
-  pg_int64_type="long int"
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether long long int is 64 bits" >&5
-$as_echo_n "checking whether long long int is 64 bits... " >&6; }
-if ${pgac_cv_type_long_long_int_64+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test "$cross_compiling" = yes; then :
-  # If cross-compiling, check the size reported by the compiler and
-# trust that the arithmetic works.
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-static int test_array [1 - 2 * !(sizeof(long long int) == 8)];
-test_array [0] = 0;
-return test_array [0];
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  pgac_cv_type_long_long_int_64=yes
-else
-  pgac_cv_type_long_long_int_64=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-typedef long long int ac_int64;
-
-/*
- * These are globals to discourage the compiler from folding all the
- * arithmetic tests down to compile-time constants.
- */
-ac_int64 a = 20000001;
-ac_int64 b = 40000005;
-
-int does_int64_work()
-{
-  ac_int64 c,d;
-
-  if (sizeof(ac_int64) != 8)
-    return 0;			/* definitely not the right size */
-
-  /* Do perfunctory checks to see if 64-bit arithmetic seems to work */
-  c = a * b;
-  d = (c + b) / b;
-  if (d != a+1)
-    return 0;
-  return 1;
-}
-
-int
-main() {
-  return (! does_int64_work());
-}
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
-  pgac_cv_type_long_long_int_64=yes
-else
-  pgac_cv_type_long_long_int_64=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
-  conftest.$ac_objext conftest.beam conftest.$ac_ext
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_type_long_long_int_64" >&5
-$as_echo "$pgac_cv_type_long_long_int_64" >&6; }
-
-HAVE_LONG_LONG_INT_64=$pgac_cv_type_long_long_int_64
-if test x"$pgac_cv_type_long_long_int_64" = xyes ; then
-
-$as_echo "#define HAVE_LONG_LONG_INT_64 1" >>confdefs.h
-
-fi
-
-  if test x"$HAVE_LONG_LONG_INT_64" = x"yes" ; then
-    pg_int64_type="long long int"
-  else
-    as_fn_error $? "Cannot find a working 64-bit integer type." "$LINENO" 5
-  fi
-fi
-
-
-cat >>confdefs.h <<_ACEOF
-#define PG_INT64_TYPE $pg_int64_type
-_ACEOF
-
-
-# Select the printf length modifier that goes with that, too.
-if test x"$pg_int64_type" = x"long long int" ; then
-  INT64_MODIFIER='"ll"'
-else
-  INT64_MODIFIER='"l"'
-fi
-
-
-cat >>confdefs.h <<_ACEOF
-#define INT64_MODIFIER $INT64_MODIFIER
-_ACEOF
-
-
-# has to be down here, rather than with the other builtins, because
-# the test uses PG_INT64_TYPE.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_mul_overflow" >&5
-$as_echo_n "checking for __builtin_mul_overflow... " >&6; }
-if ${pgac_cv__builtin_op_overflow+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-PG_INT64_TYPE a = 1;
-PG_INT64_TYPE b = 1;
-PG_INT64_TYPE result;
-int oflo;
-
-int
-main ()
-{
-oflo = __builtin_mul_overflow(a, b, &result);
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-  pgac_cv__builtin_op_overflow=yes
-else
-  pgac_cv__builtin_op_overflow=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv__builtin_op_overflow" >&5
-$as_echo "$pgac_cv__builtin_op_overflow" >&6; }
-if test x"$pgac_cv__builtin_op_overflow" = xyes ; then
-
-$as_echo "#define HAVE__BUILTIN_OP_OVERFLOW 1" >>confdefs.h
-
-fi
-
 # Check size of void *, size_t (enables tweaks for > 32bit address space)
 # The cast to long int works around a bug in the HP C Compiler
 # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
@@ -16526,6 +16333,39 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long long" >&5
+$as_echo_n "checking size of long long... " >&6; }
+if ${ac_cv_sizeof_long_long+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long long))" "ac_cv_sizeof_long_long"        "$ac_includes_default"; then :
+
+else
+  if test "$ac_cv_type_long_long" = yes; then
+     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (long long)
+See \`config.log' for more details" "$LINENO" 5; }
+   else
+     ac_cv_sizeof_long_long=0
+   fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long_long" >&5
+$as_echo "$ac_cv_sizeof_long_long" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_LONG_LONG $ac_cv_sizeof_long_long
+_ACEOF
+
+
 
 # Determine memory alignment requirements for the basic C data types.
 
@@ -16634,43 +16474,41 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
-if test x"$HAVE_LONG_LONG_INT_64" = x"yes" ; then
-  # The cast to long int works around a bug in the HP C Compiler,
+# The cast to long int works around a bug in the HP C Compiler,
 # see AC_CHECK_SIZEOF for more information.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking alignment of long long int" >&5
-$as_echo_n "checking alignment of long long int... " >&6; }
-if ${ac_cv_alignof_long_long_int+:} false; then :
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking alignment of int64_t" >&5
+$as_echo_n "checking alignment of int64_t... " >&6; }
+if ${ac_cv_alignof_int64_t+:} false; then :
   $as_echo_n "(cached) " >&6
 else
-  if ac_fn_c_compute_int "$LINENO" "(long int) offsetof (ac__type_alignof_, y)" "ac_cv_alignof_long_long_int"        "$ac_includes_default
+  if ac_fn_c_compute_int "$LINENO" "(long int) offsetof (ac__type_alignof_, y)" "ac_cv_alignof_int64_t"        "$ac_includes_default
 #ifndef offsetof
 # define offsetof(type, member) ((char *) &((type *) 0)->member - (char *) 0)
 #endif
-typedef struct { char x; long long int y; } ac__type_alignof_;"; then :
+typedef struct { char x; int64_t y; } ac__type_alignof_;"; then :
 
 else
-  if test "$ac_cv_type_long_long_int" = yes; then
+  if test "$ac_cv_type_int64_t" = yes; then
      { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error 77 "cannot compute alignment of long long int
+as_fn_error 77 "cannot compute alignment of int64_t
 See \`config.log' for more details" "$LINENO" 5; }
    else
-     ac_cv_alignof_long_long_int=0
+     ac_cv_alignof_int64_t=0
    fi
 fi
 
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_alignof_long_long_int" >&5
-$as_echo "$ac_cv_alignof_long_long_int" >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_alignof_int64_t" >&5
+$as_echo "$ac_cv_alignof_int64_t" >&6; }
 
 
 
 cat >>confdefs.h <<_ACEOF
-#define ALIGNOF_LONG_LONG_INT $ac_cv_alignof_long_long_int
+#define ALIGNOF_INT64_T $ac_cv_alignof_int64_t
 _ACEOF
 
 
-fi
 # The cast to long int works around a bug in the HP C Compiler,
 # see AC_CHECK_SIZEOF for more information.
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking alignment of double" >&5
@@ -16728,8 +16566,8 @@ MAX_ALIGNOF=$ac_cv_alignof_double
 if test $ac_cv_alignof_long -gt $MAX_ALIGNOF ; then
   as_fn_error $? "alignment of 'long' is greater than the alignment of 'double'" "$LINENO" 5
 fi
-if test x"$HAVE_LONG_LONG_INT_64" = xyes && test $ac_cv_alignof_long_long_int -gt $MAX_ALIGNOF ; then
-  as_fn_error $? "alignment of 'long long int' is greater than the alignment of 'double'" "$LINENO" 5
+if test $ac_cv_alignof_int64_t -gt $MAX_ALIGNOF ; then
+  as_fn_error $? "alignment of 'int64_t' is greater than the alignment of 'double'" "$LINENO" 5
 fi
 
 cat >>confdefs.h <<_ACEOF
@@ -16737,7 +16575,6 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
-
 # Some compilers offer a 128-bit integer scalar type.
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __int128" >&5
 $as_echo_n "checking for __int128... " >&6; }
@@ -16992,12 +16829,12 @@ if ${pgac_cv_gcc_sync_int64_cas+:} false; then :
 else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
-
+#include <stdint.h>
 int
 main ()
 {
-PG_INT64_TYPE lock = 0;
-   __sync_val_compare_and_swap(&lock, 0, (PG_INT64_TYPE) 37);
+int64_t lock = 0;
+   __sync_val_compare_and_swap(&lock, 0, (int64_t) 37);
   ;
   return 0;
 }
@@ -17057,12 +16894,12 @@ if ${pgac_cv_gcc_atomic_int64_cas+:} false; then :
 else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
-
+#include <stdint.h>
 int
 main ()
 {
-PG_INT64_TYPE val = 0;
-   PG_INT64_TYPE expect = 0;
+int64_t val = 0;
+   int64_t expect = 0;
    __atomic_compare_exchange_n(&val, &expect, 37, 0, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);
   ;
   return 0;
@@ -17278,13 +17115,14 @@ else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 #include <immintrin.h>
+    #include <stdint.h>
     #if defined(__has_attribute) && __has_attribute (target)
     __attribute__((target("avx512vpopcntdq,avx512bw")))
     #endif
     static int popcount_test(void)
     {
       const char buf[sizeof(__m512i)];
-      PG_INT64_TYPE popcnt = 0;
+      int64_t popcnt = 0;
       __m512i accum = _mm512_setzero_si512();
       const __m512i val = _mm512_maskz_loadu_epi8((__mmask64) 0xf0f0f0f0f0f0f0f0, (const __m512i *) buf);
       const __m512i cnt = _mm512_popcnt_epi64(val);
@@ -18954,9 +18792,6 @@ fi
 ac_config_headers="$ac_config_headers src/include/pg_config.h"
 
 
-ac_config_headers="$ac_config_headers src/include/pg_config_ext.h"
-
-
 ac_config_headers="$ac_config_headers src/interfaces/ecpg/include/ecpg_config.h"
 
 
@@ -19671,7 +19506,6 @@ do
     "src/Makefile.port") CONFIG_LINKS="$CONFIG_LINKS src/Makefile.port:src/makefiles/Makefile.${template}" ;;
     "check_win32_symlinks") CONFIG_COMMANDS="$CONFIG_COMMANDS check_win32_symlinks" ;;
     "src/include/pg_config.h") CONFIG_HEADERS="$CONFIG_HEADERS src/include/pg_config.h" ;;
-    "src/include/pg_config_ext.h") CONFIG_HEADERS="$CONFIG_HEADERS src/include/pg_config_ext.h" ;;
     "src/interfaces/ecpg/include/ecpg_config.h") CONFIG_HEADERS="$CONFIG_HEADERS src/interfaces/ecpg/include/ecpg_config.h" ;;
 
   *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
@@ -20279,10 +20113,6 @@ $as_echo "$as_me: WARNING: *** link for $FILE -- please fix by hand" >&2;}
     "src/include/pg_config.h":H)
 # Update timestamp for pg_config.h (see Makefile.global)
 echo >src/include/stamp-h
- ;;
-    "src/include/pg_config_ext.h":H)
-# Update timestamp for pg_config_ext.h (see Makefile.global)
-echo >src/include/stamp-ext-h
  ;;
     "src/interfaces/ecpg/include/ecpg_config.h":H) echo >src/interfaces/ecpg/include/stamp-h ;;
 
diff --git a/configure.ac b/configure.ac
index 21817009642..074ecc62d20 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1604,6 +1604,7 @@ PGAC_C_STATIC_ASSERT
 PGAC_C_TYPEOF
 PGAC_C_TYPES_COMPATIBLE
 PGAC_C_BUILTIN_CONSTANT_P
+PGAC_C_BUILTIN_OP_OVERFLOW
 PGAC_C_BUILTIN_UNREACHABLE
 PGAC_C_COMPUTED_GOTO
 PGAC_STRUCT_TIMEZONE
@@ -1906,54 +1907,18 @@ for the exact reason.]])],
 # Run tests below here
 # --------------------
 
-dnl Check to see if we have a working 64-bit integer type.
-dnl Since Postgres 8.4, we no longer support compilers without a working
-dnl 64-bit type; but we have to determine whether that type is called
-dnl "long int" or "long long int".
-
-PGAC_TYPE_64BIT_INT([long int])
-
-if test x"$HAVE_LONG_INT_64" = x"yes" ; then
-  pg_int64_type="long int"
-else
-  PGAC_TYPE_64BIT_INT([long long int])
-  if test x"$HAVE_LONG_LONG_INT_64" = x"yes" ; then
-    pg_int64_type="long long int"
-  else
-    AC_MSG_ERROR([Cannot find a working 64-bit integer type.])
-  fi
-fi
-
-AC_DEFINE_UNQUOTED(PG_INT64_TYPE, $pg_int64_type,
-  [Define to the name of a signed 64-bit integer type.])
-
-# Select the printf length modifier that goes with that, too.
-if test x"$pg_int64_type" = x"long long int" ; then
-  INT64_MODIFIER='"ll"'
-else
-  INT64_MODIFIER='"l"'
-fi
-
-AC_DEFINE_UNQUOTED(INT64_MODIFIER, $INT64_MODIFIER,
-                   [Define to the appropriate printf length modifier for 64-bit ints.])
-
-# has to be down here, rather than with the other builtins, because
-# the test uses PG_INT64_TYPE.
-PGAC_C_BUILTIN_OP_OVERFLOW
-
 # Check size of void *, size_t (enables tweaks for > 32bit address space)
 AC_CHECK_SIZEOF([void *])
 AC_CHECK_SIZEOF([size_t])
 AC_CHECK_SIZEOF([long])
+AC_CHECK_SIZEOF([long long])
 
 # Determine memory alignment requirements for the basic C data types.
 
 AC_CHECK_ALIGNOF(short)
 AC_CHECK_ALIGNOF(int)
 AC_CHECK_ALIGNOF(long)
-if test x"$HAVE_LONG_LONG_INT_64" = x"yes" ; then
-  AC_CHECK_ALIGNOF(long long int)
-fi
+AC_CHECK_ALIGNOF(int64_t)
 AC_CHECK_ALIGNOF(double)
 
 # Compute maximum alignment of any basic type.
@@ -1977,12 +1942,11 @@ MAX_ALIGNOF=$ac_cv_alignof_double
 if test $ac_cv_alignof_long -gt $MAX_ALIGNOF ; then
   AC_MSG_ERROR([alignment of 'long' is greater than the alignment of 'double'])
 fi
-if test x"$HAVE_LONG_LONG_INT_64" = xyes && test $ac_cv_alignof_long_long_int -gt $MAX_ALIGNOF ; then
-  AC_MSG_ERROR([alignment of 'long long int' is greater than the alignment of 'double'])
+if test $ac_cv_alignof_int64_t -gt $MAX_ALIGNOF ; then
+  AC_MSG_ERROR([alignment of 'int64_t' is greater than the alignment of 'double'])
 fi
 AC_DEFINE_UNQUOTED(MAXIMUM_ALIGNOF, $MAX_ALIGNOF, [Define as the maximum alignment requirement of any C data type.])
 
-
 # Some compilers offer a 128-bit integer scalar type.
 PGAC_TYPE_128BIT_INT
 
@@ -2472,12 +2436,6 @@ AC_CONFIG_HEADERS([src/include/pg_config.h],
 echo >src/include/stamp-h
 ])
 
-AC_CONFIG_HEADERS([src/include/pg_config_ext.h],
-[
-# Update timestamp for pg_config_ext.h (see Makefile.global)
-echo >src/include/stamp-ext-h
-])
-
 AC_CONFIG_HEADERS([src/interfaces/ecpg/include/ecpg_config.h],
                   [echo >src/interfaces/ecpg/include/stamp-h])
 
diff --git a/meson.build b/meson.build
index 451c3f6d851..a2e35bca077 100644
--- a/meson.build
+++ b/meson.build
@@ -1588,21 +1588,6 @@ if not cc.compiles(c99_test, name: 'c99', args: test_c_args)
   endif
 endif
 
-sizeof_long = cc.sizeof('long', args: test_c_args)
-cdata.set('SIZEOF_LONG', sizeof_long)
-if sizeof_long == 8
-  cdata.set('HAVE_LONG_INT_64', 1)
-  pg_int64_type = 'long int'
-  cdata.set_quoted('INT64_MODIFIER', 'l')
-elif sizeof_long == 4 and cc.sizeof('long long', args: test_c_args) == 8
-  cdata.set('HAVE_LONG_LONG_INT_64', 1)
-  pg_int64_type = 'long long int'
-  cdata.set_quoted('INT64_MODIFIER', 'll')
-else
-  error('do not know how to get a 64bit int')
-endif
-cdata.set('PG_INT64_TYPE', pg_int64_type)
-
 if host_machine.endian() == 'big'
   cdata.set('WORDS_BIGENDIAN', 1)
 endif
@@ -1626,16 +1611,21 @@ endforeach
 # of MAXIMUM_ALIGNOF to avoid that, but we no longer support any platforms
 # where TYPALIGN_DOUBLE != MAXIMUM_ALIGNOF.
 #
-# We assume without checking that int64's alignment is at least as strong
+# We assume without checking that int64_t's alignment is at least as strong
 # as long, char, short, or int.  Note that we intentionally do not consider
 # any types wider than 64 bits, as allowing MAXIMUM_ALIGNOF to exceed 8
 # would be too much of a penalty for disk and memory space.
 alignof_double = cdata.get('ALIGNOF_DOUBLE')
-if cc.alignment(pg_int64_type, args: test_c_args) > alignof_double
-  error('alignment of int64 is greater than the alignment of double')
+if cc.alignment('int64_t', args: test_c_args, prefix: '#include <stdint.h>') > alignof_double
+  error('alignment of int64_t is greater than the alignment of double')
 endif
 cdata.set('MAXIMUM_ALIGNOF', alignof_double)
 
+cdata.set('SIZEOF_LONG', cc.sizeof('long', args: test_c_args))
+cdata.set('SIZEOF_LONG_LONG', cc.sizeof('long long', args: test_c_args))
+
+# Check if __int128 is a working 128 bit integer type, and if so
+# define PG_INT128_TYPE to that typename.
 cdata.set('SIZEOF_VOID_P', cc.sizeof('void *', args: test_c_args))
 cdata.set('SIZEOF_SIZE_T', cc.sizeof('size_t', args: test_c_args))
 
@@ -1834,17 +1824,17 @@ endif
 # compile, and store the results in global variables so the compiler doesn't
 # optimize away the call.
 if cc.links('''
-    INT64 a = 1;
-    INT64 b = 1;
-    INT64 result;
+    #include <stdint.h>
+    int64_t a = 1;
+    int64_t b = 1;
+    int64_t result;
 
     int main(void)
     {
         return __builtin_mul_overflow(a, b, &result);
     }''',
     name: '__builtin_mul_overflow',
-    args: test_c_args + ['-DINT64=@0@'.format(cdata.get('PG_INT64_TYPE'))],
-    )
+    args: test_c_args)
   cdata.set('HAVE__BUILTIN_OP_OVERFLOW', 1)
 endif
 
@@ -2134,7 +2124,7 @@ int main(void)
   cdata.set(check['name'],
     cc.links(test,
       name: check['desc'],
-      args: test_c_args + ['-DINT64=@0@'.format(cdata.get('PG_INT64_TYPE'))]) ? 1 : false
+      args: test_c_args) ? 1 : false
   )
 endforeach
 
@@ -2172,6 +2162,7 @@ if host_cpu == 'x86_64'
 
   prog = '''
 #include <immintrin.h>
+#include <stdint.h>
 
 #if defined(__has_attribute) && __has_attribute (target)
 __attribute__((target("avx512vpopcntdq,avx512bw")))
@@ -2179,7 +2170,7 @@ __attribute__((target("avx512vpopcntdq,avx512bw")))
 int main(void)
 {
     const char buf[sizeof(__m512i)];
-    INT64 popcnt = 0;
+    int64_t popcnt = 0;
     __m512i accum = _mm512_setzero_si512();
     const __m512i val = _mm512_maskz_loadu_epi8((__mmask64) 0xf0f0f0f0f0f0f0f0, (const __m512i *) buf);
     const __m512i cnt = _mm512_popcnt_epi64(val);
@@ -2190,8 +2181,7 @@ int main(void)
 }
 '''
 
-  if cc.links(prog, name: 'AVX-512 popcount',
-        args: test_c_args + ['-DINT64=@0@'.format(cdata.get('PG_INT64_TYPE'))])
+  if cc.links(prog, name: 'AVX-512 popcount', args: test_c_args)
     cdata.set('USE_AVX512_POPCNT_WITH_RUNTIME_CHECK', 1)
   endif
 
diff --git a/src/Makefile.global.in b/src/Makefile.global.in
index 0f38d712d15..eac3d001211 100644
--- a/src/Makefile.global.in
+++ b/src/Makefile.global.in
@@ -840,12 +840,6 @@ $(top_builddir)/src/include/pg_config.h: $(top_builddir)/src/include/stamp-h ;
 $(top_builddir)/src/include/stamp-h: $(top_srcdir)/src/include/pg_config.h.in $(top_builddir)/config.status
 	cd $(top_builddir) && ./config.status src/include/pg_config.h
 
-# Also remake pg_config_ext.h from pg_config_ext.h.in, same logic as above.
-$(top_builddir)/src/include/pg_config_ext.h: $(top_builddir)/src/include/stamp-ext-h ;
-
-$(top_builddir)/src/include/stamp-ext-h: $(top_srcdir)/src/include/pg_config_ext.h.in $(top_builddir)/config.status
-	cd $(top_builddir) && ./config.status src/include/pg_config_ext.h
-
 # Also remake ecpg_config.h from ecpg_config.h.in if the latter changed, same
 # logic as above.
 $(top_builddir)/src/interfaces/ecpg/include/ecpg_config.h: $(top_builddir)/src/interfaces/ecpg/include/stamp-h ;
diff --git a/src/bin/pg_waldump/pg_waldump.c b/src/bin/pg_waldump/pg_waldump.c
index 1f9403fc5cf..c4b04d62965 100644
--- a/src/bin/pg_waldump/pg_waldump.c
+++ b/src/bin/pg_waldump/pg_waldump.c
@@ -610,10 +610,10 @@ XLogDumpStatsRow(const char *name,
 		tot_len_pct = 100 * (double) tot_len / total_len;
 
 	printf("%-27s "
-		   "%20" INT64_MODIFIER "u (%6.02f) "
-		   "%20" INT64_MODIFIER "u (%6.02f) "
-		   "%20" INT64_MODIFIER "u (%6.02f) "
-		   "%20" INT64_MODIFIER "u (%6.02f)\n",
+		   "%20" PRIu64 " (%6.02f) "
+		   "%20" PRIu64 " (%6.02f) "
+		   "%20" PRIu64 " (%6.02f) "
+		   "%20" PRIu64 " (%6.02f)\n",
 		   name, n, n_pct, rec_len, rec_len_pct, fpi_len, fpi_len_pct,
 		   tot_len, tot_len_pct);
 }
@@ -742,10 +742,10 @@ XLogDumpDisplayStats(XLogDumpConfig *config, XLogStats *stats)
 		fpi_len_pct = 100 * (double) total_fpi_len / total_len;
 
 	printf("%-27s "
-		   "%20" INT64_MODIFIER "u %-9s"
-		   "%20" INT64_MODIFIER "u %-9s"
-		   "%20" INT64_MODIFIER "u %-9s"
-		   "%20" INT64_MODIFIER "u %-6s\n",
+		   "%20" PRIu64 " %-9s"
+		   "%20" PRIu64 " %-9s"
+		   "%20" PRIu64 " %-9s"
+		   "%20" PRIu64 " %-6s\n",
 		   "Total", stats->count, "",
 		   total_rec_len, psprintf("[%.02f%%]", rec_len_pct),
 		   total_fpi_len, psprintf("[%.02f%%]", fpi_len_pct),
diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c
index 85e7b68baa3..c4c38099c5b 100644
--- a/src/bin/pgbench/pgbench.c
+++ b/src/bin/pgbench/pgbench.c
@@ -6568,13 +6568,13 @@ printResults(StatsData *total,
 					SimpleStats *cstats = &(*commands)->stats;
 
 					if (max_tries == 1)
-						printf("   %11.3f  %10" INT64_MODIFIER "d  %s\n",
+						printf("   %11.3f  %10" PRId64 " %s\n",
 							   (cstats->count > 0) ?
 							   1000.0 * cstats->sum / cstats->count : 0.0,
 							   (*commands)->failures,
 							   (*commands)->first_line);
 					else
-						printf("   %11.3f  %10" INT64_MODIFIER "d  %10" INT64_MODIFIER "d  %s\n",
+						printf("   %11.3f  %10" PRId64 " %10" PRId64 " %s\n",
 							   (cstats->count > 0) ?
 							   1000.0 * cstats->sum / cstats->count : 0.0,
 							   (*commands)->failures,
diff --git a/src/include/.gitignore b/src/include/.gitignore
index 51819fb4ddd..6e99e82fe0c 100644
--- a/src/include/.gitignore
+++ b/src/include/.gitignore
@@ -1,5 +1,3 @@
 /stamp-h
-/stamp-ext-h
 /pg_config.h
-/pg_config_ext.h
 /pg_config_os.h
diff --git a/src/include/Makefile b/src/include/Makefile
index b8b576a4de3..26332ff9cbc 100644
--- a/src/include/Makefile
+++ b/src/include/Makefile
@@ -13,7 +13,7 @@ top_builddir = ../..
 include $(top_builddir)/src/Makefile.global
 
 
-all: pg_config.h pg_config_ext.h pg_config_os.h
+all: pg_config.h pg_config_os.h
 
 
 # Subdirectories containing installable headers
@@ -32,7 +32,6 @@ install: all installdirs
 	$(INSTALL_DATA) $(srcdir)/postgres_ext.h   '$(DESTDIR)$(includedir)'
 	$(INSTALL_DATA) $(srcdir)/libpq/libpq-fs.h '$(DESTDIR)$(includedir)/libpq'
 	$(INSTALL_DATA) pg_config.h     '$(DESTDIR)$(includedir)'
-	$(INSTALL_DATA) pg_config_ext.h '$(DESTDIR)$(includedir)'
 	$(INSTALL_DATA) pg_config_os.h  '$(DESTDIR)$(includedir)'
 	$(INSTALL_DATA) $(srcdir)/pg_config_manual.h '$(DESTDIR)$(includedir)'
 # These headers are needed by the not-so-public headers of the interfaces.
@@ -43,7 +42,6 @@ install: all installdirs
 	$(INSTALL_DATA) $(srcdir)/libpq/protocol.h '$(DESTDIR)$(includedir_internal)/libpq'
 # These headers are needed for server-side development
 	$(INSTALL_DATA) pg_config.h     '$(DESTDIR)$(includedir_server)'
-	$(INSTALL_DATA) pg_config_ext.h '$(DESTDIR)$(includedir_server)'
 	$(INSTALL_DATA) pg_config_os.h  '$(DESTDIR)$(includedir_server)'
 	$(INSTALL_DATA) nodes/nodetags.h '$(DESTDIR)$(includedir_server)/nodes'
 	$(INSTALL_DATA) utils/errcodes.h '$(DESTDIR)$(includedir_server)/utils'
@@ -66,7 +64,7 @@ installdirs:
 
 
 uninstall:
-	rm -f $(addprefix '$(DESTDIR)$(includedir)'/, pg_config.h pg_config_ext.h pg_config_os.h pg_config_manual.h postgres_ext.h libpq/libpq-fs.h)
+	rm -f $(addprefix '$(DESTDIR)$(includedir)'/, pg_config.h pg_config_os.h pg_config_manual.h postgres_ext.h libpq/libpq-fs.h)
 	rm -f $(addprefix '$(DESTDIR)$(includedir_internal)'/, c.h port.h postgres_fe.h libpq/pqcomm.h libpq/protocol.h)
 # heuristic...
 	rm -rf $(addprefix '$(DESTDIR)$(includedir_server)'/, $(SUBDIRS) *.h)
@@ -80,4 +78,4 @@ clean:
 	$(MAKE) -C catalog clean
 
 distclean: clean
-	rm -f pg_config.h pg_config_ext.h pg_config_os.h stamp-h stamp-ext-h
+	rm -f pg_config.h pg_config_os.h stamp-h stamp-ext-h
diff --git a/src/include/c.h b/src/include/c.h
index 304dff27e34..734626e75a8 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -48,14 +48,12 @@
 
 #include "postgres_ext.h"
 
-/* Must undef pg_config_ext.h symbols before including pg_config.h */
-#undef PG_INT64_TYPE
-
 #include "pg_config.h"
 #include "pg_config_manual.h"	/* must be after pg_config.h */
 #include "pg_config_os.h"		/* must be before any system header files */
 
 /* System header files that should be available everywhere in Postgres */
+#include <inttypes.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -471,25 +469,15 @@ typedef void (*pg_funcptr_t) (void);
  */
 typedef char *Pointer;
 
-/*
- * intN
- *		Signed integer, EXACTLY N BITS IN SIZE,
- *		used for numerical computations and the
- *		frontend/backend protocol.
- */
-typedef signed char int8;		/* == 8 bits */
-typedef signed short int16;		/* == 16 bits */
-typedef signed int int32;		/* == 32 bits */
-
-/*
- * uintN
- *		Unsigned integer, EXACTLY N BITS IN SIZE,
- *		used for numerical computations and the
- *		frontend/backend protocol.
- */
-typedef unsigned char uint8;	/* == 8 bits */
-typedef unsigned short uint16;	/* == 16 bits */
-typedef unsigned int uint32;	/* == 32 bits */
+/* Historical names for types in <stdint.h>. */
+typedef int8_t int8;
+typedef int16_t int16;
+typedef int32_t int32;
+typedef int64_t int64;
+typedef uint8_t uint8;
+typedef uint16_t uint16;
+typedef uint32_t uint32;
+typedef uint64_t uint64;
 
 /*
  * bitsN
@@ -502,30 +490,14 @@ typedef uint32 bits32;			/* >= 32 bits */
 /*
  * 64-bit integers
  */
-#ifdef HAVE_LONG_INT_64
-/* Plain "long int" fits, use it */
-
-typedef long int int64;
-typedef unsigned long int uint64;
-#define INT64CONST(x)  (x##L)
-#define UINT64CONST(x) (x##UL)
-#elif defined(HAVE_LONG_LONG_INT_64)
-/* We have working support for "long long int", use that */
-
-typedef long long int int64;
-typedef unsigned long long int uint64;
-#define INT64CONST(x)  (x##LL)
-#define UINT64CONST(x) (x##ULL)
-#else
-/* neither HAVE_LONG_INT_64 nor HAVE_LONG_LONG_INT_64 */
-#error must have a working 64-bit integer datatype
-#endif
+#define INT64CONST(x)  INT64_C(x)
+#define UINT64CONST(x) UINT64_C(x)
 
 /* snprintf format strings to use for 64-bit integers */
-#define INT64_FORMAT "%" INT64_MODIFIER "d"
-#define UINT64_FORMAT "%" INT64_MODIFIER "u"
-#define INT64_HEX_FORMAT "%" INT64_MODIFIER "x"
-#define UINT64_HEX_FORMAT "%" INT64_MODIFIER "x"
+#define INT64_FORMAT "%" PRId64
+#define UINT64_FORMAT "%" PRIu64
+#define INT64_HEX_FORMAT "%" PRIx64
+#define UINT64_HEX_FORMAT "%" PRIx64
 
 /*
  * 128-bit signed and unsigned integers
@@ -554,22 +526,19 @@ typedef unsigned PG_INT128_TYPE uint128
 #endif
 #endif
 
-/*
- * stdint.h limits aren't guaranteed to have compatible types with our fixed
- * width types. So just define our own.
- */
-#define PG_INT8_MIN		(-0x7F-1)
-#define PG_INT8_MAX		(0x7F)
-#define PG_UINT8_MAX	(0xFF)
-#define PG_INT16_MIN	(-0x7FFF-1)
-#define PG_INT16_MAX	(0x7FFF)
-#define PG_UINT16_MAX	(0xFFFF)
-#define PG_INT32_MIN	(-0x7FFFFFFF-1)
-#define PG_INT32_MAX	(0x7FFFFFFF)
-#define PG_UINT32_MAX	(0xFFFFFFFFU)
-#define PG_INT64_MIN	(-INT64CONST(0x7FFFFFFFFFFFFFFF) - 1)
-#define PG_INT64_MAX	INT64CONST(0x7FFFFFFFFFFFFFFF)
-#define PG_UINT64_MAX	UINT64CONST(0xFFFFFFFFFFFFFFFF)
+/* Historical names for limits in <stdint.h>. */
+#define PG_INT8_MIN		INT8_MIN
+#define PG_INT8_MAX		INT8_MAX
+#define PG_UINT8_MAX	UINT8_MAX
+#define PG_INT16_MIN	INT16_MIN
+#define PG_INT16_MAX	INT16_MAX
+#define PG_UINT16_MAX	UINT16_MAX
+#define PG_INT32_MIN	INT32_MIN
+#define PG_INT32_MAX	INT32_MAX
+#define PG_UINT32_MAX	UINT32_MAX
+#define PG_INT64_MIN	INT64_MIN
+#define PG_INT64_MAX	INT64_MAX
+#define PG_UINT64_MAX	UINT64_MAX
 
 /*
  * We now always use int64 timestamps, but keep this symbol defined for the
@@ -1272,21 +1241,25 @@ extern int	fdatasync(int fildes);
  * definition of int64.  (For the naming, compare that POSIX has
  * strtoimax()/strtoumax() which return intmax_t/uintmax_t.)
  */
-#ifdef HAVE_LONG_INT_64
+#if SIZEOF_LONG == 8
 #define strtoi64(str, endptr, base) ((int64) strtol(str, endptr, base))
 #define strtou64(str, endptr, base) ((uint64) strtoul(str, endptr, base))
-#else
+#elif SIZEOF_LONG_LONG == 8
 #define strtoi64(str, endptr, base) ((int64) strtoll(str, endptr, base))
 #define strtou64(str, endptr, base) ((uint64) strtoull(str, endptr, base))
+#else
+#error "cannot find integer type of the same size as int64_t"
 #endif
 
 /*
  * Similarly, wrappers around labs()/llabs() matching our int64.
  */
-#ifdef HAVE_LONG_INT_64
+#if SIZEOF_LONG == 8
 #define i64abs(i) labs(i)
-#else
+#elif SIZEOF_LONG_LONG == 8
 #define i64abs(i) llabs(i)
+#else
+#error "cannot find integer type of the same size as int64_t"
 #endif
 
 /*
diff --git a/src/include/meson.build b/src/include/meson.build
index 58b7a9c1e7e..e691b12b8a0 100644
--- a/src/include/meson.build
+++ b/src/include/meson.build
@@ -1,14 +1,5 @@
 # Copyright (c) 2022-2024, PostgreSQL Global Development Group
 
-pg_config_ext = configure_file(
-  input: 'pg_config_ext.h.meson',
-  output: 'pg_config_ext.h',
-  configuration: cdata,
-  install: true,
-  install_dir: dir_include,
-)
-configure_files += pg_config_ext
-
 pg_config_os = configure_file(
   output: 'pg_config_os.h',
   input: files('port/@0@.h'.format(portname)),
@@ -116,7 +107,6 @@ install_headers(
   'postgres_fe.h',
   'varatt.h',
   'windowapi.h',
-  pg_config_ext,
   pg_config_os,
   pg_config,
   install_dir: dir_include_server,
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index ab0f8cc2b4a..07b2f798abd 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -9,12 +9,12 @@
 /* The normal alignment of `int', in bytes. */
 #undef ALIGNOF_INT
 
+/* The normal alignment of `int64_t', in bytes. */
+#undef ALIGNOF_INT64_T
+
 /* The normal alignment of `long', in bytes. */
 #undef ALIGNOF_LONG
 
-/* The normal alignment of `long long int', in bytes. */
-#undef ALIGNOF_LONG_LONG_INT
-
 /* The normal alignment of `PG_INT128_TYPE', in bytes. */
 #undef ALIGNOF_PG_INT128_TYPE
 
@@ -153,8 +153,8 @@
 /* Define to 1 if you have __sync_lock_test_and_set(int *) and friends. */
 #undef HAVE_GCC__SYNC_INT32_TAS
 
-/* Define to 1 if you have __sync_val_compare_and_swap(int64 *, int64, int64).
-   */
+/* Define to 1 if you have __sync_val_compare_and_swap(int64_t *, int64_t,
+   int64_t). */
 #undef HAVE_GCC__SYNC_INT64_CAS
 
 /* Define to 1 if you have the `getauxval' function. */
@@ -265,12 +265,6 @@
 /* Define to 1 if you have the `zstd' library (-lzstd). */
 #undef HAVE_LIBZSTD
 
-/* Define to 1 if `long int' works and is 64 bits. */
-#undef HAVE_LONG_INT_64
-
-/* Define to 1 if `long long int' works and is 64 bits. */
-#undef HAVE_LONG_LONG_INT_64
-
 /* Define to 1 if you have the <mbarrier.h> header file. */
 #undef HAVE_MBARRIER_H
 
@@ -544,9 +538,6 @@
 /* Define to 1 if your compiler understands _Static_assert. */
 #undef HAVE__STATIC_ASSERT
 
-/* Define to the appropriate printf length modifier for 64-bit ints. */
-#undef INT64_MODIFIER
-
 /* Define as the maximum alignment requirement of any C data type. */
 #undef MAXIMUM_ALIGNOF
 
@@ -578,9 +569,6 @@
 /* Define to the name of a signed 128-bit integer type. */
 #undef PG_INT128_TYPE
 
-/* Define to the name of a signed 64-bit integer type. */
-#undef PG_INT64_TYPE
-
 /* Define to the name of the default PostgreSQL service principal in Kerberos
    (GSSAPI). (--with-krb-srvnam=NAME) */
 #undef PG_KRB_SRVNAM
@@ -630,6 +618,9 @@
 /* The size of `long', as computed by sizeof. */
 #undef SIZEOF_LONG
 
+/* The size of `long long', as computed by sizeof. */
+#undef SIZEOF_LONG_LONG
+
 /* The size of `off_t', as computed by sizeof. */
 #undef SIZEOF_OFF_T
 
diff --git a/src/include/pg_config_ext.h.in b/src/include/pg_config_ext.h.in
deleted file mode 100644
index 8acadbdafd4..00000000000
--- a/src/include/pg_config_ext.h.in
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
- * src/include/pg_config_ext.h.in.  This is generated manually, not by
- * autoheader, since we want to limit which symbols get defined here.
- */
-
-/* Define to the name of a signed 64-bit integer type. */
-#undef PG_INT64_TYPE
diff --git a/src/include/pg_config_ext.h.meson b/src/include/pg_config_ext.h.meson
deleted file mode 100644
index 57cdfca0cfd..00000000000
--- a/src/include/pg_config_ext.h.meson
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
- * src/include/pg_config_ext.h.in.  This is generated manually, not by
- * autoheader, since we want to limit which symbols get defined here.
- */
-
-/* Define to the name of a signed 64-bit integer type. */
-#mesondefine PG_INT64_TYPE
diff --git a/src/include/port/pg_bitutils.h b/src/include/port/pg_bitutils.h
index 4d88478c9c2..a3cad46afe9 100644
--- a/src/include/port/pg_bitutils.h
+++ b/src/include/port/pg_bitutils.h
@@ -74,13 +74,13 @@ pg_leftmost_one_pos64(uint64 word)
 #ifdef HAVE__BUILTIN_CLZ
 	Assert(word != 0);
 
-#if defined(HAVE_LONG_INT_64)
+#if SIZEOF_LONG == 8
 	return 63 - __builtin_clzl(word);
-#elif defined(HAVE_LONG_LONG_INT_64)
+#elif SIZEOF_LONG_LONG == 8
 	return 63 - __builtin_clzll(word);
 #else
-#error must have a working 64-bit integer datatype
-#endif							/* HAVE_LONG_INT_64 */
+#error "cannot find integer type of the same size as uint64_t"
+#endif
 
 #elif defined(_MSC_VER) && (defined(_M_AMD64) || defined(_M_ARM64))
 	unsigned long result;
@@ -147,13 +147,13 @@ pg_rightmost_one_pos64(uint64 word)
 #ifdef HAVE__BUILTIN_CTZ
 	Assert(word != 0);
 
-#if defined(HAVE_LONG_INT_64)
+#if SIZEOF_LONG == 8
 	return __builtin_ctzl(word);
-#elif defined(HAVE_LONG_LONG_INT_64)
+#elif SIZEOF_LONG_LONG == 8
 	return __builtin_ctzll(word);
 #else
-#error must have a working 64-bit integer datatype
-#endif							/* HAVE_LONG_INT_64 */
+#error "cannot find integer type of the same size as uint64_t"
+#endif
 
 #elif defined(_MSC_VER) && (defined(_M_AMD64) || defined(_M_ARM64))
 	unsigned long result;
diff --git a/src/include/postgres_ext.h b/src/include/postgres_ext.h
index 240ad4e93bf..202eb049622 100644
--- a/src/include/postgres_ext.h
+++ b/src/include/postgres_ext.h
@@ -23,7 +23,7 @@
 #ifndef POSTGRES_EXT_H
 #define POSTGRES_EXT_H
 
-#include "pg_config_ext.h"
+#include <stdint.h>
 
 /*
  * Object ID is a fundamental type in Postgres.
@@ -44,7 +44,7 @@ typedef unsigned int Oid;
 
 
 /* Define a signed 64-bit integer type for use in client API declarations. */
-typedef PG_INT64_TYPE pg_int64;
+typedef int64_t pg_int64;
 
 /*
  * Identifiers of error message fields.  Kept here to keep common
diff --git a/src/include/utils/dsa.h b/src/include/utils/dsa.h
index 8dff964bf33..6c952a43f79 100644
--- a/src/include/utils/dsa.h
+++ b/src/include/utils/dsa.h
@@ -66,7 +66,7 @@ typedef pg_atomic_uint64 dsa_pointer_atomic;
 #define dsa_pointer_atomic_write pg_atomic_write_u64
 #define dsa_pointer_atomic_fetch_add pg_atomic_fetch_add_u64
 #define dsa_pointer_atomic_compare_exchange pg_atomic_compare_exchange_u64
-#define DSA_POINTER_FORMAT "%016" INT64_MODIFIER "x"
+#define DSA_POINTER_FORMAT "%016" PRIx64
 #endif
 
 /* Flags for dsa_allocate_extended. */
diff --git a/src/interfaces/ecpg/ecpglib/typename.c b/src/interfaces/ecpg/ecpglib/typename.c
index 1d482c4fa61..1fb9860371b 100644
--- a/src/interfaces/ecpg/ecpglib/typename.c
+++ b/src/interfaces/ecpg/ecpglib/typename.c
@@ -131,11 +131,12 @@ sqlda_dynamic_type(Oid type, enum COMPAT_MODE compat)
 		case INTERVALOID:
 			return ECPGt_interval;
 		case INT8OID:
-#ifdef HAVE_LONG_LONG_INT_64
-			return ECPGt_long_long;
-#endif
-#ifdef HAVE_LONG_INT_64
+#if SIZEOF_LONG == 8
 			return ECPGt_long;
+#elif SIZEOF_LONG_LONG == 8
+			return ECPGt_long_long;
+#else
+#error "cannot find integer type of the same size as INT8OID"
 #endif
 			/* Unhandled types always return a string */
 		default:
diff --git a/src/interfaces/ecpg/include/ecpg_config.h.in b/src/interfaces/ecpg/include/ecpg_config.h.in
index 75f542f263b..4af45930b61 100644
--- a/src/interfaces/ecpg/include/ecpg_config.h.in
+++ b/src/interfaces/ecpg/include/ecpg_config.h.in
@@ -1,8 +1,8 @@
 /* Define to 1 to build client libraries as thread-safe code. */
 #define ENABLE_THREAD_SAFETY 1
 
-/* Define to 1 if `long int' works and is 64 bits. */
-#undef HAVE_LONG_INT_64
+/* The size of `long', as computed by sizeof. */
+#undef SIZEOF_LONG
 
-/* Define to 1 if `long long int' works and is 64 bits. */
-#undef HAVE_LONG_LONG_INT_64
+/* The size of `long long', as computed by sizeof. */
+#undef SIZEOF_LONG_LONG
diff --git a/src/interfaces/ecpg/include/meson.build b/src/interfaces/ecpg/include/meson.build
index a3beb3cc7be..c1a88e73fb8 100644
--- a/src/interfaces/ecpg/include/meson.build
+++ b/src/interfaces/ecpg/include/meson.build
@@ -3,8 +3,8 @@
 ecpg_inc = include_directories('.')
 
 ecpg_conf_keys = [
-  'HAVE_LONG_INT_64',
-  'HAVE_LONG_LONG_INT_64',
+  'SIZEOF_LONG',
+  'SIZEOF_LONG_LONG',
 ]
 
 ecpg_conf_data = configuration_data()
diff --git a/src/interfaces/ecpg/include/pgtypes_interval.h b/src/interfaces/ecpg/include/pgtypes_interval.h
index 46cfce65517..f0acbb4512a 100644
--- a/src/interfaces/ecpg/include/pgtypes_interval.h
+++ b/src/interfaces/ecpg/include/pgtypes_interval.h
@@ -3,21 +3,17 @@
 #ifndef PGTYPES_INTERVAL
 #define PGTYPES_INTERVAL
 
+#include <stdint.h>
+
 #include <ecpg_config.h>
 #include <pgtypes.h>
 
 #ifndef C_H
 
-#ifdef HAVE_LONG_INT_64
-typedef long int int64;
-#elif defined(HAVE_LONG_LONG_INT_64)
-typedef long long int int64;
-#else
-/* neither HAVE_LONG_INT_64 nor HAVE_LONG_LONG_INT_64 */
-#error must have a working 64-bit integer datatype
-#endif
+typedef int64_t int64;
 
 #define HAVE_INT64_TIMESTAMP
+
 #endif							/* C_H */
 
 typedef struct
diff --git a/src/interfaces/ecpg/include/sqltypes.h b/src/interfaces/ecpg/include/sqltypes.h
index e7cbfa47956..498840458c4 100644
--- a/src/interfaces/ecpg/include/sqltypes.h
+++ b/src/interfaces/ecpg/include/sqltypes.h
@@ -46,12 +46,14 @@
 #define SQLINTERVAL		ECPGt_interval
 #define SQLNCHAR	ECPGt_char
 #define SQLNVCHAR	ECPGt_char
-#ifdef HAVE_LONG_LONG_INT_64
+#if SIZEOF_LONG == 8
+#define SQLINT8		ECPGt_long
+#define SQLSERIAL8	ECPGt_long
+#elif SIZEOF_LONG_LONG == 8
 #define SQLINT8		ECPGt_long_long
 #define SQLSERIAL8	ECPGt_long_long
 #else
-#define SQLINT8		ECPGt_long
-#define SQLSERIAL8	ECPGt_long
+#error "cannot find integer type of the same size as SQLINT8"
 #endif
 
 #endif							/* ndef ECPG_SQLTYPES_H */
diff --git a/src/interfaces/ecpg/test/expected/compat_informix-sqlda.c b/src/interfaces/ecpg/test/expected/compat_informix-sqlda.c
index 7e19319d27f..8eebc51664e 100644
--- a/src/interfaces/ecpg/test/expected/compat_informix-sqlda.c
+++ b/src/interfaces/ecpg/test/expected/compat_informix-sqlda.c
@@ -97,12 +97,14 @@ typedef struct sqlda_struct sqlda_t;
 #define SQLINTERVAL		ECPGt_interval
 #define SQLNCHAR	ECPGt_char
 #define SQLNVCHAR	ECPGt_char
-#ifdef HAVE_LONG_LONG_INT_64
+#if SIZEOF_LONG == 8
+#define SQLINT8		ECPGt_long
+#define SQLSERIAL8	ECPGt_long
+#elif SIZEOF_LONG_LONG == 8
 #define SQLINT8		ECPGt_long_long
 #define SQLSERIAL8	ECPGt_long_long
 #else
-#define SQLINT8		ECPGt_long
-#define SQLSERIAL8	ECPGt_long
+#error "cannot find integer type of the same size as SQLINT8"
 #endif
 
 #endif							/* ndef ECPG_SQLTYPES_H */
diff --git a/src/port/pg_bitutils.c b/src/port/pg_bitutils.c
index 87f56e82b80..c8399981ee0 100644
--- a/src/port/pg_bitutils.c
+++ b/src/port/pg_bitutils.c
@@ -370,12 +370,12 @@ static inline int
 pg_popcount64_slow(uint64 word)
 {
 #ifdef HAVE__BUILTIN_POPCOUNT
-#if defined(HAVE_LONG_INT_64)
+#if SIZEOF_LONG == 8
 	return __builtin_popcountl(word);
-#elif defined(HAVE_LONG_LONG_INT_64)
+#elif SIZEOF_LONG_LONG == 8
 	return __builtin_popcountll(word);
 #else
-#error must have a working 64-bit integer datatype
+#error "cannot find integer of the same size as uint64_t"
 #endif
 #else							/* !HAVE__BUILTIN_POPCOUNT */
 	int			result = 0;
diff --git a/src/port/snprintf.c b/src/port/snprintf.c
index 884f0262dd1..c21af2fb2e7 100644
--- a/src/port/snprintf.c
+++ b/src/port/snprintf.c
@@ -560,6 +560,28 @@ nextch2:
 					fmtpos = accum;
 				accum = 0;
 				goto nextch2;
+#ifdef WIN32
+			case 'I':
+				/* Windows PRI*{32,64,PTR} size */
+				if (format[0] == '3' && format[1] == '2')
+					format += 2;
+				else if (format[0] == '6' && format[1] == '4')
+				{
+					format += 2;
+					longlongflag = 1;
+				}
+				else
+				{
+#if SIZEOF_VOID_P == SIZEOF_LONG
+				longflag = 1;
+#elif SIZEOF_VOID_P == SIZEOF_LONG_LONG
+				longlongflag = 1;
+#else
+#error "cannot find integer type of the same size as intptr_t"
+#endif
+				}
+				goto nextch2;
+#endif
 			case 'l':
 				if (longflag)
 					longlongflag = 1;
@@ -567,16 +589,12 @@ nextch2:
 					longflag = 1;
 				goto nextch2;
 			case 'z':
-#if SIZEOF_SIZE_T == 8
-#ifdef HAVE_LONG_INT_64
+#if SIZEOF_SIZE_T == SIZEOF_LONG
 				longflag = 1;
-#elif defined(HAVE_LONG_LONG_INT_64)
+#elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG
 				longlongflag = 1;
 #else
-#error "Don't know how to print 64bit integers"
-#endif
-#else
-				/* assume size_t is same size as int */
+#error "cannot find integer type of the same size as size_t"
 #endif
 				goto nextch2;
 			case 'h':
@@ -827,6 +845,28 @@ nextch1:
 					fmtpos = accum;
 				accum = 0;
 				goto nextch1;
+#ifdef WIN32
+			case 'I':
+				/* Windows PRI*{32,64,PTR} size */
+				if (format[0] == '3' && format[1] == '2')
+					format += 2;
+				else if (format[0] == '6' && format[1] == '4')
+				{
+					format += 2;
+					longlongflag = 1;
+				}
+				else
+				{
+#if SIZEOF_VOID_P == SIZEOF_LONG
+				longflag = 1;
+#elif SIZEOF_VOID_P == SIZEOF_LONG_LONG
+				longlongflag = 1;
+#else
+#error "cannot find integer type of the same size as intptr_t"
+#endif
+				}
+				goto nextch1;
+#endif
 			case 'l':
 				if (longflag)
 					longlongflag = 1;
@@ -834,16 +874,12 @@ nextch1:
 					longflag = 1;
 				goto nextch1;
 			case 'z':
-#if SIZEOF_SIZE_T == 8
-#ifdef HAVE_LONG_INT_64
+#if SIZEOF_SIZE_T == SIZEOF_LONG
 				longflag = 1;
-#elif defined(HAVE_LONG_LONG_INT_64)
+#elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG
 				longlongflag = 1;
 #else
-#error "Don't know how to print 64bit integers"
-#endif
-#else
-				/* assume size_t is same size as int */
+#error "cannot find integer type of the same size as size_t"
 #endif
 				goto nextch1;
 			case 'h':
-- 
2.47.0

#36Peter Eisentraut
peter@eisentraut.org
In reply to: Thomas Munro (#34)
Re: Cannot find a working 64-bit integer type on Illumos

On 29.11.24 20:30, Thomas Munro wrote:

On Fri, Nov 29, 2024 at 11:12 PM Thomas Munro <thomas.munro@gmail.com> wrote:
I was thinking about that ECPG stuff: I bet real applications prefer
to use int64_t etc directly too instead of long, the worst type in C.
I wondered if the embedded SQL standard might know about that these
days (ECPGt_int64_t?), but I don't have the standard to hand. DB2's
embedded SQL seems to have a type sqlint64, but I didn't look too
closely and of course even if we wanted to do something like that as
an optional API option, that'd be a later change.

Interesting:

i) If “long long” is specified, then the <host parameter data type> of
HV is BIGINT.
ii) If “long” is specified, then the <host parameter data type> of HV is
INTEGER.
iii) If “short” is specified, then the <host parameter data type> of HV
is SMALLINT.
[...]

I suppose that makes sense.

BTW I forgot to mention earlier, I peeked at the source of gettext on
NetBSD and illumos, and both appear to handle those special
<inttypes.h> tokens when loading message catalogues.

Ah great, thanks for checking that.

#37Peter Eisentraut
peter@eisentraut.org
In reply to: Thomas Munro (#35)
Re: Cannot find a working 64-bit integer type on Illumos

On 30.11.24 00:42, Thomas Munro wrote:

On Fri, Nov 29, 2024 at 11:12 PM Thomas Munro <thomas.munro@gmail.com> wrote:

New idea: let's just redefine PRI...{32,64,PTR} on that platform,
instead of modifying snprintf.c.

D'oh, that's not going to fly. gettext() would replace %<PRId64> with
the system's PRId64, so we can't avoid teaching our snprintf.c to
understand Windowsian format strings. Here's a first attempt at that.
Tested a bit by removing the #ifdef WIN32 locally and playing around
with it. CI passes on Windows, and I think that should be exercising
it via existing [U]INT64_FORMAT in various places that would break if
it didn't work.

This patch looks good to me.

In meson.build, this comment seems to be misplaced by accident:

+# Check if __int128 is a working 128 bit integer type, and if so
+# define PG_INT128_TYPE to that typename.
  cdata.set('SIZEOF_VOID_P', cc.sizeof('void *', args: test_c_args))
  cdata.set('SIZEOF_SIZE_T', cc.sizeof('size_t', args: test_c_args))

In c.h, you include <inttypes.h> instead of <stdint.h>. Is there a
reason for that?

#38Thomas Munro
thomas.munro@gmail.com
In reply to: Peter Eisentraut (#37)
Re: Cannot find a working 64-bit integer type on Illumos

On Wed, Dec 4, 2024 at 2:24 AM Peter Eisentraut <peter@eisentraut.org> wrote:

This patch looks good to me.

Thanks! Pushed. Let's see what the build farm says.

In meson.build, this comment seems to be misplaced by accident:

Oops, fixed.

In c.h, you include <inttypes.h> instead of <stdint.h>. Is there a
reason for that?

<stdint.h> was already there for uintptr_t at least. <inttypes.h> is
needed to be able to define:

#define INT64_FORMAT "%" PRId64

#39Thomas Munro
thomas.munro@gmail.com
In reply to: Thomas Munro (#38)
Re: Cannot find a working 64-bit integer type on Illumos

On Wed, Dec 4, 2024 at 4:04 PM Thomas Munro <thomas.munro@gmail.com> wrote:

Thanks! Pushed. Let's see what the build farm says.

A couple of armv7 animals seemed to die in the Perl tests. Huh. Well
I know that Perl was sensitive to this stuff but it passed on 32 bit
CI (x86). I will try to reproduce that on local ARM hardware...

#40Tom Lane
tgl@sss.pgh.pa.us
In reply to: Thomas Munro (#39)
Re: Cannot find a working 64-bit integer type on Illumos

Thomas Munro <thomas.munro@gmail.com> writes:

A couple of armv7 animals seemed to die in the Perl tests. Huh. Well
I know that Perl was sensitive to this stuff but it passed on 32 bit
CI (x86). I will try to reproduce that on local ARM hardware...

turaco seems unhappy because of

2024-12-04 05:37:14.831 GMT [9584:18] pg_regress/plperl_setup LOG: statement: CREATE EXTENSION plperl;
Util.c: loadable library and perl binaries are mismatched (got first handshake key 0xa300080, needed 0xa400080)

Not clear to me what these changes would have done to trigger that.

regards, tom lane

#41Tom Lane
tgl@sss.pgh.pa.us
In reply to: Tom Lane (#40)
Re: Cannot find a working 64-bit integer type on Illumos

Also ... grison and turaco are emitting warnings that were
not there a couple of days ago:

grison | 2024-12-04 17:10:09 | reconstruct.c:701:33: warning: passing argument 2 of 'copy_file_range' from incompatible pointer type [-Wincompatible-pointer-types]
turaco | 2024-12-04 16:15:11 | reconstruct.c:701:61: warning: passing argument 2 of 'copy_file_range' from incompatible pointer type [-Wincompatible-pointer-types]

The code they are complaining about is from ac8110155 ("Allow using
copy_file_range in write_reconstructed_file") back in April:

off_t off = offsetmap[i];
...
wb = copy_file_range(s->fd, &off, wfd, NULL, BLCKSZ - nwritten, 0);

Now, on my Linux box "man copy_file_range" saith

ssize_t copy_file_range(int fd_in, loff_t *off_in,
int fd_out, loff_t *off_out,
size_t len, unsigned int flags);

So apparently, "off_t" was the same as "loff_t" before 962da900a,
but it no longer is the same on 32-bit machines. (In any case,
if all machines that have copy_file_range define it like this,
perhaps we ought to be declaring this variable as loff_t not off_t?)

Digging a bit deeper, the full warning report is

reconstruct.c: In function "write_reconstructed_file":
reconstruct.c:701:33: warning: passing argument 2 of "copy_file_range" from incompatible pointer type [-Wincompatible-pointer-types]
wb = copy_file_range(s->fd, &off, wfd, NULL, BLCKSZ - nwritten, 0);
^~~~
In file included from reconstruct.c:15:
/usr/include/unistd.h:1107:49: note: expected "__off64_t *" {aka "long long int *"} but argument is of type "off_t *" {aka "long int *"}
ssize_t copy_file_range (int __infd, __off64_t *__pinoff,
~~~~~~~~~~~^~~~~~~~

Since these are 32-bit machines, "long int" is 32 bits (confirmed from
their configure results), which means "off_t" is only 32 bits, which
really sounds quite broken. I thought it was 64 bits pretty much
everywhere nowadays. Did 962da900a cause that? Maybe that explains
the Perl library compatibility problems these machines are reporting?

regards, tom lane

#42Thomas Munro
thomas.munro@gmail.com
In reply to: Tom Lane (#41)
Re: Cannot find a working 64-bit integer type on Illumos

On Thu, Dec 5, 2024 at 8:41 AM Tom Lane <tgl@sss.pgh.pa.us> wrote:

So apparently, "off_t" was the same as "loff_t" before 962da900a,
but it no longer is the same on 32-bit machines.

Right, that's really weird.

(In any case,
if all machines that have copy_file_range define it like this,
perhaps we ought to be declaring this variable as loff_t not off_t?)

Hmm. FreeBSD just has off_t in its declaration, but off_t is always
64 bit, and I don't think it knows about loff_t.

I guess copy_file_range() didn't follow the usual plan of respecting
_FILE_OFFSET_BITS, so there's no 32 bit off_t support for it in libc,
hence they needed to invent (or leak from the kernel?) loff_t. I
don't think we should change that, because we use AC_SYS_LARGEFILE to
find that we need -D_FILE_OFFSET_BITS=64 on 32 bit systems, so off_t
should be the same as loff_t. If something weren't broken
somewhere... Somehow it's getting lost?

Since these are 32-bit machines, "long int" is 32 bits (confirmed from
their configure results), which means "off_t" is only 32 bits, which
really sounds quite broken. I thought it was 64 bits pretty much
everywhere nowadays. Did 962da900a cause that? Maybe that explains
the Perl library compatibility problems these machines are reporting?

Right, that definitely should upset Perl, as it changes the size of
struct stat and all kinds of stuff, probably.

The affected systems are mostly running ancient OSes, and lapwing is
32 bit x86, so it's not only armv7. Current 32 bit x86 systems are
working fine. Maybe I should boot up a Debian 7 x86 build (my
attempts to run ancient Debian/armv7 on qemu last night failed, x86
sounds easier...) The armv7 systems except turaco are running the
same era of Debian as lapwing, but I'm not sure what turaco is.

#43Tom Lane
tgl@sss.pgh.pa.us
In reply to: Tom Lane (#41)
Re: Cannot find a working 64-bit integer type on Illumos

I wrote:

So apparently, "off_t" was the same as "loff_t" before 962da900a,
but it no longer is the same on 32-bit machines.

OK, I see what is happening. On platforms that need it, we define
_FILE_OFFSET_BITS as 64 in pg_config.h to ensure that off_t is
big enough. However, 962da900a did this:

--- a/src/include/postgres_ext.h
+++ b/src/include/postgres_ext.h
@@ -23,7 +23,7 @@
 #ifndef POSTGRES_EXT_H
 #define POSTGRES_EXT_H
-#include "pg_config_ext.h"
+#include <stdint.h>

Since c.h reads postgres_ext.h first, <stdint.h> is now pulled in
before pg_config.h, and that in turn pulls in <features.h>, which
locks down the decision that off_t will be 32 bits, as well as some
other decisions we don't want. We can NOT include any system headers
before pg_config.h; I'm surprised we're not seeing related failures on
the Solaris-en, where _LARGEFILE_SOURCE is similarly critical.

Another rather serious problem here is that we no longer provide
macro PG_INT64_TYPE, which seems rather likely to break applications
that were relying on it. That is part of our external API, we
can't just remove it on a whim.

I think the least painful solution would be to revert the parts
of 962da900a that got rid of pg_config_ext.h and PG_INT64_TYPE.
Since PG_INT64_TYPE is a macro not a typedef, it might be okay
to #define it as int64_t even before we've read that header,
so as not to give up the principle of relying on stdint.h for the
underlying definition.

Now that I see this, I'm fairly astonished that there aren't
more problems than we've noticed. I wonder whether it'd be
a good idea to put in a static assert somewhere about the
width of off_t, so that the next screwup of this sort will
be easier to diagnose.

regards, tom lane

#44Thomas Munro
thomas.munro@gmail.com
In reply to: Tom Lane (#43)
Re: Cannot find a working 64-bit integer type on Illumos

On Thu, Dec 5, 2024 at 10:20 AM Tom Lane <tgl@sss.pgh.pa.us> wrote:

I wrote:

So apparently, "off_t" was the same as "loff_t" before 962da900a,
but it no longer is the same on 32-bit machines.

OK, I see what is happening. On platforms that need it, we define
_FILE_OFFSET_BITS as 64 in pg_config.h to ensure that off_t is
big enough. However, 962da900a did this:

--- a/src/include/postgres_ext.h
+++ b/src/include/postgres_ext.h
@@ -23,7 +23,7 @@
#ifndef POSTGRES_EXT_H
#define POSTGRES_EXT_H
-#include "pg_config_ext.h"
+#include <stdint.h>

Since c.h reads postgres_ext.h first, <stdint.h> is now pulled in
before pg_config.h, and that in turn pulls in <features.h>, which
locks down the decision that off_t will be 32 bits, as well as some
other decisions we don't want. We can NOT include any system headers
before pg_config.h; I'm surprised we're not seeing related failures on
the Solaris-en, where _LARGEFILE_SOURCE is similarly critical.

Ah, right. Oops.

Another rather serious problem here is that we no longer provide
macro PG_INT64_TYPE, which seems rather likely to break applications
that were relying on it. That is part of our external API, we
can't just remove it on a whim.

I had concluded that PG_INT64_TYPE wasn't part of our external API but
pg_int64 was, based on the comment:

 /* Define a signed 64-bit integer type for use in client API declarations. */
-typedef PG_INT64_TYPE pg_int64;
+typedef int64_t pg_int64;

But yeah, I obviously hadn't considered that other interaction, and ...

I think the least painful solution would be to revert the parts
of 962da900a that got rid of pg_config_ext.h and PG_INT64_TYPE.
Since PG_INT64_TYPE is a macro not a typedef, it might be okay
to #define it as int64_t even before we've read that header,
so as not to give up the principle of relying on stdint.h for the
underlying definition.

... yeah that sounds like a plan. Looking into it.

Now that I see this, I'm fairly astonished that there aren't
more problems than we've noticed. I wonder whether it'd be
a good idea to put in a static assert somewhere about the
width of off_t, so that the next screwup of this sort will
be easier to diagnose.

Right, we could assert that it hasn't changed from what configure detected.

#45Tom Lane
tgl@sss.pgh.pa.us
In reply to: Thomas Munro (#44)
Re: Cannot find a working 64-bit integer type on Illumos

Thomas Munro <thomas.munro@gmail.com> writes:

On Thu, Dec 5, 2024 at 10:20 AM Tom Lane <tgl@sss.pgh.pa.us> wrote:

Another rather serious problem here is that we no longer provide
macro PG_INT64_TYPE, which seems rather likely to break applications
that were relying on it. That is part of our external API, we
can't just remove it on a whim.

I had concluded that PG_INT64_TYPE wasn't part of our external API but
pg_int64 was, based on the comment:

/* Define a signed 64-bit integer type for use in client API declarations. */
-typedef PG_INT64_TYPE pg_int64;
+typedef int64_t pg_int64;

Oh, hmm, maybe so. OTOH, that typedef breaks the idea of #define'ing
PG_INT64_TYPE as int64_t. We need this header to be readable without
any prior system headers, so I'm afraid we're all the way back to
making configure derive the name of a 64-bit type.

regards, tom lane

#46Tom Lane
tgl@sss.pgh.pa.us
In reply to: Tom Lane (#45)
Re: Cannot find a working 64-bit integer type on Illumos

I wrote:

... We need this header to be readable without
any prior system headers, so I'm afraid we're all the way back to
making configure derive the name of a 64-bit type.

Could another way be to read pg_config.h before postgres_ext.h?
I think the current order was intentional, but maybe the
disadvantages outweigh the advantages now.

regards, tom lane

#47Thomas Munro
thomas.munro@gmail.com
In reply to: Tom Lane (#46)
Re: Cannot find a working 64-bit integer type on Illumos

On Thu, Dec 5, 2024 at 10:55 AM Tom Lane <tgl@sss.pgh.pa.us> wrote:

I wrote:

... We need this header to be readable without
any prior system headers, so I'm afraid we're all the way back to
making configure derive the name of a 64-bit type.

Could another way be to read pg_config.h before postgres_ext.h?
I think the current order was intentional, but maybe the
disadvantages outweigh the advantages now.

Yeah I was just testing that idea :-) I can't see why it needs to be
first, but was looking for what the original reason was...

#48Thomas Munro
thomas.munro@gmail.com
In reply to: Thomas Munro (#47)
2 attachment(s)
Re: Cannot find a working 64-bit integer type on Illumos

On Thu, Dec 5, 2024 at 10:58 AM Thomas Munro <thomas.munro@gmail.com> wrote:

On Thu, Dec 5, 2024 at 10:55 AM Tom Lane <tgl@sss.pgh.pa.us> wrote:

Could another way be to read pg_config.h before postgres_ext.h?
I think the current order was intentional, but maybe the
disadvantages outweigh the advantages now.

Yeah I was just testing that idea :-) I can't see why it needs to be
first, but was looking for what the original reason was...

Seems good to me. Also there were another couple of contortions due
to the older ordering, which we could improve I think?

Attachments:

0001-Fix-header-inclusion-order-in-c.h.patchtext/x-patch; charset=US-ASCII; name=0001-Fix-header-inclusion-order-in-c.h.patchDownload
From 36e93b7c51dbc8a8d5a9b857a3616edb18c914a6 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Thu, 5 Dec 2024 11:06:28 +1300
Subject: [PATCH 1/2] Fix header inclusion order in c.h.

Commit 962da900a added #include <stdint.h> to postgres_ext.h, which
broke c.h's header ordering rule.

The system headers on some systems would then lock down off_t's size in
other private macros, before they'd had a chance to see our definition
of _FILE_OFFSET_BITS (and perhaps did the same for other things).  This
was picked up by perl's ABI compatibility checks on some 32 bit systems
in the build farm.

Move #include "postgres_ext.h" below that, because there isn't any
current reason for the original ordering.

Diagnosed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/2397643.1733347237%40sss.pgh.pa.us
---
 src/include/c.h | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/include/c.h b/src/include/c.h
index 734626e75a8..1271137f5df 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -46,11 +46,10 @@
 #ifndef C_H
 #define C_H
 
-#include "postgres_ext.h"
-
 #include "pg_config.h"
 #include "pg_config_manual.h"	/* must be after pg_config.h */
 #include "pg_config_os.h"		/* must be before any system header files */
+#include "postgres_ext.h"		/* includes a system header file */
 
 /* System header files that should be available everywhere in Postgres */
 #include <inttypes.h>
-- 
2.47.0

0002-Add-required-headers-to-postgres_ext.h.patchtext/x-patch; charset=US-ASCII; name=0002-Add-required-headers-to-postgres_ext.h.patchDownload
From caa89e1176977f26167e0b7ca8b6396a7e4dbba9 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Thu, 5 Dec 2024 11:31:52 +1300
Subject: [PATCH 2/2] Add required headers to postgres_ext.h.

A couple of macros defined by postgres_ext.h historically required their
users to include necessary headers themselves before use.  They couldn't
be included by postgres_ext.h itself due to inclusion ordering rules in
c.h.  Since we've now changed the order in c.h, we might as well be
nicer to users by including them.
---
 src/include/postgres_ext.h | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/src/include/postgres_ext.h b/src/include/postgres_ext.h
index 202eb049622..88480402d8a 100644
--- a/src/include/postgres_ext.h
+++ b/src/include/postgres_ext.h
@@ -23,7 +23,9 @@
 #ifndef POSTGRES_EXT_H
 #define POSTGRES_EXT_H
 
+#include <limits.h>
 #include <stdint.h>
+#include <stdlib.h>
 
 /*
  * Object ID is a fundamental type in Postgres.
@@ -37,10 +39,7 @@ typedef unsigned int Oid;
 #endif
 
 #define OID_MAX  UINT_MAX
-/* you will need to include <limits.h> to use the above #define */
-
 #define atooid(x) ((Oid) strtoul((x), NULL, 10))
-/* the above needs <stdlib.h> */
 
 
 /* Define a signed 64-bit integer type for use in client API declarations. */
-- 
2.47.0

#49Tom Lane
tgl@sss.pgh.pa.us
In reply to: Thomas Munro (#48)
Re: Cannot find a working 64-bit integer type on Illumos

Thomas Munro <thomas.munro@gmail.com> writes:

On Thu, Dec 5, 2024 at 10:58 AM Thomas Munro <thomas.munro@gmail.com> wrote:

On Thu, Dec 5, 2024 at 10:55 AM Tom Lane <tgl@sss.pgh.pa.us> wrote:

Could another way be to read pg_config.h before postgres_ext.h?
I think the current order was intentional, but maybe the
disadvantages outweigh the advantages now.

Seems good to me. Also there were another couple of contortions due
to the older ordering, which we could improve I think?

In c.h, I'd put in a very explicit comment in front of pg_config.h.
Also, I don't like making it look like postgres_ext.h is of the
same ilk as the config headers, since it isn't. So maybe like

/*
* These headers must be included before any system headers, because
* on some platforms they affect the behavior of the system headers
* (for example, by defining _FILE_OFFSET_BITS).
*/
#include "pg_config.h"
#include "pg_config_manual.h" /* must be after pg_config.h */
#include "pg_config_os.h" /* must be before any system header files */

/* Pull in fundamental symbols that we also expose to applications */
#include "postgres_ext.h"

/* System header files that should be available everywhere in Postgres */
#include <inttypes.h>
...

The comment for pg_config_os.h is redundant this way, maybe we could
rewrite it as something more useful?

Also, there's probably no reason anymore that postgres_ext.h couldn't
be placed after those fundamental system headers, and that might be
clearer. (I think perhaps the main reason for the existing ordering
was to demonstrate that postgres_ext.h could be included before any
system headers, and that's no longer a consideration.)

I don't especially care for your proposed changes to postgres_ext.h.
That substantially expands the footprint of what gets defined by
pulling that in, and some users might not care for that. (For
example, because they have ordering assumptions similar to what we're
dealing with here.) Now you already snuck the camel's nose under the
tent by including stdint.h there, and maybe these additional headers
wouldn't do any further damage. But I don't see a strong argument to
change long-standing external APIs any more than we absolutely must.

regards, tom lane

#50Thomas Munro
thomas.munro@gmail.com
In reply to: Tom Lane (#49)
1 attachment(s)
Re: Cannot find a working 64-bit integer type on Illumos

On Thu, Dec 5, 2024 at 12:16 PM Tom Lane <tgl@sss.pgh.pa.us> wrote:

In c.h, I'd put in a very explicit comment in front of pg_config.h.
Also, I don't like making it look like postgres_ext.h is of the
same ilk as the config headers, since it isn't. So maybe like

/*
* These headers must be included before any system headers, because
* on some platforms they affect the behavior of the system headers
* (for example, by defining _FILE_OFFSET_BITS).
*/
#include "pg_config.h"
#include "pg_config_manual.h" /* must be after pg_config.h */
#include "pg_config_os.h" /* must be before any system header files */

/* Pull in fundamental symbols that we also expose to applications */
#include "postgres_ext.h"

/* System header files that should be available everywhere in Postgres */
#include <inttypes.h>
...

The comment for pg_config_os.h is redundant this way, maybe we could
rewrite it as something more useful?

OK, how about:

+#include "pg_config_os.h" /* config from
include/port/PORTNAME.h */

That demystifies where it's really coming from ("portname" is used in
the meson script, and seems more informative than "template").

Also, there's probably no reason anymore that postgres_ext.h couldn't
be placed after those fundamental system headers, and that might be
clearer. (I think perhaps the main reason for the existing ordering
was to demonstrate that postgres_ext.h could be included before any
system headers, and that's no longer a consideration.)

Yeah, that makes sense.

I don't especially care for your proposed changes to postgres_ext.h.
That substantially expands the footprint of what gets defined by
pulling that in, and some users might not care for that. (For
example, because they have ordering assumptions similar to what we're
dealing with here.) Now you already snuck the camel's nose under the
tent by including stdint.h there, and maybe these additional headers
wouldn't do any further damage. But I don't see a strong argument to
change long-standing external APIs any more than we absolutely must.

If someone wants to define things like that before potentially
including system headers, they're not going about it the right way if
they're including our headers first (or anything at all not under
their direct control). But OK, I can work with the
not-broken-so-don't-fix-it and
pulling-in-more-stuff-that-maybe-they-don't-want arguments. :-)

Attachments:

v2-0001-Fix-header-inclusion-order-in-c.h.patchtext/x-patch; charset=US-ASCII; name=v2-0001-Fix-header-inclusion-order-in-c.h.patchDownload
From 05f334be9d01e90b0031f1e96ccd4449ae48e617 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Thu, 5 Dec 2024 11:06:28 +1300
Subject: [PATCH v2] Fix header inclusion order in c.h.

Commit 962da900a added #include <stdint.h> to postgres_ext.h, which
broke c.h's header ordering rule.

The system headers on some systems would then lock down off_t's size in
private macros, before they'd had a chance to see our definition of
_FILE_OFFSET_BITS (and presumably other things).  This was picked up by
perl's ABI compatibility checks on some 32 bit systems in the build
farm.

Move #include "postgres_ext.h" down below the system header section, and
make the comments clearer (thanks to Tom for the new wording).

Diagnosed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/2397643.1733347237%40sss.pgh.pa.us
---
 src/include/c.h | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/src/include/c.h b/src/include/c.h
index 734626e75a8..13bb39fdef3 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -46,11 +46,14 @@
 #ifndef C_H
 #define C_H
 
-#include "postgres_ext.h"
-
+/*
+ * These headers must be included before any system headers, because on some
+ * platforms they affect the behavior of the system headers (for example, by
+ * defining _FILE_OFFSET_BITS).
+ */
 #include "pg_config.h"
 #include "pg_config_manual.h"	/* must be after pg_config.h */
-#include "pg_config_os.h"		/* must be before any system header files */
+#include "pg_config_os.h"		/* config from include/port/PORTNAME.h */
 
 /* System header files that should be available everywhere in Postgres */
 #include <inttypes.h>
@@ -76,6 +79,9 @@
 #include <libintl.h>
 #endif
 
+ /* Pull in fundamental symbols that we also expose to applications */
+#include "postgres_ext.h"
+
 /* Define before including zlib.h to add const decorations to zlib API. */
 #ifdef HAVE_LIBZ
 #define ZLIB_CONST
-- 
2.47.0

#51Thomas Munro
thomas.munro@gmail.com
In reply to: Thomas Munro (#42)
Re: Cannot find a working 64-bit integer type on Illumos

On Thu, Dec 5, 2024 at 10:03 AM Thomas Munro <thomas.munro@gmail.com> wrote:

The affected systems are mostly running ancient OSes, and lapwing is
32 bit x86, so it's not only armv7. Current 32 bit x86 systems are
working fine.

I was trying to figure out how I missed this, and I think it might be
that the meson build scripts didn't port AC_SYS_LARGEFILES. So if you
build on a 32 bit Linux system with meson (like one of CI's tasks, and
also build farm animal adder) then I think you finish up with 32 bit
off_t and no SIZEOF_OFF_T, because we don't do AC_SYS_LARGEFILES'
dance to figure out if this system needs -D_FILE_OFFSET_BITS=64 (or
other similar macros for AIX, Solaris etc). I will look into that.

#52Thomas Munro
thomas.munro@gmail.com
In reply to: Thomas Munro (#51)
Re: Cannot find a working 64-bit integer type on Illumos

On Thu, Dec 5, 2024 at 1:59 PM Thomas Munro <thomas.munro@gmail.com> wrote:

I was trying to figure out how I missed this, and I think it might be
that the meson build scripts didn't port AC_SYS_LARGEFILES. So if you
build on a 32 bit Linux system with meson (like one of CI's tasks, and
also build farm animal adder) then I think you finish up with 32 bit
off_t and no SIZEOF_OFF_T, because we don't do AC_SYS_LARGEFILES'
dance to figure out if this system needs -D_FILE_OFFSET_BITS=64 (or
other similar macros for AIX, Solaris etc). I will look into that.

Ahh, correction, it does define it (or else perl would have
complained), but it seems that meson magically puts it into the
compiler command line without being asked. So it is defined without
pg_config.h being involved, and thus earlier. Huh.

#53Tom Lane
tgl@sss.pgh.pa.us
In reply to: Thomas Munro (#50)
Re: Cannot find a working 64-bit integer type on Illumos

Thomas Munro <thomas.munro@gmail.com> writes:

If someone wants to define things like that before potentially
including system headers, they're not going about it the right way if
they're including our headers first (or anything at all not under
their direct control). But OK, I can work with the
not-broken-so-don't-fix-it and
pulling-in-more-stuff-that-maybe-they-don't-want arguments. :-)

v2 LGTM.

regards, tom lane

#54Tom Lane
tgl@sss.pgh.pa.us
In reply to: Thomas Munro (#52)
Re: Cannot find a working 64-bit integer type on Illumos

Thomas Munro <thomas.munro@gmail.com> writes:

On Thu, Dec 5, 2024 at 1:59 PM Thomas Munro <thomas.munro@gmail.com> wrote:

I was trying to figure out how I missed this, and I think it might be
that the meson build scripts didn't port AC_SYS_LARGEFILES. So if you
build on a 32 bit Linux system with meson (like one of CI's tasks, and
also build farm animal adder) then I think you finish up with 32 bit
off_t and no SIZEOF_OFF_T, because we don't do AC_SYS_LARGEFILES'
dance to figure out if this system needs -D_FILE_OFFSET_BITS=64 (or
other similar macros for AIX, Solaris etc). I will look into that.

Ahh, correction, it does define it (or else perl would have
complained), but it seems that meson magically puts it into the
compiler command line without being asked. So it is defined without
pg_config.h being involved, and thus earlier. Huh.

That does not seem great. Compile an extension without the same
CPPFLAGS, you silently get an ABI-incompatible module. We really
ought to be putting these ABI-critical flags into pg_config.h.
It's especially bad that this works differently between autoconf
and meson builds.

regards, tom lane

#55Thomas Munro
thomas.munro@gmail.com
In reply to: Tom Lane (#54)
Re: Cannot find a working 64-bit integer type on Illumos

On Thu, Dec 5, 2024 at 4:29 PM Tom Lane <tgl@sss.pgh.pa.us> wrote:

Thomas Munro <thomas.munro@gmail.com> writes:

Ahh, correction, it does define it (or else perl would have
complained), but it seems that meson magically puts it into the
compiler command line without being asked. So it is defined without
pg_config.h being involved, and thus earlier. Huh.

That does not seem great. Compile an extension without the same
CPPFLAGS, you silently get an ABI-incompatible module. We really
ought to be putting these ABI-critical flags into pg_config.h.
It's especially bad that this works differently between autoconf
and meson builds.

It makes the whole MinGW circus worse that I'd realised:

/messages/by-id/CA+hUKG+6ZPD_X5ADMwX2uUtXqe_wv8+KQ5xFeAR2zbcodjNZvw@mail.gmail.com

#56Thomas Munro
thomas.munro@gmail.com
In reply to: Tom Lane (#49)
1 attachment(s)
Re: Cannot find a working 64-bit integer type on Illumos

On Thu, Dec 5, 2024 at 12:16 PM Tom Lane <tgl@sss.pgh.pa.us> wrote:

Now you already snuck the camel's nose under the
tent by including stdint.h there, and maybe these additional headers
wouldn't do any further damage.

Even though we fixed the immediate issue (thanks), this comment stayed
with me. I did that because I didn't want to change any interfaces at
the same time as the <stdint.h> retrofit, but I agree that it feels a
bit odd hidden in there, and doesn't appear to conform to
postgres_ext.h's self-description. Stepping back, and I realise it's
difficult to answer with certainty, I wonder why anyone would ever
want to use postgres_ext.h directly for the definition of pg_int64
*without* being a user of libpq-fe.h. I can't find any references to
pg_int64 (excluding forks of our code) on github; there are a few
things like proxies and suchlike that include postgres_ext.h for other
things, mostly bogusly (they also include libpq-fe.h, or they say they
want NAMEDATALEN, which isn't there anymore).

We have just three lo_*64() functions using that type and then
pg_usec_time_t. Seems like a very narrow usage that hasn't spread,
likely only used to receive arguments, and really quite specific to
libpq-fe.h and not one of the "fundamental Postgres declarations".
Maybe we should consider moving #include <stdint.h> into libpq-fe.h?

And if we included <stdint.h> overtly, rather than covertly in
postgres_ext.h, why would we still want a third name for int64_t? We
could change the three lo_*64() declarations to use the standard type
directly, but keep the historical typedef marked deprecated.

But I don't see a strong argument to
change long-standing external APIs any more than we absolutely must.

So perhaps you'll hate that idea then. I wonder if you'll hate it
more than keeping the #include in postgres_ext.h, hence putting the
idea forward!

Attachments:

0001-Deprecate-pg_int64.patchtext/x-patch; charset=US-ASCII; name=0001-Deprecate-pg_int64.patchDownload
From 1fddfe14a1f145b23fa5c31aa1cf6afc38d074d4 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Sat, 7 Dec 2024 15:55:44 +1300
Subject: [PATCH] Deprecate pg_int64.

Previously we used pg_int64 in the function prototypes of libpq-fe.h.
It was a typedef for the type that we selected for int64 in the backend.
That type is now int64_t, since commit 962da900.

Given that it didn't match the name we use in the backend anyway, let's
just use int64_t directly in public interfaces.  It is likely to be the
name that modern client applications would use for their own 64-bit
processing anyway.

Keep a typedef marked deprecated for backward compatibility, but move it
to libpq-fe.h, where the only uses of it were.
---
 doc/src/sgml/libpq.sgml         |  2 +-
 doc/src/sgml/lobj.sgml          |  6 +++---
 src/include/postgres_ext.h      |  5 -----
 src/interfaces/libpq/fe-lobj.c  | 30 +++++++++++++++---------------
 src/interfaces/libpq/libpq-fe.h | 12 ++++++++----
 src/test/examples/testlo64.c    |  7 ++++---
 6 files changed, 31 insertions(+), 31 deletions(-)

diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index 01f259fd0dc..fff9dd898d0 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -522,7 +522,7 @@ switch(PQstatus(conn))
        sequence described in the documentation of
        <xref linkend="libpq-PQconnectStartParams"/>.
 <synopsis>
-typedef pg_int64 pg_usec_time_t;
+typedef int64_t pg_usec_time_t;
 
 int PQsocketPoll(int sock, int forRead, int forWrite,
                  pg_usec_time_t end_time);
diff --git a/doc/src/sgml/lobj.sgml b/doc/src/sgml/lobj.sgml
index 2b725c3c182..1783f530901 100644
--- a/doc/src/sgml/lobj.sgml
+++ b/doc/src/sgml/lobj.sgml
@@ -398,7 +398,7 @@ int lo_lseek(PGconn *conn, int fd, int offset, int whence);
      When dealing with large objects that might exceed 2GB in size,
      instead use
 <synopsis>
-pg_int64 lo_lseek64(PGconn *conn, int fd, pg_int64 offset, int whence);
+int64_t lo_lseek64(PGconn *conn, int fd, int64_t offset, int whence);
 </synopsis>
      This function has the same behavior
      as <function>lo_lseek</function>, but it can accept an
@@ -434,7 +434,7 @@ int lo_tell(PGconn *conn, int fd);
      When dealing with large objects that might exceed 2GB in size,
      instead use
 <synopsis>
-pg_int64 lo_tell64(PGconn *conn, int fd);
+int64_t lo_tell64(PGconn *conn, int fd);
 </synopsis>
      This function has the same behavior
      as <function>lo_tell</function>, but it can deliver a result larger
@@ -485,7 +485,7 @@ int lo_truncate(PGconn *conn, int fd, size_t len);
      When dealing with large objects that might exceed 2GB in size,
      instead use
 <synopsis>
-int lo_truncate64(PGconn *conn, int fd, pg_int64 len);
+int lo_truncate64(PGconn *conn, int fd, int64_t len);
 </synopsis>
      This function has the same
      behavior as <function>lo_truncate</function>, but it can accept a
diff --git a/src/include/postgres_ext.h b/src/include/postgres_ext.h
index 202eb049622..473f9ba0ebc 100644
--- a/src/include/postgres_ext.h
+++ b/src/include/postgres_ext.h
@@ -23,8 +23,6 @@
 #ifndef POSTGRES_EXT_H
 #define POSTGRES_EXT_H
 
-#include <stdint.h>
-
 /*
  * Object ID is a fundamental type in Postgres.
  */
@@ -43,9 +41,6 @@ typedef unsigned int Oid;
 /* the above needs <stdlib.h> */
 
 
-/* Define a signed 64-bit integer type for use in client API declarations. */
-typedef int64_t pg_int64;
-
 /*
  * Identifiers of error message fields.  Kept here to keep common
  * between frontend and backend, and also to export them to libpq
diff --git a/src/interfaces/libpq/fe-lobj.c b/src/interfaces/libpq/fe-lobj.c
index c17585e38b7..95a1e54290a 100644
--- a/src/interfaces/libpq/fe-lobj.c
+++ b/src/interfaces/libpq/fe-lobj.c
@@ -43,8 +43,8 @@
 
 static int	lo_initialize(PGconn *conn);
 static Oid	lo_import_internal(PGconn *conn, const char *filename, Oid oid);
-static pg_int64 lo_hton64(pg_int64 host64);
-static pg_int64 lo_ntoh64(pg_int64 net64);
+static int64_t lo_hton64(int64_t host64);
+static int64_t lo_ntoh64(int64_t net64);
 
 /*
  * lo_open
@@ -192,7 +192,7 @@ lo_truncate(PGconn *conn, int fd, size_t len)
  * returns -1 upon failure
  */
 int
-lo_truncate64(PGconn *conn, int fd, pg_int64 len)
+lo_truncate64(PGconn *conn, int fd, int64_t len)
 {
 	PQArgBlock	argv[2];
 	PGresult   *res;
@@ -381,12 +381,12 @@ lo_lseek(PGconn *conn, int fd, int offset, int whence)
  * lo_lseek64
  *	  change the current read or write location on a large object
  */
-pg_int64
-lo_lseek64(PGconn *conn, int fd, pg_int64 offset, int whence)
+int64_t
+lo_lseek64(PGconn *conn, int fd, int64_t offset, int whence)
 {
 	PQArgBlock	argv[3];
 	PGresult   *res;
-	pg_int64	retval;
+	int64		retval;
 	int			result_len;
 
 	if (lo_initialize(conn) < 0)
@@ -544,10 +544,10 @@ lo_tell(PGconn *conn, int fd)
  * lo_tell64
  *	  returns the current seek location of the large object
  */
-pg_int64
+int64_t
 lo_tell64(PGconn *conn, int fd)
 {
-	pg_int64	retval;
+	int64		retval;
 	PQArgBlock	argv[1];
 	PGresult   *res;
 	int			result_len;
@@ -1019,12 +1019,12 @@ lo_initialize(PGconn *conn)
  * lo_hton64
  *	  converts a 64-bit integer from host byte order to network byte order
  */
-static pg_int64
-lo_hton64(pg_int64 host64)
+static int64_t
+lo_hton64(int64_t host64)
 {
 	union
 	{
-		pg_int64	i64;
+		int64		i64;
 		uint32		i32[2];
 	}			swap;
 	uint32		t;
@@ -1044,15 +1044,15 @@ lo_hton64(pg_int64 host64)
  * lo_ntoh64
  *	  converts a 64-bit integer from network byte order to host byte order
  */
-static pg_int64
-lo_ntoh64(pg_int64 net64)
+static int64_t
+lo_ntoh64(int64_t net64)
 {
 	union
 	{
-		pg_int64	i64;
+		int64		i64;
 		uint32		i32[2];
 	}			swap;
-	pg_int64	result;
+	int64		result;
 
 	swap.i64 = net64;
 
diff --git a/src/interfaces/libpq/libpq-fe.h b/src/interfaces/libpq/libpq-fe.h
index 15012c770c4..b598f3b80c1 100644
--- a/src/interfaces/libpq/libpq-fe.h
+++ b/src/interfaces/libpq/libpq-fe.h
@@ -20,6 +20,7 @@ extern "C"
 {
 #endif
 
+#include <stdint.h>
 #include <stdio.h>
 
 /*
@@ -222,8 +223,11 @@ typedef struct pgNotify
 	struct pgNotify *next;		/* list link */
 } PGnotify;
 
+/* deprecated name for int64_t */
+typedef int64_t pg_int64;
+
 /* pg_usec_time_t is like time_t, but with microsecond resolution */
-typedef pg_int64 pg_usec_time_t;
+typedef int64_t pg_usec_time_t;
 
 /* Function types for notice-handling callbacks */
 typedef void (*PQnoticeReceiver) (void *arg, const PGresult *res);
@@ -679,13 +683,13 @@ extern int	lo_close(PGconn *conn, int fd);
 extern int	lo_read(PGconn *conn, int fd, char *buf, size_t len);
 extern int	lo_write(PGconn *conn, int fd, const char *buf, size_t len);
 extern int	lo_lseek(PGconn *conn, int fd, int offset, int whence);
-extern pg_int64 lo_lseek64(PGconn *conn, int fd, pg_int64 offset, int whence);
+extern int64_t lo_lseek64(PGconn *conn, int fd, int64_t offset, int whence);
 extern Oid	lo_creat(PGconn *conn, int mode);
 extern Oid	lo_create(PGconn *conn, Oid lobjId);
 extern int	lo_tell(PGconn *conn, int fd);
-extern pg_int64 lo_tell64(PGconn *conn, int fd);
+extern int64_t lo_tell64(PGconn *conn, int fd);
 extern int	lo_truncate(PGconn *conn, int fd, size_t len);
-extern int	lo_truncate64(PGconn *conn, int fd, pg_int64 len);
+extern int	lo_truncate64(PGconn *conn, int fd, int64_t len);
 extern int	lo_unlink(PGconn *conn, Oid lobjId);
 extern Oid	lo_import(PGconn *conn, const char *filename);
 extern Oid	lo_import_with_oid(PGconn *conn, const char *filename, Oid lobjId);
diff --git a/src/test/examples/testlo64.c b/src/test/examples/testlo64.c
index f0636a47961..6f8d96cb304 100644
--- a/src/test/examples/testlo64.c
+++ b/src/test/examples/testlo64.c
@@ -12,6 +12,7 @@
  *
  *-------------------------------------------------------------------------
  */
+#include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 
@@ -75,7 +76,7 @@ importFile(PGconn *conn, char *filename)
 }
 
 static void
-pickout(PGconn *conn, Oid lobjId, pg_int64 start, int len)
+pickout(PGconn *conn, Oid lobjId, int64_t start, int len)
 {
 	int			lobj_fd;
 	char	   *buf;
@@ -110,7 +111,7 @@ pickout(PGconn *conn, Oid lobjId, pg_int64 start, int len)
 }
 
 static void
-overwrite(PGconn *conn, Oid lobjId, pg_int64 start, int len)
+overwrite(PGconn *conn, Oid lobjId, int64_t start, int len)
 {
 	int			lobj_fd;
 	char	   *buf;
@@ -148,7 +149,7 @@ overwrite(PGconn *conn, Oid lobjId, pg_int64 start, int len)
 }
 
 static void
-my_truncate(PGconn *conn, Oid lobjId, pg_int64 len)
+my_truncate(PGconn *conn, Oid lobjId, int64_t len)
 {
 	int			lobj_fd;
 
-- 
2.47.0

#57Thomas Munro
thomas.munro@gmail.com
In reply to: Thomas Munro (#56)
Re: Cannot find a working 64-bit integer type on Illumos

On Tue, Dec 10, 2024 at 3:02 PM Thomas Munro <thomas.munro@gmail.com> wrote:

On Thu, Dec 5, 2024 at 12:16 PM Tom Lane <tgl@sss.pgh.pa.us> wrote:

Now you already snuck the camel's nose under the
tent by including stdint.h there, and maybe these additional headers
wouldn't do any further damage.

Even though we fixed the immediate issue (thanks), this comment stayed
with me. I did that because I didn't want to change any interfaces at
the same time as the <stdint.h> retrofit, but I agree that it feels a
bit odd hidden in there, and doesn't appear to conform to
postgres_ext.h's self-description. Stepping back, and I realise it's
difficult to answer with certainty, I wonder why anyone would ever
want to use postgres_ext.h directly for the definition of pg_int64
*without* being a user of libpq-fe.h. I can't find any references to
pg_int64 (excluding forks of our code) on github; there are a few
things like proxies and suchlike that include postgres_ext.h for other
things, mostly bogusly (they also include libpq-fe.h, or they say they
want NAMEDATALEN, which isn't there anymore).

We have just three lo_*64() functions using that type and then
pg_usec_time_t. Seems like a very narrow usage that hasn't spread,
likely only used to receive arguments, and really quite specific to
libpq-fe.h and not one of the "fundamental Postgres declarations".
Maybe we should consider moving #include <stdint.h> into libpq-fe.h?

And if we included <stdint.h> overtly, rather than covertly in
postgres_ext.h, why would we still want a third name for int64_t? We
could change the three lo_*64() declarations to use the standard type
directly, but keep the historical typedef marked deprecated.

But I don't see a strong argument to
change long-standing external APIs any more than we absolutely must.

So perhaps you'll hate that idea then. I wonder if you'll hate it
more than keeping the #include in postgres_ext.h, hence putting the
idea forward!

Does anyone else have thoughts about this arguable leftover quirk from
the <stdint.h> refactoring work? In brief, shouldn't libpq-fe.h
include <stdint.h> directly, and use int64_t explicitly, instead of
doing it "secretly" in another header that came about because of
historical namespace pollution concerns, now gone? We require you to
have a 64 bit integer type, we require C99, C99 requires int64_t to be
defined if you have a 64 bit type, and there doesn't seem to be any
reason to want pg_int64 other than to use these large object functions
in libpq-fe.h. The current arrangement feels a bit obfuscated,
leading to the patch in the previous email. Adding Ishii-san who
introduced the three uses of pg_int64 to libpq-fe.h in 461ef73f.

#58Peter Eisentraut
peter@eisentraut.org
In reply to: Thomas Munro (#56)
Re: Cannot find a working 64-bit integer type on Illumos

On 10.12.24 03:02, Thomas Munro wrote:

On Thu, Dec 5, 2024 at 12:16 PM Tom Lane <tgl@sss.pgh.pa.us> wrote:

Now you already snuck the camel's nose under the
tent by including stdint.h there, and maybe these additional headers
wouldn't do any further damage.

Even though we fixed the immediate issue (thanks), this comment stayed
with me. I did that because I didn't want to change any interfaces at
the same time as the <stdint.h> retrofit, but I agree that it feels a
bit odd hidden in there, and doesn't appear to conform to
postgres_ext.h's self-description. Stepping back, and I realise it's
difficult to answer with certainty, I wonder why anyone would ever
want to use postgres_ext.h directly for the definition of pg_int64
*without* being a user of libpq-fe.h. I can't find any references to
pg_int64 (excluding forks of our code) on github; there are a few
things like proxies and suchlike that include postgres_ext.h for other
things, mostly bogusly (they also include libpq-fe.h, or they say they
want NAMEDATALEN, which isn't there anymore).

We have just three lo_*64() functions using that type and then
pg_usec_time_t. Seems like a very narrow usage that hasn't spread,
likely only used to receive arguments, and really quite specific to
libpq-fe.h and not one of the "fundamental Postgres declarations".
Maybe we should consider moving #include <stdint.h> into libpq-fe.h?

And if we included <stdint.h> overtly, rather than covertly in
postgres_ext.h, why would we still want a third name for int64_t? We
could change the three lo_*64() declarations to use the standard type
directly, but keep the historical typedef marked deprecated.

I agree with your patch 0001-Deprecate-pg_int64.patch. I don't see a
reason to keep the current arrangement around pg_int64.

#59Thomas Munro
thomas.munro@gmail.com
In reply to: Peter Eisentraut (#58)
Re: Cannot find a working 64-bit integer type on Illumos

On Wed, Mar 5, 2025 at 6:00 AM Peter Eisentraut <peter@eisentraut.org> wrote:

I agree with your patch 0001-Deprecate-pg_int64.patch. I don't see a
reason to keep the current arrangement around pg_int64.

Thanks for looking! Pushed.

#60Nathan Bossart
nathandbossart@gmail.com
In reply to: Thomas Munro (#59)
Re: Cannot find a working 64-bit integer type on Illumos

On Tue, Mar 25, 2025 at 09:41:21PM +1300, Thomas Munro wrote:

On Wed, Mar 5, 2025 at 6:00 AM Peter Eisentraut <peter@eisentraut.org> wrote:

I agree with your patch 0001-Deprecate-pg_int64.patch. I don't see a
reason to keep the current arrangement around pg_int64.

Thanks for looking! Pushed.

anaconda seems to be upset about this one [0]https://buildfarm.postgresql.org/cgi-bin/show_log.pl?nm=anaconda&amp;dt=2025-03-25%2021%3A22%3A33. I've spent all of 30
seconds looking at it so far, but it appears to be using an old version of
the header file.

In file included from pg_regress.c:34:
/usr/local/include/libpq-fe.h:623:8: error: unknown type name 'pg_int64'
623 | extern pg_int64 lo_lseek64(PGconn *conn, int fd, pg_int64 offset, int whence);
| ^
/usr/local/include/libpq-fe.h:623:50: error: unknown type name 'pg_int64'
623 | extern pg_int64 lo_lseek64(PGconn *conn, int fd, pg_int64 offset, int whence);
| ^
/usr/local/include/libpq-fe.h:627:8: error: unknown type name 'pg_int64'
627 | extern pg_int64 lo_tell64(PGconn *conn, int fd);
| ^
/usr/local/include/libpq-fe.h:629:48: error: unknown type name 'pg_int64'
629 | extern int lo_truncate64(PGconn *conn, int fd, pg_int64 len);
| ^
4 errors generated.

[0]: https://buildfarm.postgresql.org/cgi-bin/show_log.pl?nm=anaconda&amp;dt=2025-03-25%2021%3A22%3A33

--
nathan

#61Thomas Munro
thomas.munro@gmail.com
In reply to: Nathan Bossart (#60)
Re: Cannot find a working 64-bit integer type on Illumos

On Wed, Mar 26, 2025 at 10:34 AM Nathan Bossart
<nathandbossart@gmail.com> wrote:

anaconda seems to be upset about this one [0]. I've spent all of 30
seconds looking at it so far, but it appears to be using an old version of
the header file.

In file included from pg_regress.c:34:
/usr/local/include/libpq-fe.h:623:8: error: unknown type name 'pg_int64'

Looks like it's mixing up /usr/local/include and our source tree...

#62Tom Lane
tgl@sss.pgh.pa.us
In reply to: Thomas Munro (#61)
Re: Cannot find a working 64-bit integer type on Illumos

Thomas Munro <thomas.munro@gmail.com> writes:

On Wed, Mar 26, 2025 at 10:34 AM Nathan Bossart
<nathandbossart@gmail.com> wrote:

In file included from pg_regress.c:34:
/usr/local/include/libpq-fe.h:623:8: error: unknown type name 'pg_int64'

Looks like it's mixing up /usr/local/include and our source tree...

Yeah. That's because the compile command for pg_regress.c has
-I../../../src/include/libpq too late, after -I switches added
for other things:

ccache cc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Werror=unguarded-availability-new -Wendif-labels -Wmissing-format-attribute -Wcast-function-type -Wformat-security -Wmissing-variable-declarations -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-unused-command-line-argument -Wno-compound-token-split-by-macro -Wno-format-truncation -Wno-cast-function-type-strict -g -O2 -fPIC -DPIC -fvisibility=hidden -I../../../src/include -I/usr/local/include -I/usr/local/include/libxml2 -I/usr/local/include -I../../../src/port -I../../../src/interfaces/libpq '-DHOST_TUPLE="x86_64-unknown-freebsd15.0"' '-DSHELLPROG="/bin/sh"' -c -o pg_regress.o pg_regress.c

How did that work before? Perhaps somebody just now added a libpq
dependency to pg_regress.c?

regards, tom lane

#63Daniel Gustafsson
daniel@yesql.se
In reply to: Tom Lane (#62)
Re: Cannot find a working 64-bit integer type on Illumos

On 26 Mar 2025, at 00:01, Tom Lane <tgl@sss.pgh.pa.us> wrote:

How did that work before? Perhaps somebody just now added a libpq
dependency to pg_regress.c?

I believe the libpq dependency came in 66d6086cbcbfc8 which wasn't all that
recent.

--
Daniel Gustafsson

#64Tom Lane
tgl@sss.pgh.pa.us
In reply to: Daniel Gustafsson (#63)
Re: Cannot find a working 64-bit integer type on Illumos

Daniel Gustafsson <daniel@yesql.se> writes:

On 26 Mar 2025, at 00:01, Tom Lane <tgl@sss.pgh.pa.us> wrote:
How did that work before? Perhaps somebody just now added a libpq
dependency to pg_regress.c?

I believe the libpq dependency came in 66d6086cbcbfc8 which wasn't all that
recent.

It looks like this has been broken for a very long time, but it must
never have mattered before because libpq-fe.h is so stable, and
pg_regress doesn't use any new-ish APIs from it. So pulling in
whatever version the platform had still worked.

I think this should work to fix it:

-pg_regress.o: override CPPFLAGS += -I$(top_builddir)/src/port -I$(libpq_srcdir) $(EXTRADEFS)
+pg_regress.o: override CPPFLAGS := -I$(top_builddir)/src/port -I$(libpq_srcdir) $(EXTRADEFS) $(CPPFLAGS)

but I haven't tested yet.

regards, tom lane

#65Thomas Munro
thomas.munro@gmail.com
In reply to: Tom Lane (#64)
Re: Cannot find a working 64-bit integer type on Illumos

On Wed, Mar 26, 2025 at 12:36 PM Tom Lane <tgl@sss.pgh.pa.us> wrote:

Daniel Gustafsson <daniel@yesql.se> writes:

On 26 Mar 2025, at 00:01, Tom Lane <tgl@sss.pgh.pa.us> wrote:
How did that work before? Perhaps somebody just now added a libpq
dependency to pg_regress.c?

I believe the libpq dependency came in 66d6086cbcbfc8 which wasn't all that
recent.

It looks like this has been broken for a very long time, but it must
never have mattered before because libpq-fe.h is so stable, and
pg_regress doesn't use any new-ish APIs from it. So pulling in
whatever version the platform had still worked.

I think this should work to fix it:

-pg_regress.o: override CPPFLAGS += -I$(top_builddir)/src/port -I$(libpq_srcdir) $(EXTRADEFS)
+pg_regress.o: override CPPFLAGS := -I$(top_builddir)/src/port -I$(libpq_srcdir) $(EXTRADEFS) $(CPPFLAGS)

but I haven't tested yet.

Our meson scripts also have this problem, which I couldn't figure out
how to fix completely in my first attempt:

/messages/by-id/CA+hUKGKispvxLyrBn3=3mp0BB1N+RBYR5eE2guCOksnwEoOcPQ@mail.gmail.com

#66Peter Eisentraut
peter@eisentraut.org
In reply to: Thomas Munro (#56)
Re: Cannot find a working 64-bit integer type on Illumos

On 10.12.24 03:02, Thomas Munro wrote:

And if we included <stdint.h> overtly, rather than covertly in
postgres_ext.h, why would we still want a third name for int64_t? We
could change the three lo_*64() declarations to use the standard type
directly, but keep the historical typedef marked deprecated.

But I don't see a strong argument to
change long-standing external APIs any more than we absolutely must.

So perhaps you'll hate that idea then. I wonder if you'll hate it
more than keeping the #include in postgres_ext.h, hence putting the
idea forward!

This change in commit 3c86223c998 is problematic.

commit 3c86223c998
Author: Thomas Munro <tmunro@postgresql.org>
Date: Tue Mar 25 08:17:53 2025

libpq: Deprecate pg_int64.

...

Keep a typedef marked deprecated for backward compatibility, but
move it
into libpq-fe.h where it was used.

Consider a third-party extension that does something like dblink or
postgres_fdw. It will compile against a server and also a libpq. The
server and the libpq might not be of the same major version. (On
Debian, only the latest libpq will be available.) If you have for
example server version 17 and libpq version 18, then you will get the
pg_int64 typedef both from postgres_ext.h (from the PG17 server
includes) and from libpq-fe.h (from PG18 libpq). That is not allowed in
C99, and even if it were, the underlying types of PG_INT64_TYPE (in
PG17) and int64_t (in PG18) might be different (long int vs. long long
int) and this would fail.

I think this could be fixed by moving the definition of pg_int64 back to
postgres_ext.h. Then extension builds would only get one definition,
because of the header guards. Depending on include order, they could
get a different underlying type, but that's a smaller problem, since the
type is supposed to be deprecated anyway.

#67Thomas Munro
thomas.munro@gmail.com
In reply to: Peter Eisentraut (#66)
Re: Cannot find a working 64-bit integer type on Illumos

On Thu, Sep 4, 2025 at 3:04 AM Peter Eisentraut <peter@eisentraut.org> wrote:

This change in commit 3c86223c998 is problematic.

commit 3c86223c998
Author: Thomas Munro <tmunro@postgresql.org>
Date: Tue Mar 25 08:17:53 2025

libpq: Deprecate pg_int64.

...

Keep a typedef marked deprecated for backward compatibility, but
move it
into libpq-fe.h where it was used.

Consider a third-party extension that does something like dblink or
postgres_fdw. It will compile against a server and also a libpq. The
server and the libpq might not be of the same major version. (On
Debian, only the latest libpq will be available.) If you have for
example server version 17 and libpq version 18, then you will get the
pg_int64 typedef both from postgres_ext.h (from the PG17 server
includes) and from libpq-fe.h (from PG18 libpq). That is not allowed in
C99, and even if it were, the underlying types of PG_INT64_TYPE (in
PG17) and int64_t (in PG18) might be different (long int vs. long long
int) and this would fail.

postgres_ext.h. Then extension builds would only get one definition,
because of the header guards. Depending on include order, they could
get a different underlying type, but that's a smaller problem, since the
type is supposed to be deprecated anyway.

Hmm. So we're talking about a Debian system compiling an extension
that has these headers in its search path:

/usr/include/postgresql/postgres_ext.h <-- v18[1]https://packages.debian.org/trixie/amd64/libpq-dev/filelist
/usr/include/postgresql/17/server/postgres_ext.h <-- v17[2]https://packages.debian.org/trixie/amd64/postgresql-server-dev-17/filelist (or other
older release)

I guess it's only a problem if the v17 header is found first, but such
an extension must build OK if the libpq headers are found first,
right? I'm not sure what to think about that yet, ie how to decide
which orders should work.

Is there an argument for recommending/requiring the newer one be used?
The counter argument must be that we could eventually remove macros
for stuff we remove in future that are still useful in the older
server that your extension is building against. (Here we removed
something, but it's not something that matches the file's own mission
statement, it's just ancient C evolution stuff and I still think that
commit was a reasonable choice, though of course this wrinkle needs a
solution.)

Other ideas to make cross-version postgres_ext.h work, at least as far
as this issue goes:

1. Wrap the new typedef in #ifndef PG_INT64_TYPE, with a comment to
explain that it's for older releases of postgres_ext.h that supplied
the typedef.
2. Just delete the new typedef completely, and if someone wants it
they can define it themselves. IIRC I couldn't actually find a single
example of another project using the typename in github or the Debian
code search. In other words, if people are using those 3 functions
they're using some other typename, that's just how we spelled it, so
technically it may be a (noop) cast when you call them.

[1]: https://packages.debian.org/trixie/amd64/libpq-dev/filelist
[2]: https://packages.debian.org/trixie/amd64/postgresql-server-dev-17/filelist

#68Peter Eisentraut
peter@eisentraut.org
In reply to: Peter Eisentraut (#66)
1 attachment(s)
Re: Cannot find a working 64-bit integer type on Illumos

On 03.09.25 17:04, Peter Eisentraut wrote:

Consider a third-party extension that does something like dblink or
postgres_fdw.  It will compile against a server and also a libpq.  The
server and the libpq might not be of the same major version.  (On
Debian, only the latest libpq will be available.)  If you have for
example server version 17 and libpq version 18, then you will get the
pg_int64 typedef both from postgres_ext.h (from the PG17 server
includes) and from libpq-fe.h (from PG18 libpq).  That is not allowed in
C99, and even if it were, the underlying types of PG_INT64_TYPE (in
PG17) and int64_t (in PG18) might be different (long int vs. long long
int) and this would fail.

I think this could be fixed by moving the definition of pg_int64 back to
postgres_ext.h.  Then extension builds would only get one definition,
because of the header guards.  Depending on include order, they could
get a different underlying type, but that's a smaller problem, since the
type is supposed to be deprecated anyway.

Here is a patch that has been reported to fix the problem.

Attachments:

v0-0001-Move-pg_int64-back-to-postgres_ext.h.patchtext/plain; charset=UTF-8; name=v0-0001-Move-pg_int64-back-to-postgres_ext.h.patchDownload
From c4e0c2e406adfa15c4f0916f18616ca44b2419ef Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Wed, 3 Sep 2025 17:45:18 +0200
Subject: [PATCH v0] Move pg_int64 back to postgres_ext.h

Fix for commit 3c86223c998.  Details TODO ...
---
 src/include/postgres_ext.h      | 3 +++
 src/interfaces/libpq/libpq-fe.h | 3 ---
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/include/postgres_ext.h b/src/include/postgres_ext.h
index bf45c50dcf3..c8eb26a3c2e 100644
--- a/src/include/postgres_ext.h
+++ b/src/include/postgres_ext.h
@@ -42,6 +42,9 @@ typedef unsigned int Oid;
 /* the above needs <stdlib.h> */
 
 
+/* deprecated name for int64_t */
+typedef int64_t pg_int64;
+
 /*
  * Identifiers of error message fields.  Kept here to keep common
  * between frontend and backend, and also to export them to libpq
diff --git a/src/interfaces/libpq/libpq-fe.h b/src/interfaces/libpq/libpq-fe.h
index af8004f952a..0852584edae 100644
--- a/src/interfaces/libpq/libpq-fe.h
+++ b/src/interfaces/libpq/libpq-fe.h
@@ -234,9 +234,6 @@ typedef struct pgNotify
 	struct pgNotify *next;		/* list link */
 } PGnotify;
 
-/* deprecated name for int64_t */
-typedef int64_t pg_int64;
-
 /* pg_usec_time_t is like time_t, but with microsecond resolution */
 typedef int64_t pg_usec_time_t;
 
-- 
2.51.0

#69Peter Eisentraut
peter@eisentraut.org
In reply to: Thomas Munro (#67)
Re: Cannot find a working 64-bit integer type on Illumos

On 04.09.25 02:39, Thomas Munro wrote:

Hmm. So we're talking about a Debian system compiling an extension
that has these headers in its search path:

/usr/include/postgresql/postgres_ext.h <-- v18[1]
/usr/include/postgresql/17/server/postgres_ext.h <-- v17[2] (or other
older release)

I guess it's only a problem if the v17 header is found first, but such
an extension must build OK if the libpq headers are found first,
right? I'm not sure what to think about that yet, ie how to decide
which orders should work.

The logs I have seen have the libpq include path first.

I don't think the order matters. The problem is that you have two
conflicting typedefs of the same name in two separate header files. So
if you include both of them, you'll get an error.

#70Peter Eisentraut
peter@eisentraut.org
In reply to: Peter Eisentraut (#68)
Re: Cannot find a working 64-bit integer type on Illumos

On 04.09.25 11:01, Peter Eisentraut wrote:

On 03.09.25 17:04, Peter Eisentraut wrote:

Consider a third-party extension that does something like dblink or
postgres_fdw.  It will compile against a server and also a libpq.  The
server and the libpq might not be of the same major version.  (On
Debian, only the latest libpq will be available.)  If you have for
example server version 17 and libpq version 18, then you will get the
pg_int64 typedef both from postgres_ext.h (from the PG17 server
includes) and from libpq-fe.h (from PG18 libpq).  That is not allowed
in C99, and even if it were, the underlying types of PG_INT64_TYPE (in
PG17) and int64_t (in PG18) might be different (long int vs. long long
int) and this would fail.

I think this could be fixed by moving the definition of pg_int64 back
to postgres_ext.h.  Then extension builds would only get one
definition, because of the header guards.  Depending on include order,
they could get a different underlying type, but that's a smaller
problem, since the type is supposed to be deprecated anyway.

Here is a patch that has been reported to fix the problem.

I propose to go ahead with this patch in a few days if there are no
other solutions coming.

#71Peter Eisentraut
peter@eisentraut.org
In reply to: Peter Eisentraut (#70)
Re: Cannot find a working 64-bit integer type on Illumos

On 12.09.25 15:51, Peter Eisentraut wrote:

On 04.09.25 11:01, Peter Eisentraut wrote:

On 03.09.25 17:04, Peter Eisentraut wrote:

Consider a third-party extension that does something like dblink or
postgres_fdw.  It will compile against a server and also a libpq.
The server and the libpq might not be of the same major version.  (On
Debian, only the latest libpq will be available.)  If you have for
example server version 17 and libpq version 18, then you will get the
pg_int64 typedef both from postgres_ext.h (from the PG17 server
includes) and from libpq-fe.h (from PG18 libpq).  That is not allowed
in C99, and even if it were, the underlying types of PG_INT64_TYPE
(in PG17) and int64_t (in PG18) might be different (long int vs. long
long int) and this would fail.

I think this could be fixed by moving the definition of pg_int64 back
to postgres_ext.h.  Then extension builds would only get one
definition, because of the header guards.  Depending on include
order, they could get a different underlying type, but that's a
smaller problem, since the type is supposed to be deprecated anyway.

Here is a patch that has been reported to fix the problem.

I propose to go ahead with this patch in a few days if there are no
other solutions coming.

done