aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/libpq
diff options
context:
space:
mode:
authorgalaxycrab <UgnineSirdis@ydb.tech>2023-11-23 11:26:33 +0300
committergalaxycrab <UgnineSirdis@ydb.tech>2023-11-23 12:01:57 +0300
commit44354d0fc55926c1d4510d1d2c9c9f6a1a5e9300 (patch)
treecb4d75cd1c6dbc3da0ed927337fd8d1b6ed9da84 /contrib/libs/libpq
parent0e69bf615395fdd48ecee032faaec81bc468b0b8 (diff)
downloadydb-44354d0fc55926c1d4510d1d2c9c9f6a1a5e9300.tar.gz
YQ Connector:test INNER JOIN
Diffstat (limited to 'contrib/libs/libpq')
-rw-r--r--contrib/libs/libpq/CMakeLists.darwin-arm64.txt112
-rw-r--r--contrib/libs/libpq/CMakeLists.darwin-x86_64.txt114
-rw-r--r--contrib/libs/libpq/CMakeLists.linux-aarch64.txt113
-rw-r--r--contrib/libs/libpq/CMakeLists.linux-x86_64.txt115
-rw-r--r--contrib/libs/libpq/CMakeLists.txt17
-rw-r--r--contrib/libs/libpq/COPYRIGHT23
-rw-r--r--contrib/libs/libpq/README27
-rw-r--r--contrib/libs/libpq/README.git14
-rw-r--r--contrib/libs/libpq/src/backend/catalog/pg_tablespace_d.h38
-rw-r--r--contrib/libs/libpq/src/backend/utils/README.Gen_dummy_probes27
-rw-r--r--contrib/libs/libpq/src/backend/utils/errcodes.h354
-rw-r--r--contrib/libs/libpq/src/common/archive.c60
-rw-r--r--contrib/libs/libpq/src/common/base64.c242
-rw-r--r--contrib/libs/libpq/src/common/checksum_helper.c232
-rw-r--r--contrib/libs/libpq/src/common/compression.c476
-rw-r--r--contrib/libs/libpq/src/common/config_info.c201
-rw-r--r--contrib/libs/libpq/src/common/controldata_utils.c269
-rw-r--r--contrib/libs/libpq/src/common/cryptohash_openssl.c353
-rw-r--r--contrib/libs/libpq/src/common/d2s.c1076
-rw-r--r--contrib/libs/libpq/src/common/d2s_full_table.h358
-rw-r--r--contrib/libs/libpq/src/common/d2s_intrinsics.h202
-rw-r--r--contrib/libs/libpq/src/common/digit_table.h21
-rw-r--r--contrib/libs/libpq/src/common/encnames.c598
-rw-r--r--contrib/libs/libpq/src/common/exec.c719
-rw-r--r--contrib/libs/libpq/src/common/f2s.c803
-rw-r--r--contrib/libs/libpq/src/common/fe_memutils.c175
-rw-r--r--contrib/libs/libpq/src/common/file_perm.c91
-rw-r--r--contrib/libs/libpq/src/common/file_utils.c582
-rw-r--r--contrib/libs/libpq/src/common/hashfn.c692
-rw-r--r--contrib/libs/libpq/src/common/hmac_openssl.c348
-rw-r--r--contrib/libs/libpq/src/common/ip.c262
-rw-r--r--contrib/libs/libpq/src/common/jsonapi.c1206
-rw-r--r--contrib/libs/libpq/src/common/keywords.c48
-rw-r--r--contrib/libs/libpq/src/common/kwlist_d.h1119
-rw-r--r--contrib/libs/libpq/src/common/kwlookup.c85
-rw-r--r--contrib/libs/libpq/src/common/link-canary.c36
-rw-r--r--contrib/libs/libpq/src/common/logging.c334
-rw-r--r--contrib/libs/libpq/src/common/md5_common.c172
-rw-r--r--contrib/libs/libpq/src/common/percentrepl.c137
-rw-r--r--contrib/libs/libpq/src/common/pg_get_line.c180
-rw-r--r--contrib/libs/libpq/src/common/pg_lzcompress.c876
-rw-r--r--contrib/libs/libpq/src/common/pg_prng.c282
-rw-r--r--contrib/libs/libpq/src/common/pgfnames.c94
-rw-r--r--contrib/libs/libpq/src/common/protocol_openssl.c117
-rw-r--r--contrib/libs/libpq/src/common/psprintf.c151
-rw-r--r--contrib/libs/libpq/src/common/relpath.c210
-rw-r--r--contrib/libs/libpq/src/common/restricted_token.c174
-rw-r--r--contrib/libs/libpq/src/common/rmtree.c130
-rw-r--r--contrib/libs/libpq/src/common/ryu_common.h133
-rw-r--r--contrib/libs/libpq/src/common/saslprep.c1245
-rw-r--r--contrib/libs/libpq/src/common/scram-common.c319
-rw-r--r--contrib/libs/libpq/src/common/sprompt.c181
-rw-r--r--contrib/libs/libpq/src/common/string.c164
-rw-r--r--contrib/libs/libpq/src/common/stringinfo.c343
-rw-r--r--contrib/libs/libpq/src/common/unicode_norm.c634
-rw-r--r--contrib/libs/libpq/src/common/username.c87
-rw-r--r--contrib/libs/libpq/src/common/wait_error.c148
-rw-r--r--contrib/libs/libpq/src/common/wchar.c2193
-rw-r--r--contrib/libs/libpq/src/include/access/rmgr.h62
-rw-r--r--contrib/libs/libpq/src/include/access/rmgrlist.h49
-rw-r--r--contrib/libs/libpq/src/include/access/transam.h375
-rw-r--r--contrib/libs/libpq/src/include/access/xlog_internal.h404
-rw-r--r--contrib/libs/libpq/src/include/access/xlogdefs.h82
-rw-r--r--contrib/libs/libpq/src/include/access/xlogreader.h444
-rw-r--r--contrib/libs/libpq/src/include/access/xlogrecord.h248
-rw-r--r--contrib/libs/libpq/src/include/c.h1383
-rw-r--r--contrib/libs/libpq/src/include/catalog/catversion.h62
-rw-r--r--contrib/libs/libpq/src/include/catalog/pg_control.h258
-rw-r--r--contrib/libs/libpq/src/include/common/archive.h21
-rw-r--r--contrib/libs/libpq/src/include/common/base64.h19
-rw-r--r--contrib/libs/libpq/src/include/common/checksum_helper.h72
-rw-r--r--contrib/libs/libpq/src/include/common/compression.h53
-rw-r--r--contrib/libs/libpq/src/include/common/config_info.h21
-rw-r--r--contrib/libs/libpq/src/include/common/controldata_utils.h19
-rw-r--r--contrib/libs/libpq/src/include/common/cryptohash.h39
-rw-r--r--contrib/libs/libpq/src/include/common/fe_memutils.h73
-rw-r--r--contrib/libs/libpq/src/include/common/file_perm.h56
-rw-r--r--contrib/libs/libpq/src/include/common/file_utils.h49
-rw-r--r--contrib/libs/libpq/src/include/common/hashfn.h104
-rw-r--r--contrib/libs/libpq/src/include/common/hmac.h30
-rw-r--r--contrib/libs/libpq/src/include/common/ip.h33
-rw-r--r--contrib/libs/libpq/src/include/common/jsonapi.h177
-rw-r--r--contrib/libs/libpq/src/include/common/keywords.h29
-rw-r--r--contrib/libs/libpq/src/include/common/kwlookup.h44
-rw-r--r--contrib/libs/libpq/src/include/common/link-canary.h17
-rw-r--r--contrib/libs/libpq/src/include/common/logging.h156
-rw-r--r--contrib/libs/libpq/src/include/common/md5.h37
-rw-r--r--contrib/libs/libpq/src/include/common/openssl.h49
-rw-r--r--contrib/libs/libpq/src/include/common/percentrepl.h18
-rw-r--r--contrib/libs/libpq/src/include/common/pg_lzcompress.h93
-rw-r--r--contrib/libs/libpq/src/include/common/pg_prng.h61
-rw-r--r--contrib/libs/libpq/src/include/common/relpath.h97
-rw-r--r--contrib/libs/libpq/src/include/common/restricted_token.h24
-rw-r--r--contrib/libs/libpq/src/include/common/saslprep.h30
-rw-r--r--contrib/libs/libpq/src/include/common/scram-common.h70
-rw-r--r--contrib/libs/libpq/src/include/common/sha1.h21
-rw-r--r--contrib/libs/libpq/src/include/common/sha2.h32
-rw-r--r--contrib/libs/libpq/src/include/common/shortest_dec.h63
-rw-r--r--contrib/libs/libpq/src/include/common/string.h44
-rw-r--r--contrib/libs/libpq/src/include/common/unicode_east_asian_fw_table.h125
-rw-r--r--contrib/libs/libpq/src/include/common/unicode_nonspacing_table.h326
-rw-r--r--contrib/libs/libpq/src/include/common/unicode_norm.h39
-rw-r--r--contrib/libs/libpq/src/include/common/unicode_norm_table.h9114
-rw-r--r--contrib/libs/libpq/src/include/common/username.h15
-rw-r--r--contrib/libs/libpq/src/include/datatype/timestamp.h243
-rw-r--r--contrib/libs/libpq/src/include/lib/sort_template.h432
-rw-r--r--contrib/libs/libpq/src/include/lib/stringinfo.h161
-rw-r--r--contrib/libs/libpq/src/include/libpq/libpq-fs.h24
-rw-r--r--contrib/libs/libpq/src/include/libpq/pqcomm.h163
-rw-r--r--contrib/libs/libpq/src/include/mb/pg_wchar.h772
-rw-r--r--contrib/libs/libpq/src/include/parser/kwlist.h498
-rw-r--r--contrib/libs/libpq/src/include/pg_config-linux-aarch64.h6
-rw-r--r--contrib/libs/libpq/src/include/pg_config-linux.h828
-rw-r--r--contrib/libs/libpq/src/include/pg_config-osx-arm64.h159
-rw-r--r--contrib/libs/libpq/src/include/pg_config-osx.h156
-rw-r--r--contrib/libs/libpq/src/include/pg_config-win.h318
-rw-r--r--contrib/libs/libpq/src/include/pg_config.h13
-rw-r--r--contrib/libs/libpq/src/include/pg_config_ext.h8
-rw-r--r--contrib/libs/libpq/src/include/pg_config_manual.h372
-rw-r--r--contrib/libs/libpq/src/include/pg_config_os-linux.h1
-rw-r--r--contrib/libs/libpq/src/include/pg_config_os-osx.h1
-rw-r--r--contrib/libs/libpq/src/include/pg_config_os-win.h1
-rw-r--r--contrib/libs/libpq/src/include/pg_config_os.h9
-rw-r--r--contrib/libs/libpq/src/include/pgtar.h45
-rw-r--r--contrib/libs/libpq/src/include/pgtime.h94
-rw-r--r--contrib/libs/libpq/src/include/port.h520
-rw-r--r--contrib/libs/libpq/src/include/port/darwin.h8
-rw-r--r--contrib/libs/libpq/src/include/port/linux.h22
-rw-r--r--contrib/libs/libpq/src/include/port/pg_bitutils.h339
-rw-r--r--contrib/libs/libpq/src/include/port/pg_bswap.h161
-rw-r--r--contrib/libs/libpq/src/include/port/pg_crc32c.h101
-rw-r--r--contrib/libs/libpq/src/include/port/pg_iovec.h55
-rw-r--r--contrib/libs/libpq/src/include/port/pg_lfind.h180
-rw-r--r--contrib/libs/libpq/src/include/port/simd.h375
-rw-r--r--contrib/libs/libpq/src/include/port/win32.h60
-rw-r--r--contrib/libs/libpq/src/include/port/win32/arpa/inet.h3
-rw-r--r--contrib/libs/libpq/src/include/port/win32/netdb.h7
-rw-r--r--contrib/libs/libpq/src/include/port/win32/netinet/in.h3
-rw-r--r--contrib/libs/libpq/src/include/port/win32/netinet/tcp.h7
-rw-r--r--contrib/libs/libpq/src/include/port/win32/pwd.h3
-rw-r--r--contrib/libs/libpq/src/include/port/win32/sys/select.h3
-rw-r--r--contrib/libs/libpq/src/include/port/win32/sys/socket.h26
-rw-r--r--contrib/libs/libpq/src/include/port/win32/sys/un.h17
-rw-r--r--contrib/libs/libpq/src/include/port/win32/sys/wait.h3
-rw-r--r--contrib/libs/libpq/src/include/port/win32_msvc/dirent.h34
-rw-r--r--contrib/libs/libpq/src/include/port/win32_msvc/sys/file.h1
-rw-r--r--contrib/libs/libpq/src/include/port/win32_msvc/sys/param.h1
-rw-r--r--contrib/libs/libpq/src/include/port/win32_msvc/sys/time.h1
-rw-r--r--contrib/libs/libpq/src/include/port/win32_msvc/unistd.h9
-rw-r--r--contrib/libs/libpq/src/include/port/win32_port.h594
-rw-r--r--contrib/libs/libpq/src/include/port/win32ntdll.h34
-rw-r--r--contrib/libs/libpq/src/include/postgres.h579
-rw-r--r--contrib/libs/libpq/src/include/postgres_ext.h73
-rw-r--r--contrib/libs/libpq/src/include/postgres_fe.h29
-rw-r--r--contrib/libs/libpq/src/include/storage/backendid.h37
-rw-r--r--contrib/libs/libpq/src/include/storage/block.h108
-rw-r--r--contrib/libs/libpq/src/include/storage/buf.h46
-rw-r--r--contrib/libs/libpq/src/include/storage/relfilelocator.h99
-rw-r--r--contrib/libs/libpq/src/include/utils/elog.h545
-rw-r--r--contrib/libs/libpq/src/include/utils/palloc.h165
-rw-r--r--contrib/libs/libpq/src/interfaces/libpq/README3
-rw-r--r--contrib/libs/libpq/src/interfaces/libpq/exports.txt189
-rw-r--r--contrib/libs/libpq/src/interfaces/libpq/fe-auth-sasl.h131
-rw-r--r--contrib/libs/libpq/src/interfaces/libpq/fe-auth-scram.c936
-rw-r--r--contrib/libs/libpq/src/interfaces/libpq/fe-auth.c1385
-rw-r--r--contrib/libs/libpq/src/interfaces/libpq/fe-auth.h32
-rw-r--r--contrib/libs/libpq/src/interfaces/libpq/fe-connect.c7831
-rw-r--r--contrib/libs/libpq/src/interfaces/libpq/fe-exec.c4445
-rw-r--r--contrib/libs/libpq/src/interfaces/libpq/fe-lobj.c1064
-rw-r--r--contrib/libs/libpq/src/interfaces/libpq/fe-misc.c1333
-rw-r--r--contrib/libs/libpq/src/interfaces/libpq/fe-print.c773
-rw-r--r--contrib/libs/libpq/src/interfaces/libpq/fe-protocol3.c2306
-rw-r--r--contrib/libs/libpq/src/interfaces/libpq/fe-secure-common.c307
-rw-r--r--contrib/libs/libpq/src/interfaces/libpq/fe-secure-common.h30
-rw-r--r--contrib/libs/libpq/src/interfaces/libpq/fe-secure-openssl.c2062
-rw-r--r--contrib/libs/libpq/src/interfaces/libpq/fe-secure.c611
-rw-r--r--contrib/libs/libpq/src/interfaces/libpq/fe-trace.c729
-rw-r--r--contrib/libs/libpq/src/interfaces/libpq/libpq-events.c211
-rw-r--r--contrib/libs/libpq/src/interfaces/libpq/libpq-events.h94
-rw-r--r--contrib/libs/libpq/src/interfaces/libpq/libpq-fe.h675
-rw-r--r--contrib/libs/libpq/src/interfaces/libpq/libpq-int.h939
-rw-r--r--contrib/libs/libpq/src/interfaces/libpq/pqexpbuffer.c412
-rw-r--r--contrib/libs/libpq/src/interfaces/libpq/pqexpbuffer.h192
-rw-r--r--contrib/libs/libpq/src/interfaces/libpq/pthread-win32.c60
-rw-r--r--contrib/libs/libpq/src/interfaces/libpq/win32.c320
-rw-r--r--contrib/libs/libpq/src/port/README32
-rw-r--r--contrib/libs/libpq/src/port/bsearch_arg.c78
-rw-r--r--contrib/libs/libpq/src/port/chklocale.c433
-rw-r--r--contrib/libs/libpq/src/port/dirmod.c422
-rw-r--r--contrib/libs/libpq/src/port/getpeereid.c78
-rw-r--r--contrib/libs/libpq/src/port/inet_aton.c149
-rw-r--r--contrib/libs/libpq/src/port/inet_net_ntop.c296
-rw-r--r--contrib/libs/libpq/src/port/noblock.c66
-rw-r--r--contrib/libs/libpq/src/port/open.c222
-rw-r--r--contrib/libs/libpq/src/port/path.c1057
-rw-r--r--contrib/libs/libpq/src/port/pg_bitutils.c335
-rw-r--r--contrib/libs/libpq/src/port/pg_config_paths.h12
-rw-r--r--contrib/libs/libpq/src/port/pg_crc32c_sb8.c1169
-rw-r--r--contrib/libs/libpq/src/port/pg_crc32c_sse42.c69
-rw-r--r--contrib/libs/libpq/src/port/pg_crc32c_sse42_choose.c64
-rw-r--r--contrib/libs/libpq/src/port/pg_strong_random.c182
-rw-r--r--contrib/libs/libpq/src/port/pgcheckdir.c92
-rw-r--r--contrib/libs/libpq/src/port/pgmkdirp.c148
-rw-r--r--contrib/libs/libpq/src/port/pgsleep.c57
-rw-r--r--contrib/libs/libpq/src/port/pgstrcasecmp.c151
-rw-r--r--contrib/libs/libpq/src/port/pgstrsignal.c64
-rw-r--r--contrib/libs/libpq/src/port/pqsignal.c62
-rw-r--r--contrib/libs/libpq/src/port/pthread-win32.h22
-rw-r--r--contrib/libs/libpq/src/port/qsort.c22
-rw-r--r--contrib/libs/libpq/src/port/qsort_arg.c14
-rw-r--r--contrib/libs/libpq/src/port/quotes.c51
-rw-r--r--contrib/libs/libpq/src/port/snprintf.c1535
-rw-r--r--contrib/libs/libpq/src/port/strerror.c312
-rw-r--r--contrib/libs/libpq/src/port/tar.c206
-rw-r--r--contrib/libs/libpq/src/port/thread.c96
-rw-r--r--contrib/libs/libpq/src/port/win32common.c68
-rw-r--r--contrib/libs/libpq/src/port/win32error.c214
-rw-r--r--contrib/libs/libpq/src/port/win32gettimeofday.c75
-rw-r--r--contrib/libs/libpq/src/port/win32ntdll.c71
-rw-r--r--contrib/libs/libpq/src/port/win32setlocale.c193
-rw-r--r--contrib/libs/libpq/src/port/win32stat.c306
-rw-r--r--contrib/libs/libpq/ya.make155
222 files changed, 78349 insertions, 0 deletions
diff --git a/contrib/libs/libpq/CMakeLists.darwin-arm64.txt b/contrib/libs/libpq/CMakeLists.darwin-arm64.txt
new file mode 100644
index 0000000000..68370e4e4a
--- /dev/null
+++ b/contrib/libs/libpq/CMakeLists.darwin-arm64.txt
@@ -0,0 +1,112 @@
+
+# This file was generated by the build system used internally in the Yandex monorepo.
+# Only simple modifications are allowed (adding source-files to targets, adding simple properties
+# like target_include_directories). These modifications will be ported to original
+# ya.make files by maintainers. Any complex modifications which can't be ported back to the
+# original buildsystem will not be accepted.
+
+
+
+add_library(contrib-libs-libpq)
+target_compile_options(contrib-libs-libpq PRIVATE
+ -DFRONTEND
+ -DUNSAFE_STAT_OK
+ -D_POSIX_PTHREAD_SEMANTICS
+ -D_REENTRANT
+ -D_THREAD_SAFE
+ $<IF:$<CXX_COMPILER_ID:MSVC>,,-Wno-everything>
+)
+target_include_directories(contrib-libs-libpq PUBLIC
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/include
+)
+target_include_directories(contrib-libs-libpq PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/backend
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port
+)
+target_link_libraries(contrib-libs-libpq PUBLIC
+ contrib-libs-libc_compat
+ contrib-libs-openssl
+ contrib-libs-zlib
+)
+target_sources(contrib-libs-libpq PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/archive.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/base64.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/checksum_helper.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/compression.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/config_info.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/controldata_utils.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/cryptohash_openssl.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/d2s.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/encnames.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/exec.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/f2s.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/fe_memutils.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/file_perm.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/file_utils.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/hashfn.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/hmac_openssl.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/ip.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/jsonapi.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/keywords.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/kwlookup.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/link-canary.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/logging.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/md5_common.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/percentrepl.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/pg_get_line.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/pg_lzcompress.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/pg_prng.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/pgfnames.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/protocol_openssl.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/psprintf.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/relpath.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/restricted_token.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/rmtree.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/saslprep.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/scram-common.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/sprompt.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/string.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/stringinfo.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/unicode_norm.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/username.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/wait_error.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/wchar.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-auth-scram.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-auth.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-connect.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-exec.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-lobj.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-misc.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-print.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-protocol3.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-secure-common.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-secure-openssl.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-secure.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-trace.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/libpq-events.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/pqexpbuffer.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/bsearch_arg.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/chklocale.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/getpeereid.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/inet_net_ntop.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/noblock.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/path.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/pg_bitutils.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/pg_crc32c_sb8.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/pg_strong_random.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/pgcheckdir.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/pgmkdirp.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/pgsleep.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/pgstrcasecmp.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/pgstrsignal.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/pqsignal.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/qsort.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/qsort_arg.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/quotes.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/snprintf.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/strerror.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/tar.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/thread.c
+)
diff --git a/contrib/libs/libpq/CMakeLists.darwin-x86_64.txt b/contrib/libs/libpq/CMakeLists.darwin-x86_64.txt
new file mode 100644
index 0000000000..60eae0ae86
--- /dev/null
+++ b/contrib/libs/libpq/CMakeLists.darwin-x86_64.txt
@@ -0,0 +1,114 @@
+
+# This file was generated by the build system used internally in the Yandex monorepo.
+# Only simple modifications are allowed (adding source-files to targets, adding simple properties
+# like target_include_directories). These modifications will be ported to original
+# ya.make files by maintainers. Any complex modifications which can't be ported back to the
+# original buildsystem will not be accepted.
+
+
+
+add_library(contrib-libs-libpq)
+target_compile_options(contrib-libs-libpq PRIVATE
+ -DFRONTEND
+ -DUNSAFE_STAT_OK
+ -D_POSIX_PTHREAD_SEMANTICS
+ -D_REENTRANT
+ -D_THREAD_SAFE
+ $<IF:$<CXX_COMPILER_ID:MSVC>,,-Wno-everything>
+)
+target_include_directories(contrib-libs-libpq PUBLIC
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/include
+)
+target_include_directories(contrib-libs-libpq PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/backend
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port
+)
+target_link_libraries(contrib-libs-libpq PUBLIC
+ contrib-libs-libc_compat
+ contrib-libs-openssl
+ contrib-libs-zlib
+)
+target_sources(contrib-libs-libpq PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/archive.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/base64.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/checksum_helper.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/compression.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/config_info.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/controldata_utils.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/cryptohash_openssl.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/d2s.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/encnames.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/exec.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/f2s.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/fe_memutils.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/file_perm.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/file_utils.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/hashfn.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/hmac_openssl.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/ip.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/jsonapi.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/keywords.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/kwlookup.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/link-canary.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/logging.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/md5_common.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/percentrepl.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/pg_get_line.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/pg_lzcompress.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/pg_prng.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/pgfnames.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/protocol_openssl.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/psprintf.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/relpath.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/restricted_token.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/rmtree.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/saslprep.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/scram-common.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/sprompt.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/string.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/stringinfo.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/unicode_norm.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/username.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/wait_error.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/wchar.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-auth-scram.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-auth.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-connect.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-exec.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-lobj.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-misc.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-print.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-protocol3.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-secure-common.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-secure-openssl.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-secure.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-trace.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/libpq-events.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/pqexpbuffer.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/bsearch_arg.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/chklocale.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/getpeereid.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/inet_net_ntop.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/noblock.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/path.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/pg_bitutils.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/pg_crc32c_sb8.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/pg_strong_random.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/pgcheckdir.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/pgmkdirp.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/pgsleep.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/pgstrcasecmp.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/pgstrsignal.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/pqsignal.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/qsort.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/qsort_arg.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/quotes.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/snprintf.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/strerror.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/tar.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/thread.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/pg_crc32c_sse42.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/pg_crc32c_sse42_choose.c
+)
diff --git a/contrib/libs/libpq/CMakeLists.linux-aarch64.txt b/contrib/libs/libpq/CMakeLists.linux-aarch64.txt
new file mode 100644
index 0000000000..fc19677dc2
--- /dev/null
+++ b/contrib/libs/libpq/CMakeLists.linux-aarch64.txt
@@ -0,0 +1,113 @@
+
+# This file was generated by the build system used internally in the Yandex monorepo.
+# Only simple modifications are allowed (adding source-files to targets, adding simple properties
+# like target_include_directories). These modifications will be ported to original
+# ya.make files by maintainers. Any complex modifications which can't be ported back to the
+# original buildsystem will not be accepted.
+
+
+
+add_library(contrib-libs-libpq)
+target_compile_options(contrib-libs-libpq PRIVATE
+ -DFRONTEND
+ -DUNSAFE_STAT_OK
+ -D_POSIX_PTHREAD_SEMANTICS
+ -D_REENTRANT
+ -D_THREAD_SAFE
+ $<IF:$<CXX_COMPILER_ID:MSVC>,,-Wno-everything>
+)
+target_include_directories(contrib-libs-libpq PUBLIC
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/include
+)
+target_include_directories(contrib-libs-libpq PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/backend
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port
+)
+target_link_libraries(contrib-libs-libpq PUBLIC
+ contrib-libs-linux-headers
+ contrib-libs-libc_compat
+ contrib-libs-openssl
+ contrib-libs-zlib
+)
+target_sources(contrib-libs-libpq PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/archive.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/base64.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/checksum_helper.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/compression.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/config_info.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/controldata_utils.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/cryptohash_openssl.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/d2s.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/encnames.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/exec.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/f2s.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/fe_memutils.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/file_perm.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/file_utils.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/hashfn.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/hmac_openssl.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/ip.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/jsonapi.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/keywords.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/kwlookup.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/link-canary.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/logging.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/md5_common.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/percentrepl.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/pg_get_line.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/pg_lzcompress.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/pg_prng.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/pgfnames.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/protocol_openssl.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/psprintf.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/relpath.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/restricted_token.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/rmtree.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/saslprep.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/scram-common.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/sprompt.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/string.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/stringinfo.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/unicode_norm.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/username.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/wait_error.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/wchar.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-auth-scram.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-auth.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-connect.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-exec.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-lobj.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-misc.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-print.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-protocol3.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-secure-common.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-secure-openssl.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-secure.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-trace.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/libpq-events.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/pqexpbuffer.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/bsearch_arg.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/chklocale.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/getpeereid.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/inet_net_ntop.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/noblock.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/path.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/pg_bitutils.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/pg_crc32c_sb8.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/pg_strong_random.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/pgcheckdir.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/pgmkdirp.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/pgsleep.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/pgstrcasecmp.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/pgstrsignal.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/pqsignal.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/qsort.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/qsort_arg.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/quotes.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/snprintf.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/strerror.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/tar.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/thread.c
+)
diff --git a/contrib/libs/libpq/CMakeLists.linux-x86_64.txt b/contrib/libs/libpq/CMakeLists.linux-x86_64.txt
new file mode 100644
index 0000000000..108f48a475
--- /dev/null
+++ b/contrib/libs/libpq/CMakeLists.linux-x86_64.txt
@@ -0,0 +1,115 @@
+
+# This file was generated by the build system used internally in the Yandex monorepo.
+# Only simple modifications are allowed (adding source-files to targets, adding simple properties
+# like target_include_directories). These modifications will be ported to original
+# ya.make files by maintainers. Any complex modifications which can't be ported back to the
+# original buildsystem will not be accepted.
+
+
+
+add_library(contrib-libs-libpq)
+target_compile_options(contrib-libs-libpq PRIVATE
+ -DFRONTEND
+ -DUNSAFE_STAT_OK
+ -D_POSIX_PTHREAD_SEMANTICS
+ -D_REENTRANT
+ -D_THREAD_SAFE
+ $<IF:$<CXX_COMPILER_ID:MSVC>,,-Wno-everything>
+)
+target_include_directories(contrib-libs-libpq PUBLIC
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/include
+)
+target_include_directories(contrib-libs-libpq PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/backend
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port
+)
+target_link_libraries(contrib-libs-libpq PUBLIC
+ contrib-libs-linux-headers
+ contrib-libs-libc_compat
+ contrib-libs-openssl
+ contrib-libs-zlib
+)
+target_sources(contrib-libs-libpq PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/archive.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/base64.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/checksum_helper.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/compression.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/config_info.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/controldata_utils.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/cryptohash_openssl.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/d2s.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/encnames.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/exec.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/f2s.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/fe_memutils.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/file_perm.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/file_utils.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/hashfn.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/hmac_openssl.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/ip.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/jsonapi.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/keywords.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/kwlookup.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/link-canary.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/logging.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/md5_common.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/percentrepl.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/pg_get_line.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/pg_lzcompress.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/pg_prng.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/pgfnames.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/protocol_openssl.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/psprintf.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/relpath.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/restricted_token.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/rmtree.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/saslprep.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/scram-common.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/sprompt.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/string.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/stringinfo.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/unicode_norm.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/username.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/wait_error.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/common/wchar.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-auth-scram.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-auth.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-connect.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-exec.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-lobj.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-misc.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-print.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-protocol3.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-secure-common.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-secure-openssl.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-secure.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/fe-trace.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/libpq-events.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/interfaces/libpq/pqexpbuffer.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/bsearch_arg.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/chklocale.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/getpeereid.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/inet_net_ntop.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/noblock.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/path.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/pg_bitutils.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/pg_crc32c_sb8.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/pg_strong_random.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/pgcheckdir.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/pgmkdirp.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/pgsleep.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/pgstrcasecmp.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/pgstrsignal.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/pqsignal.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/qsort.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/qsort_arg.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/quotes.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/snprintf.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/strerror.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/tar.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/thread.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/pg_crc32c_sse42.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/libpq/src/port/pg_crc32c_sse42_choose.c
+)
diff --git a/contrib/libs/libpq/CMakeLists.txt b/contrib/libs/libpq/CMakeLists.txt
new file mode 100644
index 0000000000..1beba2829f
--- /dev/null
+++ b/contrib/libs/libpq/CMakeLists.txt
@@ -0,0 +1,17 @@
+
+# This file was generated by the build system used internally in the Yandex monorepo.
+# Only simple modifications are allowed (adding source-files to targets, adding simple properties
+# like target_include_directories). These modifications will be ported to original
+# ya.make files by maintainers. Any complex modifications which can't be ported back to the
+# original buildsystem will not be accepted.
+
+
+if (CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64" AND NOT HAVE_CUDA)
+ include(CMakeLists.linux-aarch64.txt)
+elseif (CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
+ include(CMakeLists.darwin-x86_64.txt)
+elseif (CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64")
+ include(CMakeLists.darwin-arm64.txt)
+elseif (CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" AND NOT HAVE_CUDA)
+ include(CMakeLists.linux-x86_64.txt)
+endif()
diff --git a/contrib/libs/libpq/COPYRIGHT b/contrib/libs/libpq/COPYRIGHT
new file mode 100644
index 0000000000..d33e0f599d
--- /dev/null
+++ b/contrib/libs/libpq/COPYRIGHT
@@ -0,0 +1,23 @@
+PostgreSQL Database Management System
+(formerly known as Postgres, then as Postgres95)
+
+Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+
+Portions Copyright (c) 1994, The Regents of the University of California
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose, without fee, and without a written agreement
+is hereby granted, provided that the above copyright notice and this
+paragraph and the following two paragraphs appear in all copies.
+
+IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
+LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
+DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO
+PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
diff --git a/contrib/libs/libpq/README b/contrib/libs/libpq/README
new file mode 100644
index 0000000000..6416a8cf3b
--- /dev/null
+++ b/contrib/libs/libpq/README
@@ -0,0 +1,27 @@
+PostgreSQL Database Management System
+=====================================
+
+This directory contains the source code distribution of the PostgreSQL
+database management system.
+
+PostgreSQL is an advanced object-relational database management system
+that supports an extended subset of the SQL standard, including
+transactions, foreign keys, subqueries, triggers, user-defined types
+and functions. This distribution also contains C language bindings.
+
+PostgreSQL has many language interfaces, many of which are listed here:
+
+ https://www.postgresql.org/download/
+
+See the file INSTALL for instructions on how to build and install
+PostgreSQL. That file also lists supported operating systems and
+hardware platforms and contains information regarding any other
+software packages that are required to build or run the PostgreSQL
+system. Copyright and license information can be found in the
+file COPYRIGHT. A comprehensive documentation set is included in this
+distribution; it can be read as described in the installation
+instructions.
+
+The latest version of this software may be obtained at
+https://www.postgresql.org/download/. For more information look at our
+web site located at https://www.postgresql.org/.
diff --git a/contrib/libs/libpq/README.git b/contrib/libs/libpq/README.git
new file mode 100644
index 0000000000..4bf614eea4
--- /dev/null
+++ b/contrib/libs/libpq/README.git
@@ -0,0 +1,14 @@
+(This file does not appear in release tarballs.)
+
+In a release or snapshot tarball of PostgreSQL, a documentation file named
+INSTALL will appear in this directory. However, this file is not stored in
+git and so will not be present if you are using a git checkout.
+
+If you are using a git checkout, you can view the most recent installation
+instructions at:
+ https://www.postgresql.org/docs/devel/installation.html
+
+Users compiling from git will also need compatible versions of Bison, Flex,
+and Perl, as discussed in the install documentation. These programs are not
+needed when using a tarball, since the files they are needed to build are
+already present in the tarball. (On Windows, however, you need Perl anyway.)
diff --git a/contrib/libs/libpq/src/backend/catalog/pg_tablespace_d.h b/contrib/libs/libpq/src/backend/catalog/pg_tablespace_d.h
new file mode 100644
index 0000000000..064e58d758
--- /dev/null
+++ b/contrib/libs/libpq/src/backend/catalog/pg_tablespace_d.h
@@ -0,0 +1,38 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_tablespace_d.h
+ * Macro definitions for pg_tablespace
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_TABLESPACE_D_H
+#define PG_TABLESPACE_D_H
+
+#define TableSpaceRelationId 1213
+#define PgTablespaceToastTable 4185
+#define PgTablespaceToastIndex 4186
+#define TablespaceOidIndexId 2697
+#define TablespaceNameIndexId 2698
+
+#define Anum_pg_tablespace_oid 1
+#define Anum_pg_tablespace_spcname 2
+#define Anum_pg_tablespace_spcowner 3
+#define Anum_pg_tablespace_spcacl 4
+#define Anum_pg_tablespace_spcoptions 5
+
+#define Natts_pg_tablespace 5
+
+#define DEFAULTTABLESPACE_OID 1663
+#define GLOBALTABLESPACE_OID 1664
+
+#endif /* PG_TABLESPACE_D_H */
diff --git a/contrib/libs/libpq/src/backend/utils/README.Gen_dummy_probes b/contrib/libs/libpq/src/backend/utils/README.Gen_dummy_probes
new file mode 100644
index 0000000000..e17060ef24
--- /dev/null
+++ b/contrib/libs/libpq/src/backend/utils/README.Gen_dummy_probes
@@ -0,0 +1,27 @@
+# Generating dummy probes
+
+If Postgres isn't configured with dtrace enabled, we need to generate
+dummy probes for the entries in probes.d, that do nothing.
+
+This is accomplished in Unix via the sed script `Gen_dummy_probes.sed`. We
+used to use this in MSVC builds using the perl utility `psed`, which mimicked
+sed. However, that utility disappeared from Windows perl distributions and so
+we converted the sed script to a perl script to be used in MSVC builds.
+
+We still keep the sed script as the authoritative source for generating
+these dummy probes because except on Windows perl is not a hard requirement
+when building from a tarball.
+
+So, if you need to change the way dummy probes are generated, first change
+the sed script, and when it's working generate the perl script. This can
+be accomplished by using the perl utility s2p.
+
+s2p is no longer part of the perl core, so it might not be on your system,
+but it is available on CPAN and also in many package systems. e.g.
+on Fedora it can be installed using `cpan App::s2p` or
+`dnf install perl-App-s2p`.
+
+The Makefile contains a recipe for regenerating Gen_dummy_probes.pl, so all
+you need to do is once you have s2p installed is `make Gen_dummy_probes.pl`
+Note that in a VPATH build this will generate the file in the vpath tree,
+not the source tree.
diff --git a/contrib/libs/libpq/src/backend/utils/errcodes.h b/contrib/libs/libpq/src/backend/utils/errcodes.h
new file mode 100644
index 0000000000..a2f604c2fa
--- /dev/null
+++ b/contrib/libs/libpq/src/backend/utils/errcodes.h
@@ -0,0 +1,354 @@
+/* autogenerated from src/backend/utils/errcodes.txt, do not edit */
+/* there is deliberately not an #ifndef ERRCODES_H here */
+
+/* Class 00 - Successful Completion */
+#define ERRCODE_SUCCESSFUL_COMPLETION MAKE_SQLSTATE('0','0','0','0','0')
+
+/* Class 01 - Warning */
+#define ERRCODE_WARNING MAKE_SQLSTATE('0','1','0','0','0')
+#define ERRCODE_WARNING_DYNAMIC_RESULT_SETS_RETURNED MAKE_SQLSTATE('0','1','0','0','C')
+#define ERRCODE_WARNING_IMPLICIT_ZERO_BIT_PADDING MAKE_SQLSTATE('0','1','0','0','8')
+#define ERRCODE_WARNING_NULL_VALUE_ELIMINATED_IN_SET_FUNCTION MAKE_SQLSTATE('0','1','0','0','3')
+#define ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED MAKE_SQLSTATE('0','1','0','0','7')
+#define ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED MAKE_SQLSTATE('0','1','0','0','6')
+#define ERRCODE_WARNING_STRING_DATA_RIGHT_TRUNCATION MAKE_SQLSTATE('0','1','0','0','4')
+#define ERRCODE_WARNING_DEPRECATED_FEATURE MAKE_SQLSTATE('0','1','P','0','1')
+
+/* Class 02 - No Data (this is also a warning class per the SQL standard) */
+#define ERRCODE_NO_DATA MAKE_SQLSTATE('0','2','0','0','0')
+#define ERRCODE_NO_ADDITIONAL_DYNAMIC_RESULT_SETS_RETURNED MAKE_SQLSTATE('0','2','0','0','1')
+
+/* Class 03 - SQL Statement Not Yet Complete */
+#define ERRCODE_SQL_STATEMENT_NOT_YET_COMPLETE MAKE_SQLSTATE('0','3','0','0','0')
+
+/* Class 08 - Connection Exception */
+#define ERRCODE_CONNECTION_EXCEPTION MAKE_SQLSTATE('0','8','0','0','0')
+#define ERRCODE_CONNECTION_DOES_NOT_EXIST MAKE_SQLSTATE('0','8','0','0','3')
+#define ERRCODE_CONNECTION_FAILURE MAKE_SQLSTATE('0','8','0','0','6')
+#define ERRCODE_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION MAKE_SQLSTATE('0','8','0','0','1')
+#define ERRCODE_SQLSERVER_REJECTED_ESTABLISHMENT_OF_SQLCONNECTION MAKE_SQLSTATE('0','8','0','0','4')
+#define ERRCODE_TRANSACTION_RESOLUTION_UNKNOWN MAKE_SQLSTATE('0','8','0','0','7')
+#define ERRCODE_PROTOCOL_VIOLATION MAKE_SQLSTATE('0','8','P','0','1')
+
+/* Class 09 - Triggered Action Exception */
+#define ERRCODE_TRIGGERED_ACTION_EXCEPTION MAKE_SQLSTATE('0','9','0','0','0')
+
+/* Class 0A - Feature Not Supported */
+#define ERRCODE_FEATURE_NOT_SUPPORTED MAKE_SQLSTATE('0','A','0','0','0')
+
+/* Class 0B - Invalid Transaction Initiation */
+#define ERRCODE_INVALID_TRANSACTION_INITIATION MAKE_SQLSTATE('0','B','0','0','0')
+
+/* Class 0F - Locator Exception */
+#define ERRCODE_LOCATOR_EXCEPTION MAKE_SQLSTATE('0','F','0','0','0')
+#define ERRCODE_L_E_INVALID_SPECIFICATION MAKE_SQLSTATE('0','F','0','0','1')
+
+/* Class 0L - Invalid Grantor */
+#define ERRCODE_INVALID_GRANTOR MAKE_SQLSTATE('0','L','0','0','0')
+#define ERRCODE_INVALID_GRANT_OPERATION MAKE_SQLSTATE('0','L','P','0','1')
+
+/* Class 0P - Invalid Role Specification */
+#define ERRCODE_INVALID_ROLE_SPECIFICATION MAKE_SQLSTATE('0','P','0','0','0')
+
+/* Class 0Z - Diagnostics Exception */
+#define ERRCODE_DIAGNOSTICS_EXCEPTION MAKE_SQLSTATE('0','Z','0','0','0')
+#define ERRCODE_STACKED_DIAGNOSTICS_ACCESSED_WITHOUT_ACTIVE_HANDLER MAKE_SQLSTATE('0','Z','0','0','2')
+
+/* Class 20 - Case Not Found */
+#define ERRCODE_CASE_NOT_FOUND MAKE_SQLSTATE('2','0','0','0','0')
+
+/* Class 21 - Cardinality Violation */
+#define ERRCODE_CARDINALITY_VIOLATION MAKE_SQLSTATE('2','1','0','0','0')
+
+/* Class 22 - Data Exception */
+#define ERRCODE_DATA_EXCEPTION MAKE_SQLSTATE('2','2','0','0','0')
+#define ERRCODE_ARRAY_ELEMENT_ERROR MAKE_SQLSTATE('2','2','0','2','E')
+#define ERRCODE_ARRAY_SUBSCRIPT_ERROR MAKE_SQLSTATE('2','2','0','2','E')
+#define ERRCODE_CHARACTER_NOT_IN_REPERTOIRE MAKE_SQLSTATE('2','2','0','2','1')
+#define ERRCODE_DATETIME_FIELD_OVERFLOW MAKE_SQLSTATE('2','2','0','0','8')
+#define ERRCODE_DATETIME_VALUE_OUT_OF_RANGE MAKE_SQLSTATE('2','2','0','0','8')
+#define ERRCODE_DIVISION_BY_ZERO MAKE_SQLSTATE('2','2','0','1','2')
+#define ERRCODE_ERROR_IN_ASSIGNMENT MAKE_SQLSTATE('2','2','0','0','5')
+#define ERRCODE_ESCAPE_CHARACTER_CONFLICT MAKE_SQLSTATE('2','2','0','0','B')
+#define ERRCODE_INDICATOR_OVERFLOW MAKE_SQLSTATE('2','2','0','2','2')
+#define ERRCODE_INTERVAL_FIELD_OVERFLOW MAKE_SQLSTATE('2','2','0','1','5')
+#define ERRCODE_INVALID_ARGUMENT_FOR_LOG MAKE_SQLSTATE('2','2','0','1','E')
+#define ERRCODE_INVALID_ARGUMENT_FOR_NTILE MAKE_SQLSTATE('2','2','0','1','4')
+#define ERRCODE_INVALID_ARGUMENT_FOR_NTH_VALUE MAKE_SQLSTATE('2','2','0','1','6')
+#define ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION MAKE_SQLSTATE('2','2','0','1','F')
+#define ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION MAKE_SQLSTATE('2','2','0','1','G')
+#define ERRCODE_INVALID_CHARACTER_VALUE_FOR_CAST MAKE_SQLSTATE('2','2','0','1','8')
+#define ERRCODE_INVALID_DATETIME_FORMAT MAKE_SQLSTATE('2','2','0','0','7')
+#define ERRCODE_INVALID_ESCAPE_CHARACTER MAKE_SQLSTATE('2','2','0','1','9')
+#define ERRCODE_INVALID_ESCAPE_OCTET MAKE_SQLSTATE('2','2','0','0','D')
+#define ERRCODE_INVALID_ESCAPE_SEQUENCE MAKE_SQLSTATE('2','2','0','2','5')
+#define ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER MAKE_SQLSTATE('2','2','P','0','6')
+#define ERRCODE_INVALID_INDICATOR_PARAMETER_VALUE MAKE_SQLSTATE('2','2','0','1','0')
+#define ERRCODE_INVALID_PARAMETER_VALUE MAKE_SQLSTATE('2','2','0','2','3')
+#define ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE MAKE_SQLSTATE('2','2','0','1','3')
+#define ERRCODE_INVALID_REGULAR_EXPRESSION MAKE_SQLSTATE('2','2','0','1','B')
+#define ERRCODE_INVALID_ROW_COUNT_IN_LIMIT_CLAUSE MAKE_SQLSTATE('2','2','0','1','W')
+#define ERRCODE_INVALID_ROW_COUNT_IN_RESULT_OFFSET_CLAUSE MAKE_SQLSTATE('2','2','0','1','X')
+#define ERRCODE_INVALID_TABLESAMPLE_ARGUMENT MAKE_SQLSTATE('2','2','0','2','H')
+#define ERRCODE_INVALID_TABLESAMPLE_REPEAT MAKE_SQLSTATE('2','2','0','2','G')
+#define ERRCODE_INVALID_TIME_ZONE_DISPLACEMENT_VALUE MAKE_SQLSTATE('2','2','0','0','9')
+#define ERRCODE_INVALID_USE_OF_ESCAPE_CHARACTER MAKE_SQLSTATE('2','2','0','0','C')
+#define ERRCODE_MOST_SPECIFIC_TYPE_MISMATCH MAKE_SQLSTATE('2','2','0','0','G')
+#define ERRCODE_NULL_VALUE_NOT_ALLOWED MAKE_SQLSTATE('2','2','0','0','4')
+#define ERRCODE_NULL_VALUE_NO_INDICATOR_PARAMETER MAKE_SQLSTATE('2','2','0','0','2')
+#define ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE MAKE_SQLSTATE('2','2','0','0','3')
+#define ERRCODE_SEQUENCE_GENERATOR_LIMIT_EXCEEDED MAKE_SQLSTATE('2','2','0','0','H')
+#define ERRCODE_STRING_DATA_LENGTH_MISMATCH MAKE_SQLSTATE('2','2','0','2','6')
+#define ERRCODE_STRING_DATA_RIGHT_TRUNCATION MAKE_SQLSTATE('2','2','0','0','1')
+#define ERRCODE_SUBSTRING_ERROR MAKE_SQLSTATE('2','2','0','1','1')
+#define ERRCODE_TRIM_ERROR MAKE_SQLSTATE('2','2','0','2','7')
+#define ERRCODE_UNTERMINATED_C_STRING MAKE_SQLSTATE('2','2','0','2','4')
+#define ERRCODE_ZERO_LENGTH_CHARACTER_STRING MAKE_SQLSTATE('2','2','0','0','F')
+#define ERRCODE_FLOATING_POINT_EXCEPTION MAKE_SQLSTATE('2','2','P','0','1')
+#define ERRCODE_INVALID_TEXT_REPRESENTATION MAKE_SQLSTATE('2','2','P','0','2')
+#define ERRCODE_INVALID_BINARY_REPRESENTATION MAKE_SQLSTATE('2','2','P','0','3')
+#define ERRCODE_BAD_COPY_FILE_FORMAT MAKE_SQLSTATE('2','2','P','0','4')
+#define ERRCODE_UNTRANSLATABLE_CHARACTER MAKE_SQLSTATE('2','2','P','0','5')
+#define ERRCODE_NOT_AN_XML_DOCUMENT MAKE_SQLSTATE('2','2','0','0','L')
+#define ERRCODE_INVALID_XML_DOCUMENT MAKE_SQLSTATE('2','2','0','0','M')
+#define ERRCODE_INVALID_XML_CONTENT MAKE_SQLSTATE('2','2','0','0','N')
+#define ERRCODE_INVALID_XML_COMMENT MAKE_SQLSTATE('2','2','0','0','S')
+#define ERRCODE_INVALID_XML_PROCESSING_INSTRUCTION MAKE_SQLSTATE('2','2','0','0','T')
+#define ERRCODE_DUPLICATE_JSON_OBJECT_KEY_VALUE MAKE_SQLSTATE('2','2','0','3','0')
+#define ERRCODE_INVALID_ARGUMENT_FOR_SQL_JSON_DATETIME_FUNCTION MAKE_SQLSTATE('2','2','0','3','1')
+#define ERRCODE_INVALID_JSON_TEXT MAKE_SQLSTATE('2','2','0','3','2')
+#define ERRCODE_INVALID_SQL_JSON_SUBSCRIPT MAKE_SQLSTATE('2','2','0','3','3')
+#define ERRCODE_MORE_THAN_ONE_SQL_JSON_ITEM MAKE_SQLSTATE('2','2','0','3','4')
+#define ERRCODE_NO_SQL_JSON_ITEM MAKE_SQLSTATE('2','2','0','3','5')
+#define ERRCODE_NON_NUMERIC_SQL_JSON_ITEM MAKE_SQLSTATE('2','2','0','3','6')
+#define ERRCODE_NON_UNIQUE_KEYS_IN_A_JSON_OBJECT MAKE_SQLSTATE('2','2','0','3','7')
+#define ERRCODE_SINGLETON_SQL_JSON_ITEM_REQUIRED MAKE_SQLSTATE('2','2','0','3','8')
+#define ERRCODE_SQL_JSON_ARRAY_NOT_FOUND MAKE_SQLSTATE('2','2','0','3','9')
+#define ERRCODE_SQL_JSON_MEMBER_NOT_FOUND MAKE_SQLSTATE('2','2','0','3','A')
+#define ERRCODE_SQL_JSON_NUMBER_NOT_FOUND MAKE_SQLSTATE('2','2','0','3','B')
+#define ERRCODE_SQL_JSON_OBJECT_NOT_FOUND MAKE_SQLSTATE('2','2','0','3','C')
+#define ERRCODE_TOO_MANY_JSON_ARRAY_ELEMENTS MAKE_SQLSTATE('2','2','0','3','D')
+#define ERRCODE_TOO_MANY_JSON_OBJECT_MEMBERS MAKE_SQLSTATE('2','2','0','3','E')
+#define ERRCODE_SQL_JSON_SCALAR_REQUIRED MAKE_SQLSTATE('2','2','0','3','F')
+#define ERRCODE_SQL_JSON_ITEM_CANNOT_BE_CAST_TO_TARGET_TYPE MAKE_SQLSTATE('2','2','0','3','G')
+
+/* Class 23 - Integrity Constraint Violation */
+#define ERRCODE_INTEGRITY_CONSTRAINT_VIOLATION MAKE_SQLSTATE('2','3','0','0','0')
+#define ERRCODE_RESTRICT_VIOLATION MAKE_SQLSTATE('2','3','0','0','1')
+#define ERRCODE_NOT_NULL_VIOLATION MAKE_SQLSTATE('2','3','5','0','2')
+#define ERRCODE_FOREIGN_KEY_VIOLATION MAKE_SQLSTATE('2','3','5','0','3')
+#define ERRCODE_UNIQUE_VIOLATION MAKE_SQLSTATE('2','3','5','0','5')
+#define ERRCODE_CHECK_VIOLATION MAKE_SQLSTATE('2','3','5','1','4')
+#define ERRCODE_EXCLUSION_VIOLATION MAKE_SQLSTATE('2','3','P','0','1')
+
+/* Class 24 - Invalid Cursor State */
+#define ERRCODE_INVALID_CURSOR_STATE MAKE_SQLSTATE('2','4','0','0','0')
+
+/* Class 25 - Invalid Transaction State */
+#define ERRCODE_INVALID_TRANSACTION_STATE MAKE_SQLSTATE('2','5','0','0','0')
+#define ERRCODE_ACTIVE_SQL_TRANSACTION MAKE_SQLSTATE('2','5','0','0','1')
+#define ERRCODE_BRANCH_TRANSACTION_ALREADY_ACTIVE MAKE_SQLSTATE('2','5','0','0','2')
+#define ERRCODE_HELD_CURSOR_REQUIRES_SAME_ISOLATION_LEVEL MAKE_SQLSTATE('2','5','0','0','8')
+#define ERRCODE_INAPPROPRIATE_ACCESS_MODE_FOR_BRANCH_TRANSACTION MAKE_SQLSTATE('2','5','0','0','3')
+#define ERRCODE_INAPPROPRIATE_ISOLATION_LEVEL_FOR_BRANCH_TRANSACTION MAKE_SQLSTATE('2','5','0','0','4')
+#define ERRCODE_NO_ACTIVE_SQL_TRANSACTION_FOR_BRANCH_TRANSACTION MAKE_SQLSTATE('2','5','0','0','5')
+#define ERRCODE_READ_ONLY_SQL_TRANSACTION MAKE_SQLSTATE('2','5','0','0','6')
+#define ERRCODE_SCHEMA_AND_DATA_STATEMENT_MIXING_NOT_SUPPORTED MAKE_SQLSTATE('2','5','0','0','7')
+#define ERRCODE_NO_ACTIVE_SQL_TRANSACTION MAKE_SQLSTATE('2','5','P','0','1')
+#define ERRCODE_IN_FAILED_SQL_TRANSACTION MAKE_SQLSTATE('2','5','P','0','2')
+#define ERRCODE_IDLE_IN_TRANSACTION_SESSION_TIMEOUT MAKE_SQLSTATE('2','5','P','0','3')
+
+/* Class 26 - Invalid SQL Statement Name */
+#define ERRCODE_INVALID_SQL_STATEMENT_NAME MAKE_SQLSTATE('2','6','0','0','0')
+
+/* Class 27 - Triggered Data Change Violation */
+#define ERRCODE_TRIGGERED_DATA_CHANGE_VIOLATION MAKE_SQLSTATE('2','7','0','0','0')
+
+/* Class 28 - Invalid Authorization Specification */
+#define ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION MAKE_SQLSTATE('2','8','0','0','0')
+#define ERRCODE_INVALID_PASSWORD MAKE_SQLSTATE('2','8','P','0','1')
+
+/* Class 2B - Dependent Privilege Descriptors Still Exist */
+#define ERRCODE_DEPENDENT_PRIVILEGE_DESCRIPTORS_STILL_EXIST MAKE_SQLSTATE('2','B','0','0','0')
+#define ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST MAKE_SQLSTATE('2','B','P','0','1')
+
+/* Class 2D - Invalid Transaction Termination */
+#define ERRCODE_INVALID_TRANSACTION_TERMINATION MAKE_SQLSTATE('2','D','0','0','0')
+
+/* Class 2F - SQL Routine Exception */
+#define ERRCODE_SQL_ROUTINE_EXCEPTION MAKE_SQLSTATE('2','F','0','0','0')
+#define ERRCODE_S_R_E_FUNCTION_EXECUTED_NO_RETURN_STATEMENT MAKE_SQLSTATE('2','F','0','0','5')
+#define ERRCODE_S_R_E_MODIFYING_SQL_DATA_NOT_PERMITTED MAKE_SQLSTATE('2','F','0','0','2')
+#define ERRCODE_S_R_E_PROHIBITED_SQL_STATEMENT_ATTEMPTED MAKE_SQLSTATE('2','F','0','0','3')
+#define ERRCODE_S_R_E_READING_SQL_DATA_NOT_PERMITTED MAKE_SQLSTATE('2','F','0','0','4')
+
+/* Class 34 - Invalid Cursor Name */
+#define ERRCODE_INVALID_CURSOR_NAME MAKE_SQLSTATE('3','4','0','0','0')
+
+/* Class 38 - External Routine Exception */
+#define ERRCODE_EXTERNAL_ROUTINE_EXCEPTION MAKE_SQLSTATE('3','8','0','0','0')
+#define ERRCODE_E_R_E_CONTAINING_SQL_NOT_PERMITTED MAKE_SQLSTATE('3','8','0','0','1')
+#define ERRCODE_E_R_E_MODIFYING_SQL_DATA_NOT_PERMITTED MAKE_SQLSTATE('3','8','0','0','2')
+#define ERRCODE_E_R_E_PROHIBITED_SQL_STATEMENT_ATTEMPTED MAKE_SQLSTATE('3','8','0','0','3')
+#define ERRCODE_E_R_E_READING_SQL_DATA_NOT_PERMITTED MAKE_SQLSTATE('3','8','0','0','4')
+
+/* Class 39 - External Routine Invocation Exception */
+#define ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION MAKE_SQLSTATE('3','9','0','0','0')
+#define ERRCODE_E_R_I_E_INVALID_SQLSTATE_RETURNED MAKE_SQLSTATE('3','9','0','0','1')
+#define ERRCODE_E_R_I_E_NULL_VALUE_NOT_ALLOWED MAKE_SQLSTATE('3','9','0','0','4')
+#define ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED MAKE_SQLSTATE('3','9','P','0','1')
+#define ERRCODE_E_R_I_E_SRF_PROTOCOL_VIOLATED MAKE_SQLSTATE('3','9','P','0','2')
+#define ERRCODE_E_R_I_E_EVENT_TRIGGER_PROTOCOL_VIOLATED MAKE_SQLSTATE('3','9','P','0','3')
+
+/* Class 3B - Savepoint Exception */
+#define ERRCODE_SAVEPOINT_EXCEPTION MAKE_SQLSTATE('3','B','0','0','0')
+#define ERRCODE_S_E_INVALID_SPECIFICATION MAKE_SQLSTATE('3','B','0','0','1')
+
+/* Class 3D - Invalid Catalog Name */
+#define ERRCODE_INVALID_CATALOG_NAME MAKE_SQLSTATE('3','D','0','0','0')
+
+/* Class 3F - Invalid Schema Name */
+#define ERRCODE_INVALID_SCHEMA_NAME MAKE_SQLSTATE('3','F','0','0','0')
+
+/* Class 40 - Transaction Rollback */
+#define ERRCODE_TRANSACTION_ROLLBACK MAKE_SQLSTATE('4','0','0','0','0')
+#define ERRCODE_T_R_INTEGRITY_CONSTRAINT_VIOLATION MAKE_SQLSTATE('4','0','0','0','2')
+#define ERRCODE_T_R_SERIALIZATION_FAILURE MAKE_SQLSTATE('4','0','0','0','1')
+#define ERRCODE_T_R_STATEMENT_COMPLETION_UNKNOWN MAKE_SQLSTATE('4','0','0','0','3')
+#define ERRCODE_T_R_DEADLOCK_DETECTED MAKE_SQLSTATE('4','0','P','0','1')
+
+/* Class 42 - Syntax Error or Access Rule Violation */
+#define ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION MAKE_SQLSTATE('4','2','0','0','0')
+#define ERRCODE_SYNTAX_ERROR MAKE_SQLSTATE('4','2','6','0','1')
+#define ERRCODE_INSUFFICIENT_PRIVILEGE MAKE_SQLSTATE('4','2','5','0','1')
+#define ERRCODE_CANNOT_COERCE MAKE_SQLSTATE('4','2','8','4','6')
+#define ERRCODE_GROUPING_ERROR MAKE_SQLSTATE('4','2','8','0','3')
+#define ERRCODE_WINDOWING_ERROR MAKE_SQLSTATE('4','2','P','2','0')
+#define ERRCODE_INVALID_RECURSION MAKE_SQLSTATE('4','2','P','1','9')
+#define ERRCODE_INVALID_FOREIGN_KEY MAKE_SQLSTATE('4','2','8','3','0')
+#define ERRCODE_INVALID_NAME MAKE_SQLSTATE('4','2','6','0','2')
+#define ERRCODE_NAME_TOO_LONG MAKE_SQLSTATE('4','2','6','2','2')
+#define ERRCODE_RESERVED_NAME MAKE_SQLSTATE('4','2','9','3','9')
+#define ERRCODE_DATATYPE_MISMATCH MAKE_SQLSTATE('4','2','8','0','4')
+#define ERRCODE_INDETERMINATE_DATATYPE MAKE_SQLSTATE('4','2','P','1','8')
+#define ERRCODE_COLLATION_MISMATCH MAKE_SQLSTATE('4','2','P','2','1')
+#define ERRCODE_INDETERMINATE_COLLATION MAKE_SQLSTATE('4','2','P','2','2')
+#define ERRCODE_WRONG_OBJECT_TYPE MAKE_SQLSTATE('4','2','8','0','9')
+#define ERRCODE_GENERATED_ALWAYS MAKE_SQLSTATE('4','2','8','C','9')
+#define ERRCODE_UNDEFINED_COLUMN MAKE_SQLSTATE('4','2','7','0','3')
+#define ERRCODE_UNDEFINED_CURSOR MAKE_SQLSTATE('3','4','0','0','0')
+#define ERRCODE_UNDEFINED_DATABASE MAKE_SQLSTATE('3','D','0','0','0')
+#define ERRCODE_UNDEFINED_FUNCTION MAKE_SQLSTATE('4','2','8','8','3')
+#define ERRCODE_UNDEFINED_PSTATEMENT MAKE_SQLSTATE('2','6','0','0','0')
+#define ERRCODE_UNDEFINED_SCHEMA MAKE_SQLSTATE('3','F','0','0','0')
+#define ERRCODE_UNDEFINED_TABLE MAKE_SQLSTATE('4','2','P','0','1')
+#define ERRCODE_UNDEFINED_PARAMETER MAKE_SQLSTATE('4','2','P','0','2')
+#define ERRCODE_UNDEFINED_OBJECT MAKE_SQLSTATE('4','2','7','0','4')
+#define ERRCODE_DUPLICATE_COLUMN MAKE_SQLSTATE('4','2','7','0','1')
+#define ERRCODE_DUPLICATE_CURSOR MAKE_SQLSTATE('4','2','P','0','3')
+#define ERRCODE_DUPLICATE_DATABASE MAKE_SQLSTATE('4','2','P','0','4')
+#define ERRCODE_DUPLICATE_FUNCTION MAKE_SQLSTATE('4','2','7','2','3')
+#define ERRCODE_DUPLICATE_PSTATEMENT MAKE_SQLSTATE('4','2','P','0','5')
+#define ERRCODE_DUPLICATE_SCHEMA MAKE_SQLSTATE('4','2','P','0','6')
+#define ERRCODE_DUPLICATE_TABLE MAKE_SQLSTATE('4','2','P','0','7')
+#define ERRCODE_DUPLICATE_ALIAS MAKE_SQLSTATE('4','2','7','1','2')
+#define ERRCODE_DUPLICATE_OBJECT MAKE_SQLSTATE('4','2','7','1','0')
+#define ERRCODE_AMBIGUOUS_COLUMN MAKE_SQLSTATE('4','2','7','0','2')
+#define ERRCODE_AMBIGUOUS_FUNCTION MAKE_SQLSTATE('4','2','7','2','5')
+#define ERRCODE_AMBIGUOUS_PARAMETER MAKE_SQLSTATE('4','2','P','0','8')
+#define ERRCODE_AMBIGUOUS_ALIAS MAKE_SQLSTATE('4','2','P','0','9')
+#define ERRCODE_INVALID_COLUMN_REFERENCE MAKE_SQLSTATE('4','2','P','1','0')
+#define ERRCODE_INVALID_COLUMN_DEFINITION MAKE_SQLSTATE('4','2','6','1','1')
+#define ERRCODE_INVALID_CURSOR_DEFINITION MAKE_SQLSTATE('4','2','P','1','1')
+#define ERRCODE_INVALID_DATABASE_DEFINITION MAKE_SQLSTATE('4','2','P','1','2')
+#define ERRCODE_INVALID_FUNCTION_DEFINITION MAKE_SQLSTATE('4','2','P','1','3')
+#define ERRCODE_INVALID_PSTATEMENT_DEFINITION MAKE_SQLSTATE('4','2','P','1','4')
+#define ERRCODE_INVALID_SCHEMA_DEFINITION MAKE_SQLSTATE('4','2','P','1','5')
+#define ERRCODE_INVALID_TABLE_DEFINITION MAKE_SQLSTATE('4','2','P','1','6')
+#define ERRCODE_INVALID_OBJECT_DEFINITION MAKE_SQLSTATE('4','2','P','1','7')
+
+/* Class 44 - WITH CHECK OPTION Violation */
+#define ERRCODE_WITH_CHECK_OPTION_VIOLATION MAKE_SQLSTATE('4','4','0','0','0')
+
+/* Class 53 - Insufficient Resources */
+#define ERRCODE_INSUFFICIENT_RESOURCES MAKE_SQLSTATE('5','3','0','0','0')
+#define ERRCODE_DISK_FULL MAKE_SQLSTATE('5','3','1','0','0')
+#define ERRCODE_OUT_OF_MEMORY MAKE_SQLSTATE('5','3','2','0','0')
+#define ERRCODE_TOO_MANY_CONNECTIONS MAKE_SQLSTATE('5','3','3','0','0')
+#define ERRCODE_CONFIGURATION_LIMIT_EXCEEDED MAKE_SQLSTATE('5','3','4','0','0')
+
+/* Class 54 - Program Limit Exceeded */
+#define ERRCODE_PROGRAM_LIMIT_EXCEEDED MAKE_SQLSTATE('5','4','0','0','0')
+#define ERRCODE_STATEMENT_TOO_COMPLEX MAKE_SQLSTATE('5','4','0','0','1')
+#define ERRCODE_TOO_MANY_COLUMNS MAKE_SQLSTATE('5','4','0','1','1')
+#define ERRCODE_TOO_MANY_ARGUMENTS MAKE_SQLSTATE('5','4','0','2','3')
+
+/* Class 55 - Object Not In Prerequisite State */
+#define ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE MAKE_SQLSTATE('5','5','0','0','0')
+#define ERRCODE_OBJECT_IN_USE MAKE_SQLSTATE('5','5','0','0','6')
+#define ERRCODE_CANT_CHANGE_RUNTIME_PARAM MAKE_SQLSTATE('5','5','P','0','2')
+#define ERRCODE_LOCK_NOT_AVAILABLE MAKE_SQLSTATE('5','5','P','0','3')
+#define ERRCODE_UNSAFE_NEW_ENUM_VALUE_USAGE MAKE_SQLSTATE('5','5','P','0','4')
+
+/* Class 57 - Operator Intervention */
+#define ERRCODE_OPERATOR_INTERVENTION MAKE_SQLSTATE('5','7','0','0','0')
+#define ERRCODE_QUERY_CANCELED MAKE_SQLSTATE('5','7','0','1','4')
+#define ERRCODE_ADMIN_SHUTDOWN MAKE_SQLSTATE('5','7','P','0','1')
+#define ERRCODE_CRASH_SHUTDOWN MAKE_SQLSTATE('5','7','P','0','2')
+#define ERRCODE_CANNOT_CONNECT_NOW MAKE_SQLSTATE('5','7','P','0','3')
+#define ERRCODE_DATABASE_DROPPED MAKE_SQLSTATE('5','7','P','0','4')
+#define ERRCODE_IDLE_SESSION_TIMEOUT MAKE_SQLSTATE('5','7','P','0','5')
+
+/* Class 58 - System Error (errors external to PostgreSQL itself) */
+#define ERRCODE_SYSTEM_ERROR MAKE_SQLSTATE('5','8','0','0','0')
+#define ERRCODE_IO_ERROR MAKE_SQLSTATE('5','8','0','3','0')
+#define ERRCODE_UNDEFINED_FILE MAKE_SQLSTATE('5','8','P','0','1')
+#define ERRCODE_DUPLICATE_FILE MAKE_SQLSTATE('5','8','P','0','2')
+
+/* Class 72 - Snapshot Failure */
+#define ERRCODE_SNAPSHOT_TOO_OLD MAKE_SQLSTATE('7','2','0','0','0')
+
+/* Class F0 - Configuration File Error */
+#define ERRCODE_CONFIG_FILE_ERROR MAKE_SQLSTATE('F','0','0','0','0')
+#define ERRCODE_LOCK_FILE_EXISTS MAKE_SQLSTATE('F','0','0','0','1')
+
+/* Class HV - Foreign Data Wrapper Error (SQL/MED) */
+#define ERRCODE_FDW_ERROR MAKE_SQLSTATE('H','V','0','0','0')
+#define ERRCODE_FDW_COLUMN_NAME_NOT_FOUND MAKE_SQLSTATE('H','V','0','0','5')
+#define ERRCODE_FDW_DYNAMIC_PARAMETER_VALUE_NEEDED MAKE_SQLSTATE('H','V','0','0','2')
+#define ERRCODE_FDW_FUNCTION_SEQUENCE_ERROR MAKE_SQLSTATE('H','V','0','1','0')
+#define ERRCODE_FDW_INCONSISTENT_DESCRIPTOR_INFORMATION MAKE_SQLSTATE('H','V','0','2','1')
+#define ERRCODE_FDW_INVALID_ATTRIBUTE_VALUE MAKE_SQLSTATE('H','V','0','2','4')
+#define ERRCODE_FDW_INVALID_COLUMN_NAME MAKE_SQLSTATE('H','V','0','0','7')
+#define ERRCODE_FDW_INVALID_COLUMN_NUMBER MAKE_SQLSTATE('H','V','0','0','8')
+#define ERRCODE_FDW_INVALID_DATA_TYPE MAKE_SQLSTATE('H','V','0','0','4')
+#define ERRCODE_FDW_INVALID_DATA_TYPE_DESCRIPTORS MAKE_SQLSTATE('H','V','0','0','6')
+#define ERRCODE_FDW_INVALID_DESCRIPTOR_FIELD_IDENTIFIER MAKE_SQLSTATE('H','V','0','9','1')
+#define ERRCODE_FDW_INVALID_HANDLE MAKE_SQLSTATE('H','V','0','0','B')
+#define ERRCODE_FDW_INVALID_OPTION_INDEX MAKE_SQLSTATE('H','V','0','0','C')
+#define ERRCODE_FDW_INVALID_OPTION_NAME MAKE_SQLSTATE('H','V','0','0','D')
+#define ERRCODE_FDW_INVALID_STRING_LENGTH_OR_BUFFER_LENGTH MAKE_SQLSTATE('H','V','0','9','0')
+#define ERRCODE_FDW_INVALID_STRING_FORMAT MAKE_SQLSTATE('H','V','0','0','A')
+#define ERRCODE_FDW_INVALID_USE_OF_NULL_POINTER MAKE_SQLSTATE('H','V','0','0','9')
+#define ERRCODE_FDW_TOO_MANY_HANDLES MAKE_SQLSTATE('H','V','0','1','4')
+#define ERRCODE_FDW_OUT_OF_MEMORY MAKE_SQLSTATE('H','V','0','0','1')
+#define ERRCODE_FDW_NO_SCHEMAS MAKE_SQLSTATE('H','V','0','0','P')
+#define ERRCODE_FDW_OPTION_NAME_NOT_FOUND MAKE_SQLSTATE('H','V','0','0','J')
+#define ERRCODE_FDW_REPLY_HANDLE MAKE_SQLSTATE('H','V','0','0','K')
+#define ERRCODE_FDW_SCHEMA_NOT_FOUND MAKE_SQLSTATE('H','V','0','0','Q')
+#define ERRCODE_FDW_TABLE_NOT_FOUND MAKE_SQLSTATE('H','V','0','0','R')
+#define ERRCODE_FDW_UNABLE_TO_CREATE_EXECUTION MAKE_SQLSTATE('H','V','0','0','L')
+#define ERRCODE_FDW_UNABLE_TO_CREATE_REPLY MAKE_SQLSTATE('H','V','0','0','M')
+#define ERRCODE_FDW_UNABLE_TO_ESTABLISH_CONNECTION MAKE_SQLSTATE('H','V','0','0','N')
+
+/* Class P0 - PL/pgSQL Error */
+#define ERRCODE_PLPGSQL_ERROR MAKE_SQLSTATE('P','0','0','0','0')
+#define ERRCODE_RAISE_EXCEPTION MAKE_SQLSTATE('P','0','0','0','1')
+#define ERRCODE_NO_DATA_FOUND MAKE_SQLSTATE('P','0','0','0','2')
+#define ERRCODE_TOO_MANY_ROWS MAKE_SQLSTATE('P','0','0','0','3')
+#define ERRCODE_ASSERT_FAILURE MAKE_SQLSTATE('P','0','0','0','4')
+
+/* Class XX - Internal Error */
+#define ERRCODE_INTERNAL_ERROR MAKE_SQLSTATE('X','X','0','0','0')
+#define ERRCODE_DATA_CORRUPTED MAKE_SQLSTATE('X','X','0','0','1')
+#define ERRCODE_INDEX_CORRUPTED MAKE_SQLSTATE('X','X','0','0','2')
diff --git a/contrib/libs/libpq/src/common/archive.c b/contrib/libs/libpq/src/common/archive.c
new file mode 100644
index 0000000000..641a58ee88
--- /dev/null
+++ b/contrib/libs/libpq/src/common/archive.c
@@ -0,0 +1,60 @@
+/*-------------------------------------------------------------------------
+ *
+ * archive.c
+ * Common WAL archive routines
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/common/archive.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#include "common/archive.h"
+#include "common/percentrepl.h"
+
+/*
+ * BuildRestoreCommand
+ *
+ * Builds a restore command to retrieve a file from WAL archives, replacing
+ * the supported aliases with values supplied by the caller as defined by
+ * the GUC parameter restore_command: xlogpath for %p, xlogfname for %f and
+ * lastRestartPointFname for %r.
+ *
+ * The result is a palloc'd string for the restore command built. The
+ * caller is responsible for freeing it. If any of the required arguments
+ * is NULL and that the corresponding alias is found in the command given
+ * by the caller, then an error is thrown.
+ */
+char *
+BuildRestoreCommand(const char *restoreCommand,
+ const char *xlogpath,
+ const char *xlogfname,
+ const char *lastRestartPointFname)
+{
+ char *nativePath = NULL;
+ char *result;
+
+ if (xlogpath)
+ {
+ nativePath = pstrdup(xlogpath);
+ make_native_path(nativePath);
+ }
+
+ result = replace_percent_placeholders(restoreCommand, "restore_command", "frp",
+ xlogfname, lastRestartPointFname, nativePath);
+
+ if (nativePath)
+ pfree(nativePath);
+
+ return result;
+}
diff --git a/contrib/libs/libpq/src/common/base64.c b/contrib/libs/libpq/src/common/base64.c
new file mode 100644
index 0000000000..ec4eb49382
--- /dev/null
+++ b/contrib/libs/libpq/src/common/base64.c
@@ -0,0 +1,242 @@
+/*-------------------------------------------------------------------------
+ *
+ * base64.c
+ * Encoding and decoding routines for base64 without whitespace.
+ *
+ * Copyright (c) 2001-2023, PostgreSQL Global Development Group
+ *
+ *
+ * IDENTIFICATION
+ * src/common/base64.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#include "common/base64.h"
+
+/*
+ * BASE64
+ */
+
+static const char _base64[] =
+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+static const int8 b64lookup[128] = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
+ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
+ -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
+};
+
+/*
+ * pg_b64_encode
+ *
+ * Encode into base64 the given string. Returns the length of the encoded
+ * string, and -1 in the event of an error with the result buffer zeroed
+ * for safety.
+ */
+int
+pg_b64_encode(const char *src, int len, char *dst, int dstlen)
+{
+ char *p;
+ const char *s,
+ *end = src + len;
+ int pos = 2;
+ uint32 buf = 0;
+
+ s = src;
+ p = dst;
+
+ while (s < end)
+ {
+ buf |= (unsigned char) *s << (pos << 3);
+ pos--;
+ s++;
+
+ /* write it out */
+ if (pos < 0)
+ {
+ /*
+ * Leave if there is an overflow in the area allocated for the
+ * encoded string.
+ */
+ if ((p - dst + 4) > dstlen)
+ goto error;
+
+ *p++ = _base64[(buf >> 18) & 0x3f];
+ *p++ = _base64[(buf >> 12) & 0x3f];
+ *p++ = _base64[(buf >> 6) & 0x3f];
+ *p++ = _base64[buf & 0x3f];
+
+ pos = 2;
+ buf = 0;
+ }
+ }
+ if (pos != 2)
+ {
+ /*
+ * Leave if there is an overflow in the area allocated for the encoded
+ * string.
+ */
+ if ((p - dst + 4) > dstlen)
+ goto error;
+
+ *p++ = _base64[(buf >> 18) & 0x3f];
+ *p++ = _base64[(buf >> 12) & 0x3f];
+ *p++ = (pos == 0) ? _base64[(buf >> 6) & 0x3f] : '=';
+ *p++ = '=';
+ }
+
+ Assert((p - dst) <= dstlen);
+ return p - dst;
+
+error:
+ memset(dst, 0, dstlen);
+ return -1;
+}
+
+/*
+ * pg_b64_decode
+ *
+ * Decode the given base64 string. Returns the length of the decoded
+ * string on success, and -1 in the event of an error with the result
+ * buffer zeroed for safety.
+ */
+int
+pg_b64_decode(const char *src, int len, char *dst, int dstlen)
+{
+ const char *srcend = src + len,
+ *s = src;
+ char *p = dst;
+ char c;
+ int b = 0;
+ uint32 buf = 0;
+ int pos = 0,
+ end = 0;
+
+ while (s < srcend)
+ {
+ c = *s++;
+
+ /* Leave if a whitespace is found */
+ if (c == ' ' || c == '\t' || c == '\n' || c == '\r')
+ goto error;
+
+ if (c == '=')
+ {
+ /* end sequence */
+ if (!end)
+ {
+ if (pos == 2)
+ end = 1;
+ else if (pos == 3)
+ end = 2;
+ else
+ {
+ /*
+ * Unexpected "=" character found while decoding base64
+ * sequence.
+ */
+ goto error;
+ }
+ }
+ b = 0;
+ }
+ else
+ {
+ b = -1;
+ if (c > 0 && c < 127)
+ b = b64lookup[(unsigned char) c];
+ if (b < 0)
+ {
+ /* invalid symbol found */
+ goto error;
+ }
+ }
+ /* add it to buffer */
+ buf = (buf << 6) + b;
+ pos++;
+ if (pos == 4)
+ {
+ /*
+ * Leave if there is an overflow in the area allocated for the
+ * decoded string.
+ */
+ if ((p - dst + 1) > dstlen)
+ goto error;
+ *p++ = (buf >> 16) & 255;
+
+ if (end == 0 || end > 1)
+ {
+ /* overflow check */
+ if ((p - dst + 1) > dstlen)
+ goto error;
+ *p++ = (buf >> 8) & 255;
+ }
+ if (end == 0 || end > 2)
+ {
+ /* overflow check */
+ if ((p - dst + 1) > dstlen)
+ goto error;
+ *p++ = buf & 255;
+ }
+ buf = 0;
+ pos = 0;
+ }
+ }
+
+ if (pos != 0)
+ {
+ /*
+ * base64 end sequence is invalid. Input data is missing padding, is
+ * truncated or is otherwise corrupted.
+ */
+ goto error;
+ }
+
+ Assert((p - dst) <= dstlen);
+ return p - dst;
+
+error:
+ memset(dst, 0, dstlen);
+ return -1;
+}
+
+/*
+ * pg_b64_enc_len
+ *
+ * Returns to caller the length of the string if it were encoded with
+ * base64 based on the length provided by caller. This is useful to
+ * estimate how large a buffer allocation needs to be done before doing
+ * the actual encoding.
+ */
+int
+pg_b64_enc_len(int srclen)
+{
+ /* 3 bytes will be converted to 4 */
+ return (srclen + 2) / 3 * 4;
+}
+
+/*
+ * pg_b64_dec_len
+ *
+ * Returns to caller the length of the string if it were to be decoded
+ * with base64, based on the length given by caller. This is useful to
+ * estimate how large a buffer allocation needs to be done before doing
+ * the actual decoding.
+ */
+int
+pg_b64_dec_len(int srclen)
+{
+ return (srclen * 3) >> 2;
+}
diff --git a/contrib/libs/libpq/src/common/checksum_helper.c b/contrib/libs/libpq/src/common/checksum_helper.c
new file mode 100644
index 0000000000..21ff8954fd
--- /dev/null
+++ b/contrib/libs/libpq/src/common/checksum_helper.c
@@ -0,0 +1,232 @@
+/*-------------------------------------------------------------------------
+ *
+ * checksum_helper.c
+ * Compute a checksum of any of various types using common routines
+ *
+ * Portions Copyright (c) 2016-2023, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/common/checksum_helper.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#include "common/checksum_helper.h"
+
+/*
+ * If 'name' is a recognized checksum type, set *type to the corresponding
+ * constant and return true. Otherwise, set *type to CHECKSUM_TYPE_NONE and
+ * return false.
+ */
+bool
+pg_checksum_parse_type(char *name, pg_checksum_type *type)
+{
+ pg_checksum_type result_type = CHECKSUM_TYPE_NONE;
+ bool result = true;
+
+ if (pg_strcasecmp(name, "none") == 0)
+ result_type = CHECKSUM_TYPE_NONE;
+ else if (pg_strcasecmp(name, "crc32c") == 0)
+ result_type = CHECKSUM_TYPE_CRC32C;
+ else if (pg_strcasecmp(name, "sha224") == 0)
+ result_type = CHECKSUM_TYPE_SHA224;
+ else if (pg_strcasecmp(name, "sha256") == 0)
+ result_type = CHECKSUM_TYPE_SHA256;
+ else if (pg_strcasecmp(name, "sha384") == 0)
+ result_type = CHECKSUM_TYPE_SHA384;
+ else if (pg_strcasecmp(name, "sha512") == 0)
+ result_type = CHECKSUM_TYPE_SHA512;
+ else
+ result = false;
+
+ *type = result_type;
+ return result;
+}
+
+/*
+ * Get the canonical human-readable name corresponding to a checksum type.
+ */
+char *
+pg_checksum_type_name(pg_checksum_type type)
+{
+ switch (type)
+ {
+ case CHECKSUM_TYPE_NONE:
+ return "NONE";
+ case CHECKSUM_TYPE_CRC32C:
+ return "CRC32C";
+ case CHECKSUM_TYPE_SHA224:
+ return "SHA224";
+ case CHECKSUM_TYPE_SHA256:
+ return "SHA256";
+ case CHECKSUM_TYPE_SHA384:
+ return "SHA384";
+ case CHECKSUM_TYPE_SHA512:
+ return "SHA512";
+ }
+
+ Assert(false);
+ return "???";
+}
+
+/*
+ * Initialize a checksum context for checksums of the given type.
+ * Returns 0 for a success, -1 for a failure.
+ */
+int
+pg_checksum_init(pg_checksum_context *context, pg_checksum_type type)
+{
+ context->type = type;
+
+ switch (type)
+ {
+ case CHECKSUM_TYPE_NONE:
+ /* do nothing */
+ break;
+ case CHECKSUM_TYPE_CRC32C:
+ INIT_CRC32C(context->raw_context.c_crc32c);
+ break;
+ case CHECKSUM_TYPE_SHA224:
+ context->raw_context.c_sha2 = pg_cryptohash_create(PG_SHA224);
+ if (context->raw_context.c_sha2 == NULL)
+ return -1;
+ if (pg_cryptohash_init(context->raw_context.c_sha2) < 0)
+ {
+ pg_cryptohash_free(context->raw_context.c_sha2);
+ return -1;
+ }
+ break;
+ case CHECKSUM_TYPE_SHA256:
+ context->raw_context.c_sha2 = pg_cryptohash_create(PG_SHA256);
+ if (context->raw_context.c_sha2 == NULL)
+ return -1;
+ if (pg_cryptohash_init(context->raw_context.c_sha2) < 0)
+ {
+ pg_cryptohash_free(context->raw_context.c_sha2);
+ return -1;
+ }
+ break;
+ case CHECKSUM_TYPE_SHA384:
+ context->raw_context.c_sha2 = pg_cryptohash_create(PG_SHA384);
+ if (context->raw_context.c_sha2 == NULL)
+ return -1;
+ if (pg_cryptohash_init(context->raw_context.c_sha2) < 0)
+ {
+ pg_cryptohash_free(context->raw_context.c_sha2);
+ return -1;
+ }
+ break;
+ case CHECKSUM_TYPE_SHA512:
+ context->raw_context.c_sha2 = pg_cryptohash_create(PG_SHA512);
+ if (context->raw_context.c_sha2 == NULL)
+ return -1;
+ if (pg_cryptohash_init(context->raw_context.c_sha2) < 0)
+ {
+ pg_cryptohash_free(context->raw_context.c_sha2);
+ return -1;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+/*
+ * Update a checksum context with new data.
+ * Returns 0 for a success, -1 for a failure.
+ */
+int
+pg_checksum_update(pg_checksum_context *context, const uint8 *input,
+ size_t len)
+{
+ switch (context->type)
+ {
+ case CHECKSUM_TYPE_NONE:
+ /* do nothing */
+ break;
+ case CHECKSUM_TYPE_CRC32C:
+ COMP_CRC32C(context->raw_context.c_crc32c, input, len);
+ break;
+ case CHECKSUM_TYPE_SHA224:
+ case CHECKSUM_TYPE_SHA256:
+ case CHECKSUM_TYPE_SHA384:
+ case CHECKSUM_TYPE_SHA512:
+ if (pg_cryptohash_update(context->raw_context.c_sha2, input, len) < 0)
+ return -1;
+ break;
+ }
+
+ return 0;
+}
+
+/*
+ * Finalize a checksum computation and write the result to an output buffer.
+ *
+ * The caller must ensure that the buffer is at least PG_CHECKSUM_MAX_LENGTH
+ * bytes in length. The return value is the number of bytes actually written,
+ * or -1 for a failure.
+ */
+int
+pg_checksum_final(pg_checksum_context *context, uint8 *output)
+{
+ int retval = 0;
+
+ StaticAssertDecl(sizeof(pg_crc32c) <= PG_CHECKSUM_MAX_LENGTH,
+ "CRC-32C digest too big for PG_CHECKSUM_MAX_LENGTH");
+ StaticAssertDecl(PG_SHA224_DIGEST_LENGTH <= PG_CHECKSUM_MAX_LENGTH,
+ "SHA224 digest too big for PG_CHECKSUM_MAX_LENGTH");
+ StaticAssertDecl(PG_SHA256_DIGEST_LENGTH <= PG_CHECKSUM_MAX_LENGTH,
+ "SHA256 digest too big for PG_CHECKSUM_MAX_LENGTH");
+ StaticAssertDecl(PG_SHA384_DIGEST_LENGTH <= PG_CHECKSUM_MAX_LENGTH,
+ "SHA384 digest too big for PG_CHECKSUM_MAX_LENGTH");
+ StaticAssertDecl(PG_SHA512_DIGEST_LENGTH <= PG_CHECKSUM_MAX_LENGTH,
+ "SHA512 digest too big for PG_CHECKSUM_MAX_LENGTH");
+
+ switch (context->type)
+ {
+ case CHECKSUM_TYPE_NONE:
+ break;
+ case CHECKSUM_TYPE_CRC32C:
+ FIN_CRC32C(context->raw_context.c_crc32c);
+ retval = sizeof(pg_crc32c);
+ memcpy(output, &context->raw_context.c_crc32c, retval);
+ break;
+ case CHECKSUM_TYPE_SHA224:
+ retval = PG_SHA224_DIGEST_LENGTH;
+ if (pg_cryptohash_final(context->raw_context.c_sha2,
+ output, retval) < 0)
+ return -1;
+ pg_cryptohash_free(context->raw_context.c_sha2);
+ break;
+ case CHECKSUM_TYPE_SHA256:
+ retval = PG_SHA256_DIGEST_LENGTH;
+ if (pg_cryptohash_final(context->raw_context.c_sha2,
+ output, retval) < 0)
+ return -1;
+ pg_cryptohash_free(context->raw_context.c_sha2);
+ break;
+ case CHECKSUM_TYPE_SHA384:
+ retval = PG_SHA384_DIGEST_LENGTH;
+ if (pg_cryptohash_final(context->raw_context.c_sha2,
+ output, retval) < 0)
+ return -1;
+ pg_cryptohash_free(context->raw_context.c_sha2);
+ break;
+ case CHECKSUM_TYPE_SHA512:
+ retval = PG_SHA512_DIGEST_LENGTH;
+ if (pg_cryptohash_final(context->raw_context.c_sha2,
+ output, retval) < 0)
+ return -1;
+ pg_cryptohash_free(context->raw_context.c_sha2);
+ break;
+ }
+
+ Assert(retval <= PG_CHECKSUM_MAX_LENGTH);
+ return retval;
+}
diff --git a/contrib/libs/libpq/src/common/compression.c b/contrib/libs/libpq/src/common/compression.c
new file mode 100644
index 0000000000..47b18b8c60
--- /dev/null
+++ b/contrib/libs/libpq/src/common/compression.c
@@ -0,0 +1,476 @@
+/*-------------------------------------------------------------------------
+ *
+ * compression.c
+ *
+ * Shared code for compression methods and specifications.
+ *
+ * A compression specification specifies the parameters that should be used
+ * when performing compression with a specific algorithm. The simplest
+ * possible compression specification is an integer, which sets the
+ * compression level.
+ *
+ * Otherwise, a compression specification is a comma-separated list of items,
+ * each having the form keyword or keyword=value.
+ *
+ * Currently, the supported keywords are "level", "long", and "workers".
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/common/compression.c
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#ifdef USE_ZSTD
+#error #include <zstd.h>
+#endif
+#ifdef HAVE_LIBZ
+#include <zlib.h>
+#endif
+
+#include "common/compression.h"
+
+static int expect_integer_value(char *keyword, char *value,
+ pg_compress_specification *result);
+static bool expect_boolean_value(char *keyword, char *value,
+ pg_compress_specification *result);
+
+/*
+ * Look up a compression algorithm by name. Returns true and sets *algorithm
+ * if the name is recognized. Otherwise returns false.
+ */
+bool
+parse_compress_algorithm(char *name, pg_compress_algorithm *algorithm)
+{
+ if (strcmp(name, "none") == 0)
+ *algorithm = PG_COMPRESSION_NONE;
+ else if (strcmp(name, "gzip") == 0)
+ *algorithm = PG_COMPRESSION_GZIP;
+ else if (strcmp(name, "lz4") == 0)
+ *algorithm = PG_COMPRESSION_LZ4;
+ else if (strcmp(name, "zstd") == 0)
+ *algorithm = PG_COMPRESSION_ZSTD;
+ else
+ return false;
+ return true;
+}
+
+/*
+ * Get the human-readable name corresponding to a particular compression
+ * algorithm.
+ */
+const char *
+get_compress_algorithm_name(pg_compress_algorithm algorithm)
+{
+ switch (algorithm)
+ {
+ case PG_COMPRESSION_NONE:
+ return "none";
+ case PG_COMPRESSION_GZIP:
+ return "gzip";
+ case PG_COMPRESSION_LZ4:
+ return "lz4";
+ case PG_COMPRESSION_ZSTD:
+ return "zstd";
+ /* no default, to provoke compiler warnings if values are added */
+ }
+ Assert(false);
+ return "???"; /* placate compiler */
+}
+
+/*
+ * Parse a compression specification for a specified algorithm.
+ *
+ * See the file header comments for a brief description of what a compression
+ * specification is expected to look like.
+ *
+ * On return, all fields of the result object will be initialized.
+ * In particular, result->parse_error will be NULL if no errors occurred
+ * during parsing, and will otherwise contain an appropriate error message.
+ * The caller may free this error message string using pfree, if desired.
+ * Note, however, even if there's no parse error, the string might not make
+ * sense: e.g. for gzip, level=12 is not sensible, but it does parse OK.
+ *
+ * The compression level is assigned by default if not directly specified
+ * by the specification.
+ *
+ * Use validate_compress_specification() to find out whether a compression
+ * specification is semantically sensible.
+ */
+void
+parse_compress_specification(pg_compress_algorithm algorithm, char *specification,
+ pg_compress_specification *result)
+{
+ int bare_level;
+ char *bare_level_endp;
+
+ /* Initial setup of result object. */
+ result->algorithm = algorithm;
+ result->options = 0;
+ result->parse_error = NULL;
+
+ /*
+ * Assign a default level depending on the compression method. This may
+ * be enforced later.
+ */
+ switch (result->algorithm)
+ {
+ case PG_COMPRESSION_NONE:
+ result->level = 0;
+ break;
+ case PG_COMPRESSION_LZ4:
+#ifdef USE_LZ4
+ result->level = 0; /* fast compression mode */
+#else
+ result->parse_error =
+ psprintf(_("this build does not support compression with %s"),
+ "LZ4");
+#endif
+ break;
+ case PG_COMPRESSION_ZSTD:
+#ifdef USE_ZSTD
+ result->level = ZSTD_CLEVEL_DEFAULT;
+#else
+ result->parse_error =
+ psprintf(_("this build does not support compression with %s"),
+ "ZSTD");
+#endif
+ break;
+ case PG_COMPRESSION_GZIP:
+#ifdef HAVE_LIBZ
+ result->level = Z_DEFAULT_COMPRESSION;
+#else
+ result->parse_error =
+ psprintf(_("this build does not support compression with %s"),
+ "gzip");
+#endif
+ break;
+ }
+
+ /* If there is no specification, we're done already. */
+ if (specification == NULL)
+ return;
+
+ /* As a special case, the specification can be a bare integer. */
+ bare_level = strtol(specification, &bare_level_endp, 10);
+ if (specification != bare_level_endp && *bare_level_endp == '\0')
+ {
+ result->level = bare_level;
+ return;
+ }
+
+ /* Look for comma-separated keyword or keyword=value entries. */
+ while (1)
+ {
+ char *kwstart;
+ char *kwend;
+ char *vstart;
+ char *vend;
+ int kwlen;
+ int vlen;
+ bool has_value;
+ char *keyword;
+ char *value;
+
+ /* Figure start, end, and length of next keyword and any value. */
+ kwstart = kwend = specification;
+ while (*kwend != '\0' && *kwend != ',' && *kwend != '=')
+ ++kwend;
+ kwlen = kwend - kwstart;
+ if (*kwend != '=')
+ {
+ vstart = vend = NULL;
+ vlen = 0;
+ has_value = false;
+ }
+ else
+ {
+ vstart = vend = kwend + 1;
+ while (*vend != '\0' && *vend != ',')
+ ++vend;
+ vlen = vend - vstart;
+ has_value = true;
+ }
+
+ /* Reject empty keyword. */
+ if (kwlen == 0)
+ {
+ result->parse_error =
+ pstrdup(_("found empty string where a compression option was expected"));
+ break;
+ }
+
+ /* Extract keyword and value as separate C strings. */
+ keyword = palloc(kwlen + 1);
+ memcpy(keyword, kwstart, kwlen);
+ keyword[kwlen] = '\0';
+ if (!has_value)
+ value = NULL;
+ else
+ {
+ value = palloc(vlen + 1);
+ memcpy(value, vstart, vlen);
+ value[vlen] = '\0';
+ }
+
+ /* Handle whatever keyword we found. */
+ if (strcmp(keyword, "level") == 0)
+ {
+ result->level = expect_integer_value(keyword, value, result);
+
+ /*
+ * No need to set a flag in "options", there is a default level
+ * set at least thanks to the logic above.
+ */
+ }
+ else if (strcmp(keyword, "workers") == 0)
+ {
+ result->workers = expect_integer_value(keyword, value, result);
+ result->options |= PG_COMPRESSION_OPTION_WORKERS;
+ }
+ else if (strcmp(keyword, "long") == 0)
+ {
+ result->long_distance = expect_boolean_value(keyword, value, result);
+ result->options |= PG_COMPRESSION_OPTION_LONG_DISTANCE;
+ }
+ else
+ result->parse_error =
+ psprintf(_("unrecognized compression option: \"%s\""), keyword);
+
+ /* Release memory, just to be tidy. */
+ pfree(keyword);
+ if (value != NULL)
+ pfree(value);
+
+ /*
+ * If we got an error or have reached the end of the string, stop.
+ *
+ * If there is no value, then the end of the keyword might have been
+ * the end of the string. If there is a value, then the end of the
+ * keyword cannot have been the end of the string, but the end of the
+ * value might have been.
+ */
+ if (result->parse_error != NULL ||
+ (vend == NULL ? *kwend == '\0' : *vend == '\0'))
+ break;
+
+ /* Advance to next entry and loop around. */
+ specification = vend == NULL ? kwend + 1 : vend + 1;
+ }
+}
+
+/*
+ * Parse 'value' as an integer and return the result.
+ *
+ * If parsing fails, set result->parse_error to an appropriate message
+ * and return -1.
+ */
+static int
+expect_integer_value(char *keyword, char *value, pg_compress_specification *result)
+{
+ int ivalue;
+ char *ivalue_endp;
+
+ if (value == NULL)
+ {
+ result->parse_error =
+ psprintf(_("compression option \"%s\" requires a value"),
+ keyword);
+ return -1;
+ }
+
+ ivalue = strtol(value, &ivalue_endp, 10);
+ if (ivalue_endp == value || *ivalue_endp != '\0')
+ {
+ result->parse_error =
+ psprintf(_("value for compression option \"%s\" must be an integer"),
+ keyword);
+ return -1;
+ }
+ return ivalue;
+}
+
+/*
+ * Parse 'value' as a boolean and return the result.
+ *
+ * If parsing fails, set result->parse_error to an appropriate message
+ * and return -1. The caller must check result->parse_error to determine if
+ * the call was successful.
+ *
+ * Valid values are: yes, no, on, off, 1, 0.
+ *
+ * Inspired by ParseVariableBool().
+ */
+static bool
+expect_boolean_value(char *keyword, char *value, pg_compress_specification *result)
+{
+ if (value == NULL)
+ return true;
+
+ if (pg_strcasecmp(value, "yes") == 0)
+ return true;
+ if (pg_strcasecmp(value, "on") == 0)
+ return true;
+ if (pg_strcasecmp(value, "1") == 0)
+ return true;
+
+ if (pg_strcasecmp(value, "no") == 0)
+ return false;
+ if (pg_strcasecmp(value, "off") == 0)
+ return false;
+ if (pg_strcasecmp(value, "0") == 0)
+ return false;
+
+ result->parse_error =
+ psprintf(_("value for compression option \"%s\" must be a Boolean value"),
+ keyword);
+ return false;
+}
+
+/*
+ * Returns NULL if the compression specification string was syntactically
+ * valid and semantically sensible. Otherwise, returns an error message.
+ *
+ * Does not test whether this build of PostgreSQL supports the requested
+ * compression method.
+ */
+char *
+validate_compress_specification(pg_compress_specification *spec)
+{
+ int min_level = 1;
+ int max_level = 1;
+ int default_level = 0;
+
+ /* If it didn't even parse OK, it's definitely no good. */
+ if (spec->parse_error != NULL)
+ return spec->parse_error;
+
+ /*
+ * Check that the algorithm expects a compression level and it is within
+ * the legal range for the algorithm.
+ */
+ switch (spec->algorithm)
+ {
+ case PG_COMPRESSION_GZIP:
+ max_level = 9;
+#ifdef HAVE_LIBZ
+ default_level = Z_DEFAULT_COMPRESSION;
+#endif
+ break;
+ case PG_COMPRESSION_LZ4:
+ max_level = 12;
+ default_level = 0; /* fast mode */
+ break;
+ case PG_COMPRESSION_ZSTD:
+#ifdef USE_ZSTD
+ max_level = ZSTD_maxCLevel();
+ min_level = ZSTD_minCLevel();
+ default_level = ZSTD_CLEVEL_DEFAULT;
+#endif
+ break;
+ case PG_COMPRESSION_NONE:
+ if (spec->level != 0)
+ return psprintf(_("compression algorithm \"%s\" does not accept a compression level"),
+ get_compress_algorithm_name(spec->algorithm));
+ break;
+ }
+
+ if ((spec->level < min_level || spec->level > max_level) &&
+ spec->level != default_level)
+ return psprintf(_("compression algorithm \"%s\" expects a compression level between %d and %d (default at %d)"),
+ get_compress_algorithm_name(spec->algorithm),
+ min_level, max_level, default_level);
+
+ /*
+ * Of the compression algorithms that we currently support, only zstd
+ * allows parallel workers.
+ */
+ if ((spec->options & PG_COMPRESSION_OPTION_WORKERS) != 0 &&
+ (spec->algorithm != PG_COMPRESSION_ZSTD))
+ {
+ return psprintf(_("compression algorithm \"%s\" does not accept a worker count"),
+ get_compress_algorithm_name(spec->algorithm));
+ }
+
+ /*
+ * Of the compression algorithms that we currently support, only zstd
+ * supports long-distance mode.
+ */
+ if ((spec->options & PG_COMPRESSION_OPTION_LONG_DISTANCE) != 0 &&
+ (spec->algorithm != PG_COMPRESSION_ZSTD))
+ {
+ return psprintf(_("compression algorithm \"%s\" does not support long-distance mode"),
+ get_compress_algorithm_name(spec->algorithm));
+ }
+
+ return NULL;
+}
+
+#ifdef FRONTEND
+
+/*
+ * Basic parsing of a value specified through a command-line option, commonly
+ * -Z/--compress.
+ *
+ * The parsing consists of a METHOD:DETAIL string fed later to
+ * parse_compress_specification(). This only extracts METHOD and DETAIL.
+ * If only an integer is found, the method is implied by the value specified.
+ */
+void
+parse_compress_options(const char *option, char **algorithm, char **detail)
+{
+ char *sep;
+ char *endp;
+ long result;
+
+ /*
+ * Check whether the compression specification consists of a bare integer.
+ *
+ * For backward-compatibility, assume "none" if the integer found is zero
+ * and "gzip" otherwise.
+ */
+ result = strtol(option, &endp, 10);
+ if (*endp == '\0')
+ {
+ if (result == 0)
+ {
+ *algorithm = pstrdup("none");
+ *detail = NULL;
+ }
+ else
+ {
+ *algorithm = pstrdup("gzip");
+ *detail = pstrdup(option);
+ }
+ return;
+ }
+
+ /*
+ * Check whether there is a compression detail following the algorithm
+ * name.
+ */
+ sep = strchr(option, ':');
+ if (sep == NULL)
+ {
+ *algorithm = pstrdup(option);
+ *detail = NULL;
+ }
+ else
+ {
+ char *alg;
+
+ alg = palloc((sep - option) + 1);
+ memcpy(alg, option, sep - option);
+ alg[sep - option] = '\0';
+
+ *algorithm = alg;
+ *detail = pstrdup(sep + 1);
+ }
+}
+#endif /* FRONTEND */
diff --git a/contrib/libs/libpq/src/common/config_info.c b/contrib/libs/libpq/src/common/config_info.c
new file mode 100644
index 0000000000..09e78a6efb
--- /dev/null
+++ b/contrib/libs/libpq/src/common/config_info.c
@@ -0,0 +1,201 @@
+/*-------------------------------------------------------------------------
+ *
+ * config_info.c
+ * Common code for pg_config output
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/common/config_info.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#include "common/config_info.h"
+
+
+/*
+ * get_configdata(const char *my_exec_path, size_t *configdata_len)
+ *
+ * Get configure-time constants. The caller is responsible
+ * for pfreeing the result.
+ */
+ConfigData *
+get_configdata(const char *my_exec_path, size_t *configdata_len)
+{
+ ConfigData *configdata;
+ char path[MAXPGPATH];
+ char *lastsep;
+ int i = 0;
+
+ /* Adjust this to match the number of items filled below */
+ *configdata_len = 23;
+ configdata = palloc_array(ConfigData, *configdata_len);
+
+ configdata[i].name = pstrdup("BINDIR");
+ strlcpy(path, my_exec_path, sizeof(path));
+ lastsep = strrchr(path, '/');
+ if (lastsep)
+ *lastsep = '\0';
+ cleanup_path(path);
+ configdata[i].setting = pstrdup(path);
+ i++;
+
+ configdata[i].name = pstrdup("DOCDIR");
+ get_doc_path(my_exec_path, path);
+ cleanup_path(path);
+ configdata[i].setting = pstrdup(path);
+ i++;
+
+ configdata[i].name = pstrdup("HTMLDIR");
+ get_html_path(my_exec_path, path);
+ cleanup_path(path);
+ configdata[i].setting = pstrdup(path);
+ i++;
+
+ configdata[i].name = pstrdup("INCLUDEDIR");
+ get_include_path(my_exec_path, path);
+ cleanup_path(path);
+ configdata[i].setting = pstrdup(path);
+ i++;
+
+ configdata[i].name = pstrdup("PKGINCLUDEDIR");
+ get_pkginclude_path(my_exec_path, path);
+ cleanup_path(path);
+ configdata[i].setting = pstrdup(path);
+ i++;
+
+ configdata[i].name = pstrdup("INCLUDEDIR-SERVER");
+ get_includeserver_path(my_exec_path, path);
+ cleanup_path(path);
+ configdata[i].setting = pstrdup(path);
+ i++;
+
+ configdata[i].name = pstrdup("LIBDIR");
+ get_lib_path(my_exec_path, path);
+ cleanup_path(path);
+ configdata[i].setting = pstrdup(path);
+ i++;
+
+ configdata[i].name = pstrdup("PKGLIBDIR");
+ get_pkglib_path(my_exec_path, path);
+ cleanup_path(path);
+ configdata[i].setting = pstrdup(path);
+ i++;
+
+ configdata[i].name = pstrdup("LOCALEDIR");
+ get_locale_path(my_exec_path, path);
+ cleanup_path(path);
+ configdata[i].setting = pstrdup(path);
+ i++;
+
+ configdata[i].name = pstrdup("MANDIR");
+ get_man_path(my_exec_path, path);
+ cleanup_path(path);
+ configdata[i].setting = pstrdup(path);
+ i++;
+
+ configdata[i].name = pstrdup("SHAREDIR");
+ get_share_path(my_exec_path, path);
+ cleanup_path(path);
+ configdata[i].setting = pstrdup(path);
+ i++;
+
+ configdata[i].name = pstrdup("SYSCONFDIR");
+ get_etc_path(my_exec_path, path);
+ cleanup_path(path);
+ configdata[i].setting = pstrdup(path);
+ i++;
+
+ configdata[i].name = pstrdup("PGXS");
+ get_pkglib_path(my_exec_path, path);
+ strlcat(path, "/pgxs/src/makefiles/pgxs.mk", sizeof(path));
+ cleanup_path(path);
+ configdata[i].setting = pstrdup(path);
+ i++;
+
+ configdata[i].name = pstrdup("CONFIGURE");
+ configdata[i].setting = pstrdup(CONFIGURE_ARGS);
+ i++;
+
+ configdata[i].name = pstrdup("CC");
+#ifdef VAL_CC
+ configdata[i].setting = pstrdup(VAL_CC);
+#else
+ configdata[i].setting = pstrdup(_("not recorded"));
+#endif
+ i++;
+
+ configdata[i].name = pstrdup("CPPFLAGS");
+#ifdef VAL_CPPFLAGS
+ configdata[i].setting = pstrdup(VAL_CPPFLAGS);
+#else
+ configdata[i].setting = pstrdup(_("not recorded"));
+#endif
+ i++;
+
+ configdata[i].name = pstrdup("CFLAGS");
+#ifdef VAL_CFLAGS
+ configdata[i].setting = pstrdup(VAL_CFLAGS);
+#else
+ configdata[i].setting = pstrdup(_("not recorded"));
+#endif
+ i++;
+
+ configdata[i].name = pstrdup("CFLAGS_SL");
+#ifdef VAL_CFLAGS_SL
+ configdata[i].setting = pstrdup(VAL_CFLAGS_SL);
+#else
+ configdata[i].setting = pstrdup(_("not recorded"));
+#endif
+ i++;
+
+ configdata[i].name = pstrdup("LDFLAGS");
+#ifdef VAL_LDFLAGS
+ configdata[i].setting = pstrdup(VAL_LDFLAGS);
+#else
+ configdata[i].setting = pstrdup(_("not recorded"));
+#endif
+ i++;
+
+ configdata[i].name = pstrdup("LDFLAGS_EX");
+#ifdef VAL_LDFLAGS_EX
+ configdata[i].setting = pstrdup(VAL_LDFLAGS_EX);
+#else
+ configdata[i].setting = pstrdup(_("not recorded"));
+#endif
+ i++;
+
+ configdata[i].name = pstrdup("LDFLAGS_SL");
+#ifdef VAL_LDFLAGS_SL
+ configdata[i].setting = pstrdup(VAL_LDFLAGS_SL);
+#else
+ configdata[i].setting = pstrdup(_("not recorded"));
+#endif
+ i++;
+
+ configdata[i].name = pstrdup("LIBS");
+#ifdef VAL_LIBS
+ configdata[i].setting = pstrdup(VAL_LIBS);
+#else
+ configdata[i].setting = pstrdup(_("not recorded"));
+#endif
+ i++;
+
+ configdata[i].name = pstrdup("VERSION");
+ configdata[i].setting = pstrdup("PostgreSQL " PG_VERSION);
+ i++;
+
+ Assert(i == *configdata_len);
+
+ return configdata;
+}
diff --git a/contrib/libs/libpq/src/common/controldata_utils.c b/contrib/libs/libpq/src/common/controldata_utils.c
new file mode 100644
index 0000000000..19305fa07a
--- /dev/null
+++ b/contrib/libs/libpq/src/common/controldata_utils.c
@@ -0,0 +1,269 @@
+/*-------------------------------------------------------------------------
+ *
+ * controldata_utils.c
+ * Common code for control data file output.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/common/controldata_utils.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <time.h>
+
+#include "access/xlog_internal.h"
+#include "catalog/pg_control.h"
+#include "common/controldata_utils.h"
+#include "common/file_perm.h"
+#ifdef FRONTEND
+#include "common/logging.h"
+#endif
+#include "port/pg_crc32c.h"
+
+#ifndef FRONTEND
+#error #include "pgstat.h"
+#error #include "storage/fd.h"
+#endif
+
+/*
+ * get_controlfile()
+ *
+ * Get controlfile values. The result is returned as a palloc'd copy of the
+ * control file data.
+ *
+ * crc_ok_p can be used by the caller to see whether the CRC of the control
+ * file data is correct.
+ */
+ControlFileData *
+get_controlfile(const char *DataDir, bool *crc_ok_p)
+{
+ ControlFileData *ControlFile;
+ int fd;
+ char ControlFilePath[MAXPGPATH];
+ pg_crc32c crc;
+ int r;
+#ifdef FRONTEND
+ pg_crc32c last_crc;
+ int retries = 0;
+#endif
+
+ Assert(crc_ok_p);
+
+ ControlFile = palloc_object(ControlFileData);
+ snprintf(ControlFilePath, MAXPGPATH, "%s/global/pg_control", DataDir);
+
+#ifdef FRONTEND
+ INIT_CRC32C(last_crc);
+
+retry:
+#endif
+
+#ifndef FRONTEND
+ if ((fd = OpenTransientFile(ControlFilePath, O_RDONLY | PG_BINARY)) == -1)
+ ereport(ERROR,
+ (errcode_for_file_access(),
+ errmsg("could not open file \"%s\" for reading: %m",
+ ControlFilePath)));
+#else
+ if ((fd = open(ControlFilePath, O_RDONLY | PG_BINARY, 0)) == -1)
+ pg_fatal("could not open file \"%s\" for reading: %m",
+ ControlFilePath);
+#endif
+
+ r = read(fd, ControlFile, sizeof(ControlFileData));
+ if (r != sizeof(ControlFileData))
+ {
+ if (r < 0)
+#ifndef FRONTEND
+ ereport(ERROR,
+ (errcode_for_file_access(),
+ errmsg("could not read file \"%s\": %m", ControlFilePath)));
+#else
+ pg_fatal("could not read file \"%s\": %m", ControlFilePath);
+#endif
+ else
+#ifndef FRONTEND
+ ereport(ERROR,
+ (errcode(ERRCODE_DATA_CORRUPTED),
+ errmsg("could not read file \"%s\": read %d of %zu",
+ ControlFilePath, r, sizeof(ControlFileData))));
+#else
+ pg_fatal("could not read file \"%s\": read %d of %zu",
+ ControlFilePath, r, sizeof(ControlFileData));
+#endif
+ }
+
+#ifndef FRONTEND
+ if (CloseTransientFile(fd) != 0)
+ ereport(ERROR,
+ (errcode_for_file_access(),
+ errmsg("could not close file \"%s\": %m",
+ ControlFilePath)));
+#else
+ if (close(fd) != 0)
+ pg_fatal("could not close file \"%s\": %m", ControlFilePath);
+#endif
+
+ /* Check the CRC. */
+ INIT_CRC32C(crc);
+ COMP_CRC32C(crc,
+ (char *) ControlFile,
+ offsetof(ControlFileData, crc));
+ FIN_CRC32C(crc);
+
+ *crc_ok_p = EQ_CRC32C(crc, ControlFile->crc);
+
+#ifdef FRONTEND
+
+ /*
+ * If the server was writing at the same time, it is possible that we read
+ * partially updated contents on some systems. If the CRC doesn't match,
+ * retry a limited number of times until we compute the same bad CRC twice
+ * in a row with a short sleep in between. Then the failure is unlikely
+ * to be due to a concurrent write.
+ */
+ if (!*crc_ok_p &&
+ (retries == 0 || !EQ_CRC32C(crc, last_crc)) &&
+ retries < 10)
+ {
+ retries++;
+ last_crc = crc;
+ pg_usleep(10000);
+ goto retry;
+ }
+#endif
+
+ /* Make sure the control file is valid byte order. */
+ if (ControlFile->pg_control_version % 65536 == 0 &&
+ ControlFile->pg_control_version / 65536 != 0)
+#ifndef FRONTEND
+ elog(ERROR, _("byte ordering mismatch"));
+#else
+ pg_log_warning("possible byte ordering mismatch\n"
+ "The byte ordering used to store the pg_control file might not match the one\n"
+ "used by this program. In that case the results below would be incorrect, and\n"
+ "the PostgreSQL installation would be incompatible with this data directory.");
+#endif
+
+ return ControlFile;
+}
+
+/*
+ * update_controlfile()
+ *
+ * Update controlfile values with the contents given by caller. The
+ * contents to write are included in "ControlFile". "do_sync" can be
+ * optionally used to flush the updated control file. Note that it is up
+ * to the caller to properly lock ControlFileLock when calling this
+ * routine in the backend.
+ */
+void
+update_controlfile(const char *DataDir,
+ ControlFileData *ControlFile, bool do_sync)
+{
+ int fd;
+ char buffer[PG_CONTROL_FILE_SIZE];
+ char ControlFilePath[MAXPGPATH];
+
+ /* Update timestamp */
+ ControlFile->time = (pg_time_t) time(NULL);
+
+ /* Recalculate CRC of control file */
+ INIT_CRC32C(ControlFile->crc);
+ COMP_CRC32C(ControlFile->crc,
+ (char *) ControlFile,
+ offsetof(ControlFileData, crc));
+ FIN_CRC32C(ControlFile->crc);
+
+ /*
+ * Write out PG_CONTROL_FILE_SIZE bytes into pg_control by zero-padding
+ * the excess over sizeof(ControlFileData), to avoid premature EOF related
+ * errors when reading it.
+ */
+ memset(buffer, 0, PG_CONTROL_FILE_SIZE);
+ memcpy(buffer, ControlFile, sizeof(ControlFileData));
+
+ snprintf(ControlFilePath, sizeof(ControlFilePath), "%s/%s", DataDir, XLOG_CONTROL_FILE);
+
+#ifndef FRONTEND
+
+ /*
+ * All errors issue a PANIC, so no need to use OpenTransientFile() and to
+ * worry about file descriptor leaks.
+ */
+ if ((fd = BasicOpenFile(ControlFilePath, O_RDWR | PG_BINARY)) < 0)
+ ereport(PANIC,
+ (errcode_for_file_access(),
+ errmsg("could not open file \"%s\": %m",
+ ControlFilePath)));
+#else
+ if ((fd = open(ControlFilePath, O_WRONLY | PG_BINARY,
+ pg_file_create_mode)) == -1)
+ pg_fatal("could not open file \"%s\": %m", ControlFilePath);
+#endif
+
+ errno = 0;
+#ifndef FRONTEND
+ pgstat_report_wait_start(WAIT_EVENT_CONTROL_FILE_WRITE_UPDATE);
+#endif
+ if (write(fd, buffer, PG_CONTROL_FILE_SIZE) != PG_CONTROL_FILE_SIZE)
+ {
+ /* if write didn't set errno, assume problem is no disk space */
+ if (errno == 0)
+ errno = ENOSPC;
+
+#ifndef FRONTEND
+ ereport(PANIC,
+ (errcode_for_file_access(),
+ errmsg("could not write file \"%s\": %m",
+ ControlFilePath)));
+#else
+ pg_fatal("could not write file \"%s\": %m", ControlFilePath);
+#endif
+ }
+#ifndef FRONTEND
+ pgstat_report_wait_end();
+#endif
+
+ if (do_sync)
+ {
+#ifndef FRONTEND
+ pgstat_report_wait_start(WAIT_EVENT_CONTROL_FILE_SYNC_UPDATE);
+ if (pg_fsync(fd) != 0)
+ ereport(PANIC,
+ (errcode_for_file_access(),
+ errmsg("could not fsync file \"%s\": %m",
+ ControlFilePath)));
+ pgstat_report_wait_end();
+#else
+ if (fsync(fd) != 0)
+ pg_fatal("could not fsync file \"%s\": %m", ControlFilePath);
+#endif
+ }
+
+ if (close(fd) != 0)
+ {
+#ifndef FRONTEND
+ ereport(PANIC,
+ (errcode_for_file_access(),
+ errmsg("could not close file \"%s\": %m",
+ ControlFilePath)));
+#else
+ pg_fatal("could not close file \"%s\": %m", ControlFilePath);
+#endif
+ }
+}
diff --git a/contrib/libs/libpq/src/common/cryptohash_openssl.c b/contrib/libs/libpq/src/common/cryptohash_openssl.c
new file mode 100644
index 0000000000..ac2cff0759
--- /dev/null
+++ b/contrib/libs/libpq/src/common/cryptohash_openssl.c
@@ -0,0 +1,353 @@
+/*-------------------------------------------------------------------------
+ *
+ * cryptohash_openssl.c
+ * Set of wrapper routines on top of OpenSSL to support cryptographic
+ * hash functions.
+ *
+ * This should only be used if code is compiled with OpenSSL support.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/common/cryptohash_openssl.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#include <openssl/err.h>
+#include <openssl/evp.h>
+
+#include "common/cryptohash.h"
+#include "common/md5.h"
+#include "common/sha1.h"
+#include "common/sha2.h"
+#ifndef FRONTEND
+#error #include "utils/memutils.h"
+#error #include "utils/resowner.h"
+#error #include "utils/resowner_private.h"
+#endif
+
+/*
+ * In the backend, use an allocation in TopMemoryContext to count for
+ * resowner cleanup handling. In the frontend, use malloc to be able
+ * to return a failure status back to the caller.
+ */
+#ifndef FRONTEND
+#define ALLOC(size) MemoryContextAlloc(TopMemoryContext, size)
+#define FREE(ptr) pfree(ptr)
+#else
+#define ALLOC(size) malloc(size)
+#define FREE(ptr) free(ptr)
+#endif
+
+/* Set of error states */
+typedef enum pg_cryptohash_errno
+{
+ PG_CRYPTOHASH_ERROR_NONE = 0,
+ PG_CRYPTOHASH_ERROR_DEST_LEN,
+ PG_CRYPTOHASH_ERROR_OPENSSL
+} pg_cryptohash_errno;
+
+/*
+ * Internal pg_cryptohash_ctx structure.
+ *
+ * This tracks the resource owner associated to each EVP context data
+ * for the backend.
+ */
+struct pg_cryptohash_ctx
+{
+ pg_cryptohash_type type;
+ pg_cryptohash_errno error;
+ const char *errreason;
+
+ EVP_MD_CTX *evpctx;
+
+#ifndef FRONTEND
+ ResourceOwner resowner;
+#endif
+};
+
+static const char *
+SSLerrmessage(unsigned long ecode)
+{
+ if (ecode == 0)
+ return NULL;
+
+ /*
+ * This may return NULL, but we would fall back to a default error path if
+ * that were the case.
+ */
+ return ERR_reason_error_string(ecode);
+}
+
+/*
+ * pg_cryptohash_create
+ *
+ * Allocate a hash context. Returns NULL on failure for an OOM. The
+ * backend issues an error, without returning.
+ */
+pg_cryptohash_ctx *
+pg_cryptohash_create(pg_cryptohash_type type)
+{
+ pg_cryptohash_ctx *ctx;
+
+ /*
+ * Make sure that the resource owner has space to remember this reference.
+ * This can error out with "out of memory", so do this before any other
+ * allocation to avoid leaking.
+ */
+#ifndef FRONTEND
+ ResourceOwnerEnlargeCryptoHash(CurrentResourceOwner);
+#endif
+
+ ctx = ALLOC(sizeof(pg_cryptohash_ctx));
+ if (ctx == NULL)
+ return NULL;
+ memset(ctx, 0, sizeof(pg_cryptohash_ctx));
+ ctx->type = type;
+ ctx->error = PG_CRYPTOHASH_ERROR_NONE;
+ ctx->errreason = NULL;
+
+ /*
+ * Initialization takes care of assigning the correct type for OpenSSL.
+ * Also ensure that there aren't any unconsumed errors in the queue from
+ * previous runs.
+ */
+ ERR_clear_error();
+ ctx->evpctx = EVP_MD_CTX_create();
+
+ if (ctx->evpctx == NULL)
+ {
+ explicit_bzero(ctx, sizeof(pg_cryptohash_ctx));
+ FREE(ctx);
+#ifndef FRONTEND
+ ereport(ERROR,
+ (errcode(ERRCODE_OUT_OF_MEMORY),
+ errmsg("out of memory")));
+#else
+ return NULL;
+#endif
+ }
+
+#ifndef FRONTEND
+ ctx->resowner = CurrentResourceOwner;
+ ResourceOwnerRememberCryptoHash(CurrentResourceOwner,
+ PointerGetDatum(ctx));
+#endif
+
+ return ctx;
+}
+
+/*
+ * pg_cryptohash_init
+ *
+ * Initialize a hash context. Returns 0 on success, and -1 on failure.
+ */
+int
+pg_cryptohash_init(pg_cryptohash_ctx *ctx)
+{
+ int status = 0;
+
+ if (ctx == NULL)
+ return -1;
+
+ switch (ctx->type)
+ {
+ case PG_MD5:
+ status = EVP_DigestInit_ex(ctx->evpctx, EVP_md5(), NULL);
+ break;
+ case PG_SHA1:
+ status = EVP_DigestInit_ex(ctx->evpctx, EVP_sha1(), NULL);
+ break;
+ case PG_SHA224:
+ status = EVP_DigestInit_ex(ctx->evpctx, EVP_sha224(), NULL);
+ break;
+ case PG_SHA256:
+ status = EVP_DigestInit_ex(ctx->evpctx, EVP_sha256(), NULL);
+ break;
+ case PG_SHA384:
+ status = EVP_DigestInit_ex(ctx->evpctx, EVP_sha384(), NULL);
+ break;
+ case PG_SHA512:
+ status = EVP_DigestInit_ex(ctx->evpctx, EVP_sha512(), NULL);
+ break;
+ }
+
+ /* OpenSSL internals return 1 on success, 0 on failure */
+ if (status <= 0)
+ {
+ ctx->errreason = SSLerrmessage(ERR_get_error());
+ ctx->error = PG_CRYPTOHASH_ERROR_OPENSSL;
+
+ /*
+ * The OpenSSL error queue should normally be empty since we've
+ * consumed an error, but cipher initialization can in FIPS-enabled
+ * OpenSSL builds generate two errors so clear the queue here as well.
+ */
+ ERR_clear_error();
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * pg_cryptohash_update
+ *
+ * Update a hash context. Returns 0 on success, and -1 on failure.
+ */
+int
+pg_cryptohash_update(pg_cryptohash_ctx *ctx, const uint8 *data, size_t len)
+{
+ int status = 0;
+
+ if (ctx == NULL)
+ return -1;
+
+ status = EVP_DigestUpdate(ctx->evpctx, data, len);
+
+ /* OpenSSL internals return 1 on success, 0 on failure */
+ if (status <= 0)
+ {
+ ctx->errreason = SSLerrmessage(ERR_get_error());
+ ctx->error = PG_CRYPTOHASH_ERROR_OPENSSL;
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * pg_cryptohash_final
+ *
+ * Finalize a hash context. Returns 0 on success, and -1 on failure.
+ */
+int
+pg_cryptohash_final(pg_cryptohash_ctx *ctx, uint8 *dest, size_t len)
+{
+ int status = 0;
+
+ if (ctx == NULL)
+ return -1;
+
+ switch (ctx->type)
+ {
+ case PG_MD5:
+ if (len < MD5_DIGEST_LENGTH)
+ {
+ ctx->error = PG_CRYPTOHASH_ERROR_DEST_LEN;
+ return -1;
+ }
+ break;
+ case PG_SHA1:
+ if (len < SHA1_DIGEST_LENGTH)
+ {
+ ctx->error = PG_CRYPTOHASH_ERROR_DEST_LEN;
+ return -1;
+ }
+ break;
+ case PG_SHA224:
+ if (len < PG_SHA224_DIGEST_LENGTH)
+ {
+ ctx->error = PG_CRYPTOHASH_ERROR_DEST_LEN;
+ return -1;
+ }
+ break;
+ case PG_SHA256:
+ if (len < PG_SHA256_DIGEST_LENGTH)
+ {
+ ctx->error = PG_CRYPTOHASH_ERROR_DEST_LEN;
+ return -1;
+ }
+ break;
+ case PG_SHA384:
+ if (len < PG_SHA384_DIGEST_LENGTH)
+ {
+ ctx->error = PG_CRYPTOHASH_ERROR_DEST_LEN;
+ return -1;
+ }
+ break;
+ case PG_SHA512:
+ if (len < PG_SHA512_DIGEST_LENGTH)
+ {
+ ctx->error = PG_CRYPTOHASH_ERROR_DEST_LEN;
+ return -1;
+ }
+ break;
+ }
+
+ status = EVP_DigestFinal_ex(ctx->evpctx, dest, 0);
+
+ /* OpenSSL internals return 1 on success, 0 on failure */
+ if (status <= 0)
+ {
+ ctx->errreason = SSLerrmessage(ERR_get_error());
+ ctx->error = PG_CRYPTOHASH_ERROR_OPENSSL;
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * pg_cryptohash_free
+ *
+ * Free a hash context.
+ */
+void
+pg_cryptohash_free(pg_cryptohash_ctx *ctx)
+{
+ if (ctx == NULL)
+ return;
+
+ EVP_MD_CTX_destroy(ctx->evpctx);
+
+#ifndef FRONTEND
+ ResourceOwnerForgetCryptoHash(ctx->resowner,
+ PointerGetDatum(ctx));
+#endif
+
+ explicit_bzero(ctx, sizeof(pg_cryptohash_ctx));
+ FREE(ctx);
+}
+
+/*
+ * pg_cryptohash_error
+ *
+ * Returns a static string providing details about an error that
+ * happened during a computation.
+ */
+const char *
+pg_cryptohash_error(pg_cryptohash_ctx *ctx)
+{
+ /*
+ * This implementation would never fail because of an out-of-memory error,
+ * except when creating the context.
+ */
+ if (ctx == NULL)
+ return _("out of memory");
+
+ /*
+ * If a reason is provided, rely on it, else fallback to any error code
+ * set.
+ */
+ if (ctx->errreason)
+ return ctx->errreason;
+
+ switch (ctx->error)
+ {
+ case PG_CRYPTOHASH_ERROR_NONE:
+ return _("success");
+ case PG_CRYPTOHASH_ERROR_DEST_LEN:
+ return _("destination buffer too small");
+ case PG_CRYPTOHASH_ERROR_OPENSSL:
+ return _("OpenSSL failure");
+ }
+
+ Assert(false); /* cannot be reached */
+ return _("success");
+}
diff --git a/contrib/libs/libpq/src/common/d2s.c b/contrib/libs/libpq/src/common/d2s.c
new file mode 100644
index 0000000000..614e98192a
--- /dev/null
+++ b/contrib/libs/libpq/src/common/d2s.c
@@ -0,0 +1,1076 @@
+/*---------------------------------------------------------------------------
+ *
+ * Ryu floating-point output for double precision.
+ *
+ * Portions Copyright (c) 2018-2023, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/common/d2s.c
+ *
+ * This is a modification of code taken from github.com/ulfjack/ryu under the
+ * terms of the Boost license (not the Apache license). The original copyright
+ * notice follows:
+ *
+ * Copyright 2018 Ulf Adams
+ *
+ * The contents of this file may be used under the terms of the Apache
+ * License, Version 2.0.
+ *
+ * (See accompanying file LICENSE-Apache or copy at
+ * http://www.apache.org/licenses/LICENSE-2.0)
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * Boost Software License, Version 1.0.
+ *
+ * (See accompanying file LICENSE-Boost or copy at
+ * https://www.boost.org/LICENSE_1_0.txt)
+ *
+ * Unless required by applicable law or agreed to in writing, this software is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+/*
+ * Runtime compiler options:
+ *
+ * -DRYU_ONLY_64_BIT_OPS Avoid using uint128 or 64-bit intrinsics. Slower,
+ * depending on your compiler.
+ */
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#include "common/shortest_dec.h"
+
+/*
+ * For consistency, we use 128-bit types if and only if the rest of PG also
+ * does, even though we could use them here without worrying about the
+ * alignment concerns that apply elsewhere.
+ */
+#if !defined(HAVE_INT128) && defined(_MSC_VER) \
+ && !defined(RYU_ONLY_64_BIT_OPS) && defined(_M_X64)
+#define HAS_64_BIT_INTRINSICS
+#endif
+
+#include "ryu_common.h"
+#include "digit_table.h"
+#include "d2s_full_table.h"
+#include "d2s_intrinsics.h"
+
+#define DOUBLE_MANTISSA_BITS 52
+#define DOUBLE_EXPONENT_BITS 11
+#define DOUBLE_BIAS 1023
+
+#define DOUBLE_POW5_INV_BITCOUNT 122
+#define DOUBLE_POW5_BITCOUNT 121
+
+
+static inline uint32
+pow5Factor(uint64 value)
+{
+ uint32 count = 0;
+
+ for (;;)
+ {
+ Assert(value != 0);
+ const uint64 q = div5(value);
+ const uint32 r = (uint32) (value - 5 * q);
+
+ if (r != 0)
+ break;
+
+ value = q;
+ ++count;
+ }
+ return count;
+}
+
+/* Returns true if value is divisible by 5^p. */
+static inline bool
+multipleOfPowerOf5(const uint64 value, const uint32 p)
+{
+ /*
+ * I tried a case distinction on p, but there was no performance
+ * difference.
+ */
+ return pow5Factor(value) >= p;
+}
+
+/* Returns true if value is divisible by 2^p. */
+static inline bool
+multipleOfPowerOf2(const uint64 value, const uint32 p)
+{
+ /* return __builtin_ctzll(value) >= p; */
+ return (value & ((UINT64CONST(1) << p) - 1)) == 0;
+}
+
+/*
+ * We need a 64x128-bit multiplication and a subsequent 128-bit shift.
+ *
+ * Multiplication:
+ *
+ * The 64-bit factor is variable and passed in, the 128-bit factor comes
+ * from a lookup table. We know that the 64-bit factor only has 55
+ * significant bits (i.e., the 9 topmost bits are zeros). The 128-bit
+ * factor only has 124 significant bits (i.e., the 4 topmost bits are
+ * zeros).
+ *
+ * Shift:
+ *
+ * In principle, the multiplication result requires 55 + 124 = 179 bits to
+ * represent. However, we then shift this value to the right by j, which is
+ * at least j >= 115, so the result is guaranteed to fit into 179 - 115 =
+ * 64 bits. This means that we only need the topmost 64 significant bits of
+ * the 64x128-bit multiplication.
+ *
+ * There are several ways to do this:
+ *
+ * 1. Best case: the compiler exposes a 128-bit type.
+ * We perform two 64x64-bit multiplications, add the higher 64 bits of the
+ * lower result to the higher result, and shift by j - 64 bits.
+ *
+ * We explicitly cast from 64-bit to 128-bit, so the compiler can tell
+ * that these are only 64-bit inputs, and can map these to the best
+ * possible sequence of assembly instructions. x86-64 machines happen to
+ * have matching assembly instructions for 64x64-bit multiplications and
+ * 128-bit shifts.
+ *
+ * 2. Second best case: the compiler exposes intrinsics for the x86-64
+ * assembly instructions mentioned in 1.
+ *
+ * 3. We only have 64x64 bit instructions that return the lower 64 bits of
+ * the result, i.e., we have to use plain C.
+ *
+ * Our inputs are less than the full width, so we have three options:
+ * a. Ignore this fact and just implement the intrinsics manually.
+ * b. Split both into 31-bit pieces, which guarantees no internal
+ * overflow, but requires extra work upfront (unless we change the
+ * lookup table).
+ * c. Split only the first factor into 31-bit pieces, which also
+ * guarantees no internal overflow, but requires extra work since the
+ * intermediate results are not perfectly aligned.
+ */
+#if defined(HAVE_INT128)
+
+/* Best case: use 128-bit type. */
+static inline uint64
+mulShift(const uint64 m, const uint64 *const mul, const int32 j)
+{
+ const uint128 b0 = ((uint128) m) * mul[0];
+ const uint128 b2 = ((uint128) m) * mul[1];
+
+ return (uint64) (((b0 >> 64) + b2) >> (j - 64));
+}
+
+static inline uint64
+mulShiftAll(const uint64 m, const uint64 *const mul, const int32 j,
+ uint64 *const vp, uint64 *const vm, const uint32 mmShift)
+{
+ *vp = mulShift(4 * m + 2, mul, j);
+ *vm = mulShift(4 * m - 1 - mmShift, mul, j);
+ return mulShift(4 * m, mul, j);
+}
+
+#elif defined(HAS_64_BIT_INTRINSICS)
+
+static inline uint64
+mulShift(const uint64 m, const uint64 *const mul, const int32 j)
+{
+ /* m is maximum 55 bits */
+ uint64 high1;
+
+ /* 128 */
+ const uint64 low1 = umul128(m, mul[1], &high1);
+
+ /* 64 */
+ uint64 high0;
+ uint64 sum;
+
+ /* 64 */
+ umul128(m, mul[0], &high0);
+ /* 0 */
+ sum = high0 + low1;
+
+ if (sum < high0)
+ {
+ ++high1;
+ /* overflow into high1 */
+ }
+ return shiftright128(sum, high1, j - 64);
+}
+
+static inline uint64
+mulShiftAll(const uint64 m, const uint64 *const mul, const int32 j,
+ uint64 *const vp, uint64 *const vm, const uint32 mmShift)
+{
+ *vp = mulShift(4 * m + 2, mul, j);
+ *vm = mulShift(4 * m - 1 - mmShift, mul, j);
+ return mulShift(4 * m, mul, j);
+}
+
+#else /* // !defined(HAVE_INT128) &&
+ * !defined(HAS_64_BIT_INTRINSICS) */
+
+static inline uint64
+mulShiftAll(uint64 m, const uint64 *const mul, const int32 j,
+ uint64 *const vp, uint64 *const vm, const uint32 mmShift)
+{
+ m <<= 1; /* m is maximum 55 bits */
+
+ uint64 tmp;
+ const uint64 lo = umul128(m, mul[0], &tmp);
+ uint64 hi;
+ const uint64 mid = tmp + umul128(m, mul[1], &hi);
+
+ hi += mid < tmp; /* overflow into hi */
+
+ const uint64 lo2 = lo + mul[0];
+ const uint64 mid2 = mid + mul[1] + (lo2 < lo);
+ const uint64 hi2 = hi + (mid2 < mid);
+
+ *vp = shiftright128(mid2, hi2, j - 64 - 1);
+
+ if (mmShift == 1)
+ {
+ const uint64 lo3 = lo - mul[0];
+ const uint64 mid3 = mid - mul[1] - (lo3 > lo);
+ const uint64 hi3 = hi - (mid3 > mid);
+
+ *vm = shiftright128(mid3, hi3, j - 64 - 1);
+ }
+ else
+ {
+ const uint64 lo3 = lo + lo;
+ const uint64 mid3 = mid + mid + (lo3 < lo);
+ const uint64 hi3 = hi + hi + (mid3 < mid);
+ const uint64 lo4 = lo3 - mul[0];
+ const uint64 mid4 = mid3 - mul[1] - (lo4 > lo3);
+ const uint64 hi4 = hi3 - (mid4 > mid3);
+
+ *vm = shiftright128(mid4, hi4, j - 64);
+ }
+
+ return shiftright128(mid, hi, j - 64 - 1);
+}
+
+#endif /* // HAS_64_BIT_INTRINSICS */
+
+static inline uint32
+decimalLength(const uint64 v)
+{
+ /* This is slightly faster than a loop. */
+ /* The average output length is 16.38 digits, so we check high-to-low. */
+ /* Function precondition: v is not an 18, 19, or 20-digit number. */
+ /* (17 digits are sufficient for round-tripping.) */
+ Assert(v < 100000000000000000L);
+ if (v >= 10000000000000000L)
+ {
+ return 17;
+ }
+ if (v >= 1000000000000000L)
+ {
+ return 16;
+ }
+ if (v >= 100000000000000L)
+ {
+ return 15;
+ }
+ if (v >= 10000000000000L)
+ {
+ return 14;
+ }
+ if (v >= 1000000000000L)
+ {
+ return 13;
+ }
+ if (v >= 100000000000L)
+ {
+ return 12;
+ }
+ if (v >= 10000000000L)
+ {
+ return 11;
+ }
+ if (v >= 1000000000L)
+ {
+ return 10;
+ }
+ if (v >= 100000000L)
+ {
+ return 9;
+ }
+ if (v >= 10000000L)
+ {
+ return 8;
+ }
+ if (v >= 1000000L)
+ {
+ return 7;
+ }
+ if (v >= 100000L)
+ {
+ return 6;
+ }
+ if (v >= 10000L)
+ {
+ return 5;
+ }
+ if (v >= 1000L)
+ {
+ return 4;
+ }
+ if (v >= 100L)
+ {
+ return 3;
+ }
+ if (v >= 10L)
+ {
+ return 2;
+ }
+ return 1;
+}
+
+/* A floating decimal representing m * 10^e. */
+typedef struct floating_decimal_64
+{
+ uint64 mantissa;
+ int32 exponent;
+} floating_decimal_64;
+
+static inline floating_decimal_64
+d2d(const uint64 ieeeMantissa, const uint32 ieeeExponent)
+{
+ int32 e2;
+ uint64 m2;
+
+ if (ieeeExponent == 0)
+ {
+ /* We subtract 2 so that the bounds computation has 2 additional bits. */
+ e2 = 1 - DOUBLE_BIAS - DOUBLE_MANTISSA_BITS - 2;
+ m2 = ieeeMantissa;
+ }
+ else
+ {
+ e2 = ieeeExponent - DOUBLE_BIAS - DOUBLE_MANTISSA_BITS - 2;
+ m2 = (UINT64CONST(1) << DOUBLE_MANTISSA_BITS) | ieeeMantissa;
+ }
+
+#if STRICTLY_SHORTEST
+ const bool even = (m2 & 1) == 0;
+ const bool acceptBounds = even;
+#else
+ const bool acceptBounds = false;
+#endif
+
+ /* Step 2: Determine the interval of legal decimal representations. */
+ const uint64 mv = 4 * m2;
+
+ /* Implicit bool -> int conversion. True is 1, false is 0. */
+ const uint32 mmShift = ieeeMantissa != 0 || ieeeExponent <= 1;
+
+ /* We would compute mp and mm like this: */
+ /* uint64 mp = 4 * m2 + 2; */
+ /* uint64 mm = mv - 1 - mmShift; */
+
+ /* Step 3: Convert to a decimal power base using 128-bit arithmetic. */
+ uint64 vr,
+ vp,
+ vm;
+ int32 e10;
+ bool vmIsTrailingZeros = false;
+ bool vrIsTrailingZeros = false;
+
+ if (e2 >= 0)
+ {
+ /*
+ * I tried special-casing q == 0, but there was no effect on
+ * performance.
+ *
+ * This expr is slightly faster than max(0, log10Pow2(e2) - 1).
+ */
+ const uint32 q = log10Pow2(e2) - (e2 > 3);
+ const int32 k = DOUBLE_POW5_INV_BITCOUNT + pow5bits(q) - 1;
+ const int32 i = -e2 + q + k;
+
+ e10 = q;
+
+ vr = mulShiftAll(m2, DOUBLE_POW5_INV_SPLIT[q], i, &vp, &vm, mmShift);
+
+ if (q <= 21)
+ {
+ /*
+ * This should use q <= 22, but I think 21 is also safe. Smaller
+ * values may still be safe, but it's more difficult to reason
+ * about them.
+ *
+ * Only one of mp, mv, and mm can be a multiple of 5, if any.
+ */
+ const uint32 mvMod5 = (uint32) (mv - 5 * div5(mv));
+
+ if (mvMod5 == 0)
+ {
+ vrIsTrailingZeros = multipleOfPowerOf5(mv, q);
+ }
+ else if (acceptBounds)
+ {
+ /*----
+ * Same as min(e2 + (~mm & 1), pow5Factor(mm)) >= q
+ * <=> e2 + (~mm & 1) >= q && pow5Factor(mm) >= q
+ * <=> true && pow5Factor(mm) >= q, since e2 >= q.
+ *----
+ */
+ vmIsTrailingZeros = multipleOfPowerOf5(mv - 1 - mmShift, q);
+ }
+ else
+ {
+ /* Same as min(e2 + 1, pow5Factor(mp)) >= q. */
+ vp -= multipleOfPowerOf5(mv + 2, q);
+ }
+ }
+ }
+ else
+ {
+ /*
+ * This expression is slightly faster than max(0, log10Pow5(-e2) - 1).
+ */
+ const uint32 q = log10Pow5(-e2) - (-e2 > 1);
+ const int32 i = -e2 - q;
+ const int32 k = pow5bits(i) - DOUBLE_POW5_BITCOUNT;
+ const int32 j = q - k;
+
+ e10 = q + e2;
+
+ vr = mulShiftAll(m2, DOUBLE_POW5_SPLIT[i], j, &vp, &vm, mmShift);
+
+ if (q <= 1)
+ {
+ /*
+ * {vr,vp,vm} is trailing zeros if {mv,mp,mm} has at least q
+ * trailing 0 bits.
+ */
+ /* mv = 4 * m2, so it always has at least two trailing 0 bits. */
+ vrIsTrailingZeros = true;
+ if (acceptBounds)
+ {
+ /*
+ * mm = mv - 1 - mmShift, so it has 1 trailing 0 bit iff
+ * mmShift == 1.
+ */
+ vmIsTrailingZeros = mmShift == 1;
+ }
+ else
+ {
+ /*
+ * mp = mv + 2, so it always has at least one trailing 0 bit.
+ */
+ --vp;
+ }
+ }
+ else if (q < 63)
+ {
+ /* TODO(ulfjack):Use a tighter bound here. */
+ /*
+ * We need to compute min(ntz(mv), pow5Factor(mv) - e2) >= q - 1
+ */
+ /* <=> ntz(mv) >= q - 1 && pow5Factor(mv) - e2 >= q - 1 */
+ /* <=> ntz(mv) >= q - 1 (e2 is negative and -e2 >= q) */
+ /* <=> (mv & ((1 << (q - 1)) - 1)) == 0 */
+
+ /*
+ * We also need to make sure that the left shift does not
+ * overflow.
+ */
+ vrIsTrailingZeros = multipleOfPowerOf2(mv, q - 1);
+ }
+ }
+
+ /*
+ * Step 4: Find the shortest decimal representation in the interval of
+ * legal representations.
+ */
+ uint32 removed = 0;
+ uint8 lastRemovedDigit = 0;
+ uint64 output;
+
+ /* On average, we remove ~2 digits. */
+ if (vmIsTrailingZeros || vrIsTrailingZeros)
+ {
+ /* General case, which happens rarely (~0.7%). */
+ for (;;)
+ {
+ const uint64 vpDiv10 = div10(vp);
+ const uint64 vmDiv10 = div10(vm);
+
+ if (vpDiv10 <= vmDiv10)
+ break;
+
+ const uint32 vmMod10 = (uint32) (vm - 10 * vmDiv10);
+ const uint64 vrDiv10 = div10(vr);
+ const uint32 vrMod10 = (uint32) (vr - 10 * vrDiv10);
+
+ vmIsTrailingZeros &= vmMod10 == 0;
+ vrIsTrailingZeros &= lastRemovedDigit == 0;
+ lastRemovedDigit = (uint8) vrMod10;
+ vr = vrDiv10;
+ vp = vpDiv10;
+ vm = vmDiv10;
+ ++removed;
+ }
+
+ if (vmIsTrailingZeros)
+ {
+ for (;;)
+ {
+ const uint64 vmDiv10 = div10(vm);
+ const uint32 vmMod10 = (uint32) (vm - 10 * vmDiv10);
+
+ if (vmMod10 != 0)
+ break;
+
+ const uint64 vpDiv10 = div10(vp);
+ const uint64 vrDiv10 = div10(vr);
+ const uint32 vrMod10 = (uint32) (vr - 10 * vrDiv10);
+
+ vrIsTrailingZeros &= lastRemovedDigit == 0;
+ lastRemovedDigit = (uint8) vrMod10;
+ vr = vrDiv10;
+ vp = vpDiv10;
+ vm = vmDiv10;
+ ++removed;
+ }
+ }
+
+ if (vrIsTrailingZeros && lastRemovedDigit == 5 && vr % 2 == 0)
+ {
+ /* Round even if the exact number is .....50..0. */
+ lastRemovedDigit = 4;
+ }
+
+ /*
+ * We need to take vr + 1 if vr is outside bounds or we need to round
+ * up.
+ */
+ output = vr + ((vr == vm && (!acceptBounds || !vmIsTrailingZeros)) || lastRemovedDigit >= 5);
+ }
+ else
+ {
+ /*
+ * Specialized for the common case (~99.3%). Percentages below are
+ * relative to this.
+ */
+ bool roundUp = false;
+ const uint64 vpDiv100 = div100(vp);
+ const uint64 vmDiv100 = div100(vm);
+
+ if (vpDiv100 > vmDiv100)
+ {
+ /* Optimization:remove two digits at a time(~86.2 %). */
+ const uint64 vrDiv100 = div100(vr);
+ const uint32 vrMod100 = (uint32) (vr - 100 * vrDiv100);
+
+ roundUp = vrMod100 >= 50;
+ vr = vrDiv100;
+ vp = vpDiv100;
+ vm = vmDiv100;
+ removed += 2;
+ }
+
+ /*----
+ * Loop iterations below (approximately), without optimization
+ * above:
+ *
+ * 0: 0.03%, 1: 13.8%, 2: 70.6%, 3: 14.0%, 4: 1.40%, 5: 0.14%,
+ * 6+: 0.02%
+ *
+ * Loop iterations below (approximately), with optimization
+ * above:
+ *
+ * 0: 70.6%, 1: 27.8%, 2: 1.40%, 3: 0.14%, 4+: 0.02%
+ *----
+ */
+ for (;;)
+ {
+ const uint64 vpDiv10 = div10(vp);
+ const uint64 vmDiv10 = div10(vm);
+
+ if (vpDiv10 <= vmDiv10)
+ break;
+
+ const uint64 vrDiv10 = div10(vr);
+ const uint32 vrMod10 = (uint32) (vr - 10 * vrDiv10);
+
+ roundUp = vrMod10 >= 5;
+ vr = vrDiv10;
+ vp = vpDiv10;
+ vm = vmDiv10;
+ ++removed;
+ }
+
+ /*
+ * We need to take vr + 1 if vr is outside bounds or we need to round
+ * up.
+ */
+ output = vr + (vr == vm || roundUp);
+ }
+
+ const int32 exp = e10 + removed;
+
+ floating_decimal_64 fd;
+
+ fd.exponent = exp;
+ fd.mantissa = output;
+ return fd;
+}
+
+static inline int
+to_chars_df(const floating_decimal_64 v, const uint32 olength, char *const result)
+{
+ /* Step 5: Print the decimal representation. */
+ int index = 0;
+
+ uint64 output = v.mantissa;
+ int32 exp = v.exponent;
+
+ /*----
+ * On entry, mantissa * 10^exp is the result to be output.
+ * Caller has already done the - sign if needed.
+ *
+ * We want to insert the point somewhere depending on the output length
+ * and exponent, which might mean adding zeros:
+ *
+ * exp | format
+ * 1+ | ddddddddd000000
+ * 0 | ddddddddd
+ * -1 .. -len+1 | dddddddd.d to d.ddddddddd
+ * -len ... | 0.ddddddddd to 0.000dddddd
+ */
+ uint32 i = 0;
+ int32 nexp = exp + olength;
+
+ if (nexp <= 0)
+ {
+ /* -nexp is number of 0s to add after '.' */
+ Assert(nexp >= -3);
+ /* 0.000ddddd */
+ index = 2 - nexp;
+ /* won't need more than this many 0s */
+ memcpy(result, "0.000000", 8);
+ }
+ else if (exp < 0)
+ {
+ /*
+ * dddd.dddd; leave space at the start and move the '.' in after
+ */
+ index = 1;
+ }
+ else
+ {
+ /*
+ * We can save some code later by pre-filling with zeros. We know that
+ * there can be no more than 16 output digits in this form, otherwise
+ * we would not choose fixed-point output.
+ */
+ Assert(exp < 16 && exp + olength <= 16);
+ memset(result, '0', 16);
+ }
+
+ /*
+ * We prefer 32-bit operations, even on 64-bit platforms. We have at most
+ * 17 digits, and uint32 can store 9 digits. If output doesn't fit into
+ * uint32, we cut off 8 digits, so the rest will fit into uint32.
+ */
+ if ((output >> 32) != 0)
+ {
+ /* Expensive 64-bit division. */
+ const uint64 q = div1e8(output);
+ uint32 output2 = (uint32) (output - 100000000 * q);
+ const uint32 c = output2 % 10000;
+
+ output = q;
+ output2 /= 10000;
+
+ const uint32 d = output2 % 10000;
+ const uint32 c0 = (c % 100) << 1;
+ const uint32 c1 = (c / 100) << 1;
+ const uint32 d0 = (d % 100) << 1;
+ const uint32 d1 = (d / 100) << 1;
+
+ memcpy(result + index + olength - i - 2, DIGIT_TABLE + c0, 2);
+ memcpy(result + index + olength - i - 4, DIGIT_TABLE + c1, 2);
+ memcpy(result + index + olength - i - 6, DIGIT_TABLE + d0, 2);
+ memcpy(result + index + olength - i - 8, DIGIT_TABLE + d1, 2);
+ i += 8;
+ }
+
+ uint32 output2 = (uint32) output;
+
+ while (output2 >= 10000)
+ {
+ const uint32 c = output2 - 10000 * (output2 / 10000);
+ const uint32 c0 = (c % 100) << 1;
+ const uint32 c1 = (c / 100) << 1;
+
+ output2 /= 10000;
+ memcpy(result + index + olength - i - 2, DIGIT_TABLE + c0, 2);
+ memcpy(result + index + olength - i - 4, DIGIT_TABLE + c1, 2);
+ i += 4;
+ }
+ if (output2 >= 100)
+ {
+ const uint32 c = (output2 % 100) << 1;
+
+ output2 /= 100;
+ memcpy(result + index + olength - i - 2, DIGIT_TABLE + c, 2);
+ i += 2;
+ }
+ if (output2 >= 10)
+ {
+ const uint32 c = output2 << 1;
+
+ memcpy(result + index + olength - i - 2, DIGIT_TABLE + c, 2);
+ }
+ else
+ {
+ result[index] = (char) ('0' + output2);
+ }
+
+ if (index == 1)
+ {
+ /*
+ * nexp is 1..15 here, representing the number of digits before the
+ * point. A value of 16 is not possible because we switch to
+ * scientific notation when the display exponent reaches 15.
+ */
+ Assert(nexp < 16);
+ /* gcc only seems to want to optimize memmove for small 2^n */
+ if (nexp & 8)
+ {
+ memmove(result + index - 1, result + index, 8);
+ index += 8;
+ }
+ if (nexp & 4)
+ {
+ memmove(result + index - 1, result + index, 4);
+ index += 4;
+ }
+ if (nexp & 2)
+ {
+ memmove(result + index - 1, result + index, 2);
+ index += 2;
+ }
+ if (nexp & 1)
+ {
+ result[index - 1] = result[index];
+ }
+ result[nexp] = '.';
+ index = olength + 1;
+ }
+ else if (exp >= 0)
+ {
+ /* we supplied the trailing zeros earlier, now just set the length. */
+ index = olength + exp;
+ }
+ else
+ {
+ index = olength + (2 - nexp);
+ }
+
+ return index;
+}
+
+static inline int
+to_chars(floating_decimal_64 v, const bool sign, char *const result)
+{
+ /* Step 5: Print the decimal representation. */
+ int index = 0;
+
+ uint64 output = v.mantissa;
+ uint32 olength = decimalLength(output);
+ int32 exp = v.exponent + olength - 1;
+
+ if (sign)
+ {
+ result[index++] = '-';
+ }
+
+ /*
+ * The thresholds for fixed-point output are chosen to match printf
+ * defaults. Beware that both the code of to_chars_df and the value of
+ * DOUBLE_SHORTEST_DECIMAL_LEN are sensitive to these thresholds.
+ */
+ if (exp >= -4 && exp < 15)
+ return to_chars_df(v, olength, result + index) + sign;
+
+ /*
+ * If v.exponent is exactly 0, we might have reached here via the small
+ * integer fast path, in which case v.mantissa might contain trailing
+ * (decimal) zeros. For scientific notation we need to move these zeros
+ * into the exponent. (For fixed point this doesn't matter, which is why
+ * we do this here rather than above.)
+ *
+ * Since we already calculated the display exponent (exp) above based on
+ * the old decimal length, that value does not change here. Instead, we
+ * just reduce the display length for each digit removed.
+ *
+ * If we didn't get here via the fast path, the raw exponent will not
+ * usually be 0, and there will be no trailing zeros, so we pay no more
+ * than one div10/multiply extra cost. We claw back half of that by
+ * checking for divisibility by 2 before dividing by 10.
+ */
+ if (v.exponent == 0)
+ {
+ while ((output & 1) == 0)
+ {
+ const uint64 q = div10(output);
+ const uint32 r = (uint32) (output - 10 * q);
+
+ if (r != 0)
+ break;
+ output = q;
+ --olength;
+ }
+ }
+
+ /*----
+ * Print the decimal digits.
+ *
+ * The following code is equivalent to:
+ *
+ * for (uint32 i = 0; i < olength - 1; ++i) {
+ * const uint32 c = output % 10; output /= 10;
+ * result[index + olength - i] = (char) ('0' + c);
+ * }
+ * result[index] = '0' + output % 10;
+ *----
+ */
+
+ uint32 i = 0;
+
+ /*
+ * We prefer 32-bit operations, even on 64-bit platforms. We have at most
+ * 17 digits, and uint32 can store 9 digits. If output doesn't fit into
+ * uint32, we cut off 8 digits, so the rest will fit into uint32.
+ */
+ if ((output >> 32) != 0)
+ {
+ /* Expensive 64-bit division. */
+ const uint64 q = div1e8(output);
+ uint32 output2 = (uint32) (output - 100000000 * q);
+
+ output = q;
+
+ const uint32 c = output2 % 10000;
+
+ output2 /= 10000;
+
+ const uint32 d = output2 % 10000;
+ const uint32 c0 = (c % 100) << 1;
+ const uint32 c1 = (c / 100) << 1;
+ const uint32 d0 = (d % 100) << 1;
+ const uint32 d1 = (d / 100) << 1;
+
+ memcpy(result + index + olength - i - 1, DIGIT_TABLE + c0, 2);
+ memcpy(result + index + olength - i - 3, DIGIT_TABLE + c1, 2);
+ memcpy(result + index + olength - i - 5, DIGIT_TABLE + d0, 2);
+ memcpy(result + index + olength - i - 7, DIGIT_TABLE + d1, 2);
+ i += 8;
+ }
+
+ uint32 output2 = (uint32) output;
+
+ while (output2 >= 10000)
+ {
+ const uint32 c = output2 - 10000 * (output2 / 10000);
+
+ output2 /= 10000;
+
+ const uint32 c0 = (c % 100) << 1;
+ const uint32 c1 = (c / 100) << 1;
+
+ memcpy(result + index + olength - i - 1, DIGIT_TABLE + c0, 2);
+ memcpy(result + index + olength - i - 3, DIGIT_TABLE + c1, 2);
+ i += 4;
+ }
+ if (output2 >= 100)
+ {
+ const uint32 c = (output2 % 100) << 1;
+
+ output2 /= 100;
+ memcpy(result + index + olength - i - 1, DIGIT_TABLE + c, 2);
+ i += 2;
+ }
+ if (output2 >= 10)
+ {
+ const uint32 c = output2 << 1;
+
+ /*
+ * We can't use memcpy here: the decimal dot goes between these two
+ * digits.
+ */
+ result[index + olength - i] = DIGIT_TABLE[c + 1];
+ result[index] = DIGIT_TABLE[c];
+ }
+ else
+ {
+ result[index] = (char) ('0' + output2);
+ }
+
+ /* Print decimal point if needed. */
+ if (olength > 1)
+ {
+ result[index + 1] = '.';
+ index += olength + 1;
+ }
+ else
+ {
+ ++index;
+ }
+
+ /* Print the exponent. */
+ result[index++] = 'e';
+ if (exp < 0)
+ {
+ result[index++] = '-';
+ exp = -exp;
+ }
+ else
+ result[index++] = '+';
+
+ if (exp >= 100)
+ {
+ const int32 c = exp % 10;
+
+ memcpy(result + index, DIGIT_TABLE + 2 * (exp / 10), 2);
+ result[index + 2] = (char) ('0' + c);
+ index += 3;
+ }
+ else
+ {
+ memcpy(result + index, DIGIT_TABLE + 2 * exp, 2);
+ index += 2;
+ }
+
+ return index;
+}
+
+static inline bool
+d2d_small_int(const uint64 ieeeMantissa,
+ const uint32 ieeeExponent,
+ floating_decimal_64 *v)
+{
+ const int32 e2 = (int32) ieeeExponent - DOUBLE_BIAS - DOUBLE_MANTISSA_BITS;
+
+ /*
+ * Avoid using multiple "return false;" here since it tends to provoke the
+ * compiler into inlining multiple copies of d2d, which is undesirable.
+ */
+
+ if (e2 >= -DOUBLE_MANTISSA_BITS && e2 <= 0)
+ {
+ /*----
+ * Since 2^52 <= m2 < 2^53 and 0 <= -e2 <= 52:
+ * 1 <= f = m2 / 2^-e2 < 2^53.
+ *
+ * Test if the lower -e2 bits of the significand are 0, i.e. whether
+ * the fraction is 0. We can use ieeeMantissa here, since the implied
+ * 1 bit can never be tested by this; the implied 1 can only be part
+ * of a fraction if e2 < -DOUBLE_MANTISSA_BITS which we already
+ * checked. (e.g. 0.5 gives ieeeMantissa == 0 and e2 == -53)
+ */
+ const uint64 mask = (UINT64CONST(1) << -e2) - 1;
+ const uint64 fraction = ieeeMantissa & mask;
+
+ if (fraction == 0)
+ {
+ /*----
+ * f is an integer in the range [1, 2^53).
+ * Note: mantissa might contain trailing (decimal) 0's.
+ * Note: since 2^53 < 10^16, there is no need to adjust
+ * decimalLength().
+ */
+ const uint64 m2 = (UINT64CONST(1) << DOUBLE_MANTISSA_BITS) | ieeeMantissa;
+
+ v->mantissa = m2 >> -e2;
+ v->exponent = 0;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/*
+ * Store the shortest decimal representation of the given double as an
+ * UNTERMINATED string in the caller's supplied buffer (which must be at least
+ * DOUBLE_SHORTEST_DECIMAL_LEN-1 bytes long).
+ *
+ * Returns the number of bytes stored.
+ */
+int
+double_to_shortest_decimal_bufn(double f, char *result)
+{
+ /*
+ * Step 1: Decode the floating-point number, and unify normalized and
+ * subnormal cases.
+ */
+ const uint64 bits = double_to_bits(f);
+
+ /* Decode bits into sign, mantissa, and exponent. */
+ const bool ieeeSign = ((bits >> (DOUBLE_MANTISSA_BITS + DOUBLE_EXPONENT_BITS)) & 1) != 0;
+ const uint64 ieeeMantissa = bits & ((UINT64CONST(1) << DOUBLE_MANTISSA_BITS) - 1);
+ const uint32 ieeeExponent = (uint32) ((bits >> DOUBLE_MANTISSA_BITS) & ((1u << DOUBLE_EXPONENT_BITS) - 1));
+
+ /* Case distinction; exit early for the easy cases. */
+ if (ieeeExponent == ((1u << DOUBLE_EXPONENT_BITS) - 1u) || (ieeeExponent == 0 && ieeeMantissa == 0))
+ {
+ return copy_special_str(result, ieeeSign, (ieeeExponent != 0), (ieeeMantissa != 0));
+ }
+
+ floating_decimal_64 v;
+ const bool isSmallInt = d2d_small_int(ieeeMantissa, ieeeExponent, &v);
+
+ if (!isSmallInt)
+ {
+ v = d2d(ieeeMantissa, ieeeExponent);
+ }
+
+ return to_chars(v, ieeeSign, result);
+}
+
+/*
+ * Store the shortest decimal representation of the given double as a
+ * null-terminated string in the caller's supplied buffer (which must be at
+ * least DOUBLE_SHORTEST_DECIMAL_LEN bytes long).
+ *
+ * Returns the string length.
+ */
+int
+double_to_shortest_decimal_buf(double f, char *result)
+{
+ const int index = double_to_shortest_decimal_bufn(f, result);
+
+ /* Terminate the string. */
+ Assert(index < DOUBLE_SHORTEST_DECIMAL_LEN);
+ result[index] = '\0';
+ return index;
+}
+
+/*
+ * Return the shortest decimal representation as a null-terminated palloc'd
+ * string (outside the backend, uses malloc() instead).
+ *
+ * Caller is responsible for freeing the result.
+ */
+char *
+double_to_shortest_decimal(double f)
+{
+ char *const result = (char *) palloc(DOUBLE_SHORTEST_DECIMAL_LEN);
+
+ double_to_shortest_decimal_buf(f, result);
+ return result;
+}
diff --git a/contrib/libs/libpq/src/common/d2s_full_table.h b/contrib/libs/libpq/src/common/d2s_full_table.h
new file mode 100644
index 0000000000..23f5e9a45e
--- /dev/null
+++ b/contrib/libs/libpq/src/common/d2s_full_table.h
@@ -0,0 +1,358 @@
+/*---------------------------------------------------------------------------
+ *
+ * Ryu floating-point output for double precision.
+ *
+ * Portions Copyright (c) 2018-2023, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/common/d2s_full_table.h
+ *
+ * This is a modification of code taken from github.com/ulfjack/ryu under the
+ * terms of the Boost license (not the Apache license). The original copyright
+ * notice follows:
+ *
+ * Copyright 2018 Ulf Adams
+ *
+ * The contents of this file may be used under the terms of the Apache
+ * License, Version 2.0.
+ *
+ * (See accompanying file LICENSE-Apache or copy at
+ * http://www.apache.org/licenses/LICENSE-2.0)
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * Boost Software License, Version 1.0.
+ *
+ * (See accompanying file LICENSE-Boost or copy at
+ * https://www.boost.org/LICENSE_1_0.txt)
+ *
+ * Unless required by applicable law or agreed to in writing, this software is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+#ifndef RYU_D2S_FULL_TABLE_H
+#define RYU_D2S_FULL_TABLE_H
+
+/*
+ * These tables are generated (by the upstream) using PrintDoubleLookupTable
+ * from the upstream sources at github.com/ulfjack/ryu, and then modified (by
+ * us) by adding UINT64CONST.
+ */
+static const uint64 DOUBLE_POW5_INV_SPLIT[292][2] = {
+ {UINT64CONST(1), UINT64CONST(288230376151711744)}, {UINT64CONST(3689348814741910324), UINT64CONST(230584300921369395)},
+ {UINT64CONST(2951479051793528259), UINT64CONST(184467440737095516)}, {UINT64CONST(17118578500402463900), UINT64CONST(147573952589676412)},
+ {UINT64CONST(12632330341676300947), UINT64CONST(236118324143482260)}, {UINT64CONST(10105864273341040758), UINT64CONST(188894659314785808)},
+ {UINT64CONST(15463389048156653253), UINT64CONST(151115727451828646)}, {UINT64CONST(17362724847566824558), UINT64CONST(241785163922925834)},
+ {UINT64CONST(17579528692795369969), UINT64CONST(193428131138340667)}, {UINT64CONST(6684925324752475329), UINT64CONST(154742504910672534)},
+ {UINT64CONST(18074578149087781173), UINT64CONST(247588007857076054)}, {UINT64CONST(18149011334012135262), UINT64CONST(198070406285660843)},
+ {UINT64CONST(3451162622983977240), UINT64CONST(158456325028528675)}, {UINT64CONST(5521860196774363583), UINT64CONST(253530120045645880)},
+ {UINT64CONST(4417488157419490867), UINT64CONST(202824096036516704)}, {UINT64CONST(7223339340677503017), UINT64CONST(162259276829213363)},
+ {UINT64CONST(7867994130342094503), UINT64CONST(259614842926741381)}, {UINT64CONST(2605046489531765280), UINT64CONST(207691874341393105)},
+ {UINT64CONST(2084037191625412224), UINT64CONST(166153499473114484)}, {UINT64CONST(10713157136084480204), UINT64CONST(265845599156983174)},
+ {UINT64CONST(12259874523609494487), UINT64CONST(212676479325586539)}, {UINT64CONST(13497248433629505913), UINT64CONST(170141183460469231)},
+ {UINT64CONST(14216899864323388813), UINT64CONST(272225893536750770)}, {UINT64CONST(11373519891458711051), UINT64CONST(217780714829400616)},
+ {UINT64CONST(5409467098425058518), UINT64CONST(174224571863520493)}, {UINT64CONST(4965798542738183305), UINT64CONST(278759314981632789)},
+ {UINT64CONST(7661987648932456967), UINT64CONST(223007451985306231)}, {UINT64CONST(2440241304404055250), UINT64CONST(178405961588244985)},
+ {UINT64CONST(3904386087046488400), UINT64CONST(285449538541191976)}, {UINT64CONST(17880904128604832013), UINT64CONST(228359630832953580)},
+ {UINT64CONST(14304723302883865611), UINT64CONST(182687704666362864)}, {UINT64CONST(15133127457049002812), UINT64CONST(146150163733090291)},
+ {UINT64CONST(16834306301794583852), UINT64CONST(233840261972944466)}, {UINT64CONST(9778096226693756759), UINT64CONST(187072209578355573)},
+ {UINT64CONST(15201174610838826053), UINT64CONST(149657767662684458)}, {UINT64CONST(2185786488890659746), UINT64CONST(239452428260295134)},
+ {UINT64CONST(5437978005854438120), UINT64CONST(191561942608236107)}, {UINT64CONST(15418428848909281466), UINT64CONST(153249554086588885)},
+ {UINT64CONST(6222742084545298729), UINT64CONST(245199286538542217)}, {UINT64CONST(16046240111861969953), UINT64CONST(196159429230833773)},
+ {UINT64CONST(1768945645263844993), UINT64CONST(156927543384667019)}, {UINT64CONST(10209010661905972635), UINT64CONST(251084069415467230)},
+ {UINT64CONST(8167208529524778108), UINT64CONST(200867255532373784)}, {UINT64CONST(10223115638361732810), UINT64CONST(160693804425899027)},
+ {UINT64CONST(1599589762411131202), UINT64CONST(257110087081438444)}, {UINT64CONST(4969020624670815285), UINT64CONST(205688069665150755)},
+ {UINT64CONST(3975216499736652228), UINT64CONST(164550455732120604)}, {UINT64CONST(13739044029062464211), UINT64CONST(263280729171392966)},
+ {UINT64CONST(7301886408508061046), UINT64CONST(210624583337114373)}, {UINT64CONST(13220206756290269483), UINT64CONST(168499666669691498)},
+ {UINT64CONST(17462981995322520850), UINT64CONST(269599466671506397)}, {UINT64CONST(6591687966774196033), UINT64CONST(215679573337205118)},
+ {UINT64CONST(12652048002903177473), UINT64CONST(172543658669764094)}, {UINT64CONST(9175230360419352987), UINT64CONST(276069853871622551)},
+ {UINT64CONST(3650835473593572067), UINT64CONST(220855883097298041)}, {UINT64CONST(17678063637842498946), UINT64CONST(176684706477838432)},
+ {UINT64CONST(13527506561580357021), UINT64CONST(282695530364541492)}, {UINT64CONST(3443307619780464970), UINT64CONST(226156424291633194)},
+ {UINT64CONST(6443994910566282300), UINT64CONST(180925139433306555)}, {UINT64CONST(5155195928453025840), UINT64CONST(144740111546645244)},
+ {UINT64CONST(15627011115008661990), UINT64CONST(231584178474632390)}, {UINT64CONST(12501608892006929592), UINT64CONST(185267342779705912)},
+ {UINT64CONST(2622589484121723027), UINT64CONST(148213874223764730)}, {UINT64CONST(4196143174594756843), UINT64CONST(237142198758023568)},
+ {UINT64CONST(10735612169159626121), UINT64CONST(189713759006418854)}, {UINT64CONST(12277838550069611220), UINT64CONST(151771007205135083)},
+ {UINT64CONST(15955192865369467629), UINT64CONST(242833611528216133)}, {UINT64CONST(1696107848069843133), UINT64CONST(194266889222572907)},
+ {UINT64CONST(12424932722681605476), UINT64CONST(155413511378058325)}, {UINT64CONST(1433148282581017146), UINT64CONST(248661618204893321)},
+ {UINT64CONST(15903913885032455010), UINT64CONST(198929294563914656)}, {UINT64CONST(9033782293284053685), UINT64CONST(159143435651131725)},
+ {UINT64CONST(14454051669254485895), UINT64CONST(254629497041810760)}, {UINT64CONST(11563241335403588716), UINT64CONST(203703597633448608)},
+ {UINT64CONST(16629290697806691620), UINT64CONST(162962878106758886)}, {UINT64CONST(781423413297334329), UINT64CONST(260740604970814219)},
+ {UINT64CONST(4314487545379777786), UINT64CONST(208592483976651375)}, {UINT64CONST(3451590036303822229), UINT64CONST(166873987181321100)},
+ {UINT64CONST(5522544058086115566), UINT64CONST(266998379490113760)}, {UINT64CONST(4418035246468892453), UINT64CONST(213598703592091008)},
+ {UINT64CONST(10913125826658934609), UINT64CONST(170878962873672806)}, {UINT64CONST(10082303693170474728), UINT64CONST(273406340597876490)},
+ {UINT64CONST(8065842954536379782), UINT64CONST(218725072478301192)}, {UINT64CONST(17520720807854834795), UINT64CONST(174980057982640953)},
+ {UINT64CONST(5897060404116273733), UINT64CONST(279968092772225526)}, {UINT64CONST(1028299508551108663), UINT64CONST(223974474217780421)},
+ {UINT64CONST(15580034865808528224), UINT64CONST(179179579374224336)}, {UINT64CONST(17549358155809824511), UINT64CONST(286687326998758938)},
+ {UINT64CONST(2971440080422128639), UINT64CONST(229349861599007151)}, {UINT64CONST(17134547323305344204), UINT64CONST(183479889279205720)},
+ {UINT64CONST(13707637858644275364), UINT64CONST(146783911423364576)}, {UINT64CONST(14553522944347019935), UINT64CONST(234854258277383322)},
+ {UINT64CONST(4264120725993795302), UINT64CONST(187883406621906658)}, {UINT64CONST(10789994210278856888), UINT64CONST(150306725297525326)},
+ {UINT64CONST(9885293106962350374), UINT64CONST(240490760476040522)}, {UINT64CONST(529536856086059653), UINT64CONST(192392608380832418)},
+ {UINT64CONST(7802327114352668369), UINT64CONST(153914086704665934)}, {UINT64CONST(1415676938738538420), UINT64CONST(246262538727465495)},
+ {UINT64CONST(1132541550990830736), UINT64CONST(197010030981972396)}, {UINT64CONST(15663428499760305882), UINT64CONST(157608024785577916)},
+ {UINT64CONST(17682787970132668764), UINT64CONST(252172839656924666)}, {UINT64CONST(10456881561364224688), UINT64CONST(201738271725539733)},
+ {UINT64CONST(15744202878575200397), UINT64CONST(161390617380431786)}, {UINT64CONST(17812026976236499989), UINT64CONST(258224987808690858)},
+ {UINT64CONST(3181575136763469022), UINT64CONST(206579990246952687)}, {UINT64CONST(13613306553636506187), UINT64CONST(165263992197562149)},
+ {UINT64CONST(10713244041592678929), UINT64CONST(264422387516099439)}, {UINT64CONST(12259944048016053467), UINT64CONST(211537910012879551)},
+ {UINT64CONST(6118606423670932450), UINT64CONST(169230328010303641)}, {UINT64CONST(2411072648389671274), UINT64CONST(270768524816485826)},
+ {UINT64CONST(16686253377679378312), UINT64CONST(216614819853188660)}, {UINT64CONST(13349002702143502650), UINT64CONST(173291855882550928)},
+ {UINT64CONST(17669055508687693916), UINT64CONST(277266969412081485)}, {UINT64CONST(14135244406950155133), UINT64CONST(221813575529665188)},
+ {UINT64CONST(240149081334393137), UINT64CONST(177450860423732151)}, {UINT64CONST(11452284974360759988), UINT64CONST(283921376677971441)},
+ {UINT64CONST(5472479164746697667), UINT64CONST(227137101342377153)}, {UINT64CONST(11756680961281178780), UINT64CONST(181709681073901722)},
+ {UINT64CONST(2026647139541122378), UINT64CONST(145367744859121378)}, {UINT64CONST(18000030682233437097), UINT64CONST(232588391774594204)},
+ {UINT64CONST(18089373360528660001), UINT64CONST(186070713419675363)}, {UINT64CONST(3403452244197197031), UINT64CONST(148856570735740291)},
+ {UINT64CONST(16513570034941246220), UINT64CONST(238170513177184465)}, {UINT64CONST(13210856027952996976), UINT64CONST(190536410541747572)},
+ {UINT64CONST(3189987192878576934), UINT64CONST(152429128433398058)}, {UINT64CONST(1414630693863812771), UINT64CONST(243886605493436893)},
+ {UINT64CONST(8510402184574870864), UINT64CONST(195109284394749514)}, {UINT64CONST(10497670562401807014), UINT64CONST(156087427515799611)},
+ {UINT64CONST(9417575270359070576), UINT64CONST(249739884025279378)}, {UINT64CONST(14912757845771077107), UINT64CONST(199791907220223502)},
+ {UINT64CONST(4551508647133041040), UINT64CONST(159833525776178802)}, {UINT64CONST(10971762650154775986), UINT64CONST(255733641241886083)},
+ {UINT64CONST(16156107749607641435), UINT64CONST(204586912993508866)}, {UINT64CONST(9235537384944202825), UINT64CONST(163669530394807093)},
+ {UINT64CONST(11087511001168814197), UINT64CONST(261871248631691349)}, {UINT64CONST(12559357615676961681), UINT64CONST(209496998905353079)},
+ {UINT64CONST(13736834907283479668), UINT64CONST(167597599124282463)}, {UINT64CONST(18289587036911657145), UINT64CONST(268156158598851941)},
+ {UINT64CONST(10942320814787415393), UINT64CONST(214524926879081553)}, {UINT64CONST(16132554281313752961), UINT64CONST(171619941503265242)},
+ {UINT64CONST(11054691591134363444), UINT64CONST(274591906405224388)}, {UINT64CONST(16222450902391311402), UINT64CONST(219673525124179510)},
+ {UINT64CONST(12977960721913049122), UINT64CONST(175738820099343608)}, {UINT64CONST(17075388340318968271), UINT64CONST(281182112158949773)},
+ {UINT64CONST(2592264228029443648), UINT64CONST(224945689727159819)}, {UINT64CONST(5763160197165465241), UINT64CONST(179956551781727855)},
+ {UINT64CONST(9221056315464744386), UINT64CONST(287930482850764568)}, {UINT64CONST(14755542681855616155), UINT64CONST(230344386280611654)},
+ {UINT64CONST(15493782960226403247), UINT64CONST(184275509024489323)}, {UINT64CONST(1326979923955391628), UINT64CONST(147420407219591459)},
+ {UINT64CONST(9501865507812447252), UINT64CONST(235872651551346334)}, {UINT64CONST(11290841220991868125), UINT64CONST(188698121241077067)},
+ {UINT64CONST(1653975347309673853), UINT64CONST(150958496992861654)}, {UINT64CONST(10025058185179298811), UINT64CONST(241533595188578646)},
+ {UINT64CONST(4330697733401528726), UINT64CONST(193226876150862917)}, {UINT64CONST(14532604630946953951), UINT64CONST(154581500920690333)},
+ {UINT64CONST(1116074521063664381), UINT64CONST(247330401473104534)}, {UINT64CONST(4582208431592841828), UINT64CONST(197864321178483627)},
+ {UINT64CONST(14733813189500004432), UINT64CONST(158291456942786901)}, {UINT64CONST(16195403473716186445), UINT64CONST(253266331108459042)},
+ {UINT64CONST(5577625149489128510), UINT64CONST(202613064886767234)}, {UINT64CONST(8151448934333213131), UINT64CONST(162090451909413787)},
+ {UINT64CONST(16731667109675051333), UINT64CONST(259344723055062059)}, {UINT64CONST(17074682502481951390), UINT64CONST(207475778444049647)},
+ {UINT64CONST(6281048372501740465), UINT64CONST(165980622755239718)}, {UINT64CONST(6360328581260874421), UINT64CONST(265568996408383549)},
+ {UINT64CONST(8777611679750609860), UINT64CONST(212455197126706839)}, {UINT64CONST(10711438158542398211), UINT64CONST(169964157701365471)},
+ {UINT64CONST(9759603424184016492), UINT64CONST(271942652322184754)}, {UINT64CONST(11497031554089123517), UINT64CONST(217554121857747803)},
+ {UINT64CONST(16576322872755119460), UINT64CONST(174043297486198242)}, {UINT64CONST(11764721337440549842), UINT64CONST(278469275977917188)},
+ {UINT64CONST(16790474699436260520), UINT64CONST(222775420782333750)}, {UINT64CONST(13432379759549008416), UINT64CONST(178220336625867000)},
+ {UINT64CONST(3045063541568861850), UINT64CONST(285152538601387201)}, {UINT64CONST(17193446092222730773), UINT64CONST(228122030881109760)},
+ {UINT64CONST(13754756873778184618), UINT64CONST(182497624704887808)}, {UINT64CONST(18382503128506368341), UINT64CONST(145998099763910246)},
+ {UINT64CONST(3586563302416817083), UINT64CONST(233596959622256395)}, {UINT64CONST(2869250641933453667), UINT64CONST(186877567697805116)},
+ {UINT64CONST(17052795772514404226), UINT64CONST(149502054158244092)}, {UINT64CONST(12527077977055405469), UINT64CONST(239203286653190548)},
+ {UINT64CONST(17400360011128145022), UINT64CONST(191362629322552438)}, {UINT64CONST(2852241564676785048), UINT64CONST(153090103458041951)},
+ {UINT64CONST(15631632947708587046), UINT64CONST(244944165532867121)}, {UINT64CONST(8815957543424959314), UINT64CONST(195955332426293697)},
+ {UINT64CONST(18120812478965698421), UINT64CONST(156764265941034957)}, {UINT64CONST(14235904707377476180), UINT64CONST(250822825505655932)},
+ {UINT64CONST(4010026136418160298), UINT64CONST(200658260404524746)}, {UINT64CONST(17965416168102169531), UINT64CONST(160526608323619796)},
+ {UINT64CONST(2919224165770098987), UINT64CONST(256842573317791675)}, {UINT64CONST(2335379332616079190), UINT64CONST(205474058654233340)},
+ {UINT64CONST(1868303466092863352), UINT64CONST(164379246923386672)}, {UINT64CONST(6678634360490491686), UINT64CONST(263006795077418675)},
+ {UINT64CONST(5342907488392393349), UINT64CONST(210405436061934940)}, {UINT64CONST(4274325990713914679), UINT64CONST(168324348849547952)},
+ {UINT64CONST(10528270399884173809), UINT64CONST(269318958159276723)}, {UINT64CONST(15801313949391159694), UINT64CONST(215455166527421378)},
+ {UINT64CONST(1573004715287196786), UINT64CONST(172364133221937103)}, {UINT64CONST(17274202803427156150), UINT64CONST(275782613155099364)},
+ {UINT64CONST(17508711057483635243), UINT64CONST(220626090524079491)}, {UINT64CONST(10317620031244997871), UINT64CONST(176500872419263593)},
+ {UINT64CONST(12818843235250086271), UINT64CONST(282401395870821749)}, {UINT64CONST(13944423402941979340), UINT64CONST(225921116696657399)},
+ {UINT64CONST(14844887537095493795), UINT64CONST(180736893357325919)}, {UINT64CONST(15565258844418305359), UINT64CONST(144589514685860735)},
+ {UINT64CONST(6457670077359736959), UINT64CONST(231343223497377177)}, {UINT64CONST(16234182506113520537), UINT64CONST(185074578797901741)},
+ {UINT64CONST(9297997190148906106), UINT64CONST(148059663038321393)}, {UINT64CONST(11187446689496339446), UINT64CONST(236895460861314229)},
+ {UINT64CONST(12639306166338981880), UINT64CONST(189516368689051383)}, {UINT64CONST(17490142562555006151), UINT64CONST(151613094951241106)},
+ {UINT64CONST(2158786396894637579), UINT64CONST(242580951921985771)}, {UINT64CONST(16484424376483351356), UINT64CONST(194064761537588616)},
+ {UINT64CONST(9498190686444770762), UINT64CONST(155251809230070893)}, {UINT64CONST(11507756283569722895), UINT64CONST(248402894768113429)},
+ {UINT64CONST(12895553841597688639), UINT64CONST(198722315814490743)}, {UINT64CONST(17695140702761971558), UINT64CONST(158977852651592594)},
+ {UINT64CONST(17244178680193423523), UINT64CONST(254364564242548151)}, {UINT64CONST(10105994129412828495), UINT64CONST(203491651394038521)},
+ {UINT64CONST(4395446488788352473), UINT64CONST(162793321115230817)}, {UINT64CONST(10722063196803274280), UINT64CONST(260469313784369307)},
+ {UINT64CONST(1198952927958798777), UINT64CONST(208375451027495446)}, {UINT64CONST(15716557601334680315), UINT64CONST(166700360821996356)},
+ {UINT64CONST(17767794532651667857), UINT64CONST(266720577315194170)}, {UINT64CONST(14214235626121334286), UINT64CONST(213376461852155336)},
+ {UINT64CONST(7682039686155157106), UINT64CONST(170701169481724269)}, {UINT64CONST(1223217053622520399), UINT64CONST(273121871170758831)},
+ {UINT64CONST(15735968901865657612), UINT64CONST(218497496936607064)}, {UINT64CONST(16278123936234436413), UINT64CONST(174797997549285651)},
+ {UINT64CONST(219556594781725998), UINT64CONST(279676796078857043)}, {UINT64CONST(7554342905309201445), UINT64CONST(223741436863085634)},
+ {UINT64CONST(9732823138989271479), UINT64CONST(178993149490468507)}, {UINT64CONST(815121763415193074), UINT64CONST(286389039184749612)},
+ {UINT64CONST(11720143854957885429), UINT64CONST(229111231347799689)}, {UINT64CONST(13065463898708218666), UINT64CONST(183288985078239751)},
+ {UINT64CONST(6763022304224664610), UINT64CONST(146631188062591801)}, {UINT64CONST(3442138057275642729), UINT64CONST(234609900900146882)},
+ {UINT64CONST(13821756890046245153), UINT64CONST(187687920720117505)}, {UINT64CONST(11057405512036996122), UINT64CONST(150150336576094004)},
+ {UINT64CONST(6623802375033462826), UINT64CONST(240240538521750407)}, {UINT64CONST(16367088344252501231), UINT64CONST(192192430817400325)},
+ {UINT64CONST(13093670675402000985), UINT64CONST(153753944653920260)}, {UINT64CONST(2503129006933649959), UINT64CONST(246006311446272417)},
+ {UINT64CONST(13070549649772650937), UINT64CONST(196805049157017933)}, {UINT64CONST(17835137349301941396), UINT64CONST(157444039325614346)},
+ {UINT64CONST(2710778055689733971), UINT64CONST(251910462920982955)}, {UINT64CONST(2168622444551787177), UINT64CONST(201528370336786364)},
+ {UINT64CONST(5424246770383340065), UINT64CONST(161222696269429091)}, {UINT64CONST(1300097203129523457), UINT64CONST(257956314031086546)},
+ {UINT64CONST(15797473021471260058), UINT64CONST(206365051224869236)}, {UINT64CONST(8948629602435097724), UINT64CONST(165092040979895389)},
+ {UINT64CONST(3249760919670425388), UINT64CONST(264147265567832623)}, {UINT64CONST(9978506365220160957), UINT64CONST(211317812454266098)},
+ {UINT64CONST(15361502721659949412), UINT64CONST(169054249963412878)}, {UINT64CONST(2442311466204457120), UINT64CONST(270486799941460606)},
+ {UINT64CONST(16711244431931206989), UINT64CONST(216389439953168484)}, {UINT64CONST(17058344360286875914), UINT64CONST(173111551962534787)},
+ {UINT64CONST(12535955717491360170), UINT64CONST(276978483140055660)}, {UINT64CONST(10028764573993088136), UINT64CONST(221582786512044528)},
+ {UINT64CONST(15401709288678291155), UINT64CONST(177266229209635622)}, {UINT64CONST(9885339602917624555), UINT64CONST(283625966735416996)},
+ {UINT64CONST(4218922867592189321), UINT64CONST(226900773388333597)}, {UINT64CONST(14443184738299482427), UINT64CONST(181520618710666877)},
+ {UINT64CONST(4175850161155765295), UINT64CONST(145216494968533502)}, {UINT64CONST(10370709072591134795), UINT64CONST(232346391949653603)},
+ {UINT64CONST(15675264887556728482), UINT64CONST(185877113559722882)}, {UINT64CONST(5161514280561562140), UINT64CONST(148701690847778306)},
+ {UINT64CONST(879725219414678777), UINT64CONST(237922705356445290)}, {UINT64CONST(703780175531743021), UINT64CONST(190338164285156232)},
+ {UINT64CONST(11631070584651125387), UINT64CONST(152270531428124985)}, {UINT64CONST(162968861732249003), UINT64CONST(243632850284999977)},
+ {UINT64CONST(11198421533611530172), UINT64CONST(194906280227999981)}, {UINT64CONST(5269388412147313814), UINT64CONST(155925024182399985)},
+ {UINT64CONST(8431021459435702103), UINT64CONST(249480038691839976)}, {UINT64CONST(3055468352806651359), UINT64CONST(199584030953471981)},
+ {UINT64CONST(17201769941212962380), UINT64CONST(159667224762777584)}, {UINT64CONST(16454785461715008838), UINT64CONST(255467559620444135)},
+ {UINT64CONST(13163828369372007071), UINT64CONST(204374047696355308)}, {UINT64CONST(17909760324981426303), UINT64CONST(163499238157084246)},
+ {UINT64CONST(2830174816776909822), UINT64CONST(261598781051334795)}, {UINT64CONST(2264139853421527858), UINT64CONST(209279024841067836)},
+ {UINT64CONST(16568707141704863579), UINT64CONST(167423219872854268)}, {UINT64CONST(4373838538276319787), UINT64CONST(267877151796566830)},
+ {UINT64CONST(3499070830621055830), UINT64CONST(214301721437253464)}, {UINT64CONST(6488605479238754987), UINT64CONST(171441377149802771)},
+ {UINT64CONST(3003071137298187333), UINT64CONST(274306203439684434)}, {UINT64CONST(6091805724580460189), UINT64CONST(219444962751747547)},
+ {UINT64CONST(15941491023890099121), UINT64CONST(175555970201398037)}, {UINT64CONST(10748990379256517301), UINT64CONST(280889552322236860)},
+ {UINT64CONST(8599192303405213841), UINT64CONST(224711641857789488)}, {UINT64CONST(14258051472207991719), UINT64CONST(179769313486231590)}
+};
+
+static const uint64 DOUBLE_POW5_SPLIT[326][2] = {
+ {UINT64CONST(0), UINT64CONST(72057594037927936)}, {UINT64CONST(0), UINT64CONST(90071992547409920)},
+ {UINT64CONST(0), UINT64CONST(112589990684262400)}, {UINT64CONST(0), UINT64CONST(140737488355328000)},
+ {UINT64CONST(0), UINT64CONST(87960930222080000)}, {UINT64CONST(0), UINT64CONST(109951162777600000)},
+ {UINT64CONST(0), UINT64CONST(137438953472000000)}, {UINT64CONST(0), UINT64CONST(85899345920000000)},
+ {UINT64CONST(0), UINT64CONST(107374182400000000)}, {UINT64CONST(0), UINT64CONST(134217728000000000)},
+ {UINT64CONST(0), UINT64CONST(83886080000000000)}, {UINT64CONST(0), UINT64CONST(104857600000000000)},
+ {UINT64CONST(0), UINT64CONST(131072000000000000)}, {UINT64CONST(0), UINT64CONST(81920000000000000)},
+ {UINT64CONST(0), UINT64CONST(102400000000000000)}, {UINT64CONST(0), UINT64CONST(128000000000000000)},
+ {UINT64CONST(0), UINT64CONST(80000000000000000)}, {UINT64CONST(0), UINT64CONST(100000000000000000)},
+ {UINT64CONST(0), UINT64CONST(125000000000000000)}, {UINT64CONST(0), UINT64CONST(78125000000000000)},
+ {UINT64CONST(0), UINT64CONST(97656250000000000)}, {UINT64CONST(0), UINT64CONST(122070312500000000)},
+ {UINT64CONST(0), UINT64CONST(76293945312500000)}, {UINT64CONST(0), UINT64CONST(95367431640625000)},
+ {UINT64CONST(0), UINT64CONST(119209289550781250)}, {UINT64CONST(4611686018427387904), UINT64CONST(74505805969238281)},
+ {UINT64CONST(10376293541461622784), UINT64CONST(93132257461547851)}, {UINT64CONST(8358680908399640576), UINT64CONST(116415321826934814)},
+ {UINT64CONST(612489549322387456), UINT64CONST(72759576141834259)}, {UINT64CONST(14600669991935148032), UINT64CONST(90949470177292823)},
+ {UINT64CONST(13639151471491547136), UINT64CONST(113686837721616029)}, {UINT64CONST(3213881284082270208), UINT64CONST(142108547152020037)},
+ {UINT64CONST(4314518811765112832), UINT64CONST(88817841970012523)}, {UINT64CONST(781462496279003136), UINT64CONST(111022302462515654)},
+ {UINT64CONST(10200200157203529728), UINT64CONST(138777878078144567)}, {UINT64CONST(13292654125893287936), UINT64CONST(86736173798840354)},
+ {UINT64CONST(7392445620511834112), UINT64CONST(108420217248550443)}, {UINT64CONST(4628871007212404736), UINT64CONST(135525271560688054)},
+ {UINT64CONST(16728102434789916672), UINT64CONST(84703294725430033)}, {UINT64CONST(7075069988205232128), UINT64CONST(105879118406787542)},
+ {UINT64CONST(18067209522111315968), UINT64CONST(132348898008484427)}, {UINT64CONST(8986162942105878528), UINT64CONST(82718061255302767)},
+ {UINT64CONST(6621017659204960256), UINT64CONST(103397576569128459)}, {UINT64CONST(3664586055578812416), UINT64CONST(129246970711410574)},
+ {UINT64CONST(16125424340018921472), UINT64CONST(80779356694631608)}, {UINT64CONST(1710036351314100224), UINT64CONST(100974195868289511)},
+ {UINT64CONST(15972603494424788992), UINT64CONST(126217744835361888)}, {UINT64CONST(9982877184015493120), UINT64CONST(78886090522101180)},
+ {UINT64CONST(12478596480019366400), UINT64CONST(98607613152626475)}, {UINT64CONST(10986559581596820096), UINT64CONST(123259516440783094)},
+ {UINT64CONST(2254913720070624656), UINT64CONST(77037197775489434)}, {UINT64CONST(12042014186943056628), UINT64CONST(96296497219361792)},
+ {UINT64CONST(15052517733678820785), UINT64CONST(120370621524202240)}, {UINT64CONST(9407823583549262990), UINT64CONST(75231638452626400)},
+ {UINT64CONST(11759779479436578738), UINT64CONST(94039548065783000)}, {UINT64CONST(14699724349295723422), UINT64CONST(117549435082228750)},
+ {UINT64CONST(4575641699882439235), UINT64CONST(73468396926392969)}, {UINT64CONST(10331238143280436948), UINT64CONST(91835496157991211)},
+ {UINT64CONST(8302361660673158281), UINT64CONST(114794370197489014)}, {UINT64CONST(1154580038986672043), UINT64CONST(143492962746861268)},
+ {UINT64CONST(9944984561221445835), UINT64CONST(89683101716788292)}, {UINT64CONST(12431230701526807293), UINT64CONST(112103877145985365)},
+ {UINT64CONST(1703980321626345405), UINT64CONST(140129846432481707)}, {UINT64CONST(17205888765512323542), UINT64CONST(87581154020301066)},
+ {UINT64CONST(12283988920035628619), UINT64CONST(109476442525376333)}, {UINT64CONST(1519928094762372062), UINT64CONST(136845553156720417)},
+ {UINT64CONST(12479170105294952299), UINT64CONST(85528470722950260)}, {UINT64CONST(15598962631618690374), UINT64CONST(106910588403687825)},
+ {UINT64CONST(5663645234241199255), UINT64CONST(133638235504609782)}, {UINT64CONST(17374836326682913246), UINT64CONST(83523897190381113)},
+ {UINT64CONST(7883487353071477846), UINT64CONST(104404871487976392)}, {UINT64CONST(9854359191339347308), UINT64CONST(130506089359970490)},
+ {UINT64CONST(10770660513014479971), UINT64CONST(81566305849981556)}, {UINT64CONST(13463325641268099964), UINT64CONST(101957882312476945)},
+ {UINT64CONST(2994098996302961243), UINT64CONST(127447352890596182)}, {UINT64CONST(15706369927971514489), UINT64CONST(79654595556622613)},
+ {UINT64CONST(5797904354682229399), UINT64CONST(99568244445778267)}, {UINT64CONST(2635694424925398845), UINT64CONST(124460305557222834)},
+ {UINT64CONST(6258995034005762182), UINT64CONST(77787690973264271)}, {UINT64CONST(3212057774079814824), UINT64CONST(97234613716580339)},
+ {UINT64CONST(17850130272881932242), UINT64CONST(121543267145725423)}, {UINT64CONST(18073860448192289507), UINT64CONST(75964541966078389)},
+ {UINT64CONST(8757267504958198172), UINT64CONST(94955677457597987)}, {UINT64CONST(6334898362770359811), UINT64CONST(118694596821997484)},
+ {UINT64CONST(13182683513586250689), UINT64CONST(74184123013748427)}, {UINT64CONST(11866668373555425458), UINT64CONST(92730153767185534)},
+ {UINT64CONST(5609963430089506015), UINT64CONST(115912692208981918)}, {UINT64CONST(17341285199088104971), UINT64CONST(72445432630613698)},
+ {UINT64CONST(12453234462005355406), UINT64CONST(90556790788267123)}, {UINT64CONST(10954857059079306353), UINT64CONST(113195988485333904)},
+ {UINT64CONST(13693571323849132942), UINT64CONST(141494985606667380)}, {UINT64CONST(17781854114260483896), UINT64CONST(88434366004167112)},
+ {UINT64CONST(3780573569116053255), UINT64CONST(110542957505208891)}, {UINT64CONST(114030942967678664), UINT64CONST(138178696881511114)},
+ {UINT64CONST(4682955357782187069), UINT64CONST(86361685550944446)}, {UINT64CONST(15077066234082509644), UINT64CONST(107952106938680557)},
+ {UINT64CONST(5011274737320973344), UINT64CONST(134940133673350697)}, {UINT64CONST(14661261756894078100), UINT64CONST(84337583545844185)},
+ {UINT64CONST(4491519140835433913), UINT64CONST(105421979432305232)}, {UINT64CONST(5614398926044292391), UINT64CONST(131777474290381540)},
+ {UINT64CONST(12732371365632458552), UINT64CONST(82360921431488462)}, {UINT64CONST(6692092170185797382), UINT64CONST(102951151789360578)},
+ {UINT64CONST(17588487249587022536), UINT64CONST(128688939736700722)}, {UINT64CONST(15604490549419276989), UINT64CONST(80430587335437951)},
+ {UINT64CONST(14893927168346708332), UINT64CONST(100538234169297439)}, {UINT64CONST(14005722942005997511), UINT64CONST(125672792711621799)},
+ {UINT64CONST(15671105866394830300), UINT64CONST(78545495444763624)}, {UINT64CONST(1142138259283986260), UINT64CONST(98181869305954531)},
+ {UINT64CONST(15262730879387146537), UINT64CONST(122727336632443163)}, {UINT64CONST(7233363790403272633), UINT64CONST(76704585395276977)},
+ {UINT64CONST(13653390756431478696), UINT64CONST(95880731744096221)}, {UINT64CONST(3231680390257184658), UINT64CONST(119850914680120277)},
+ {UINT64CONST(4325643253124434363), UINT64CONST(74906821675075173)}, {UINT64CONST(10018740084832930858), UINT64CONST(93633527093843966)},
+ {UINT64CONST(3300053069186387764), UINT64CONST(117041908867304958)}, {UINT64CONST(15897591223523656064), UINT64CONST(73151193042065598)},
+ {UINT64CONST(10648616992549794273), UINT64CONST(91438991302581998)}, {UINT64CONST(4087399203832467033), UINT64CONST(114298739128227498)},
+ {UINT64CONST(14332621041645359599), UINT64CONST(142873423910284372)}, {UINT64CONST(18181260187883125557), UINT64CONST(89295889943927732)},
+ {UINT64CONST(4279831161144355331), UINT64CONST(111619862429909666)}, {UINT64CONST(14573160988285219972), UINT64CONST(139524828037387082)},
+ {UINT64CONST(13719911636105650386), UINT64CONST(87203017523366926)}, {UINT64CONST(7926517508277287175), UINT64CONST(109003771904208658)},
+ {UINT64CONST(684774848491833161), UINT64CONST(136254714880260823)}, {UINT64CONST(7345513307948477581), UINT64CONST(85159196800163014)},
+ {UINT64CONST(18405263671790372785), UINT64CONST(106448996000203767)}, {UINT64CONST(18394893571310578077), UINT64CONST(133061245000254709)},
+ {UINT64CONST(13802651491282805250), UINT64CONST(83163278125159193)}, {UINT64CONST(3418256308821342851), UINT64CONST(103954097656448992)},
+ {UINT64CONST(4272820386026678563), UINT64CONST(129942622070561240)}, {UINT64CONST(2670512741266674102), UINT64CONST(81214138794100775)},
+ {UINT64CONST(17173198981865506339), UINT64CONST(101517673492625968)}, {UINT64CONST(3019754653622331308), UINT64CONST(126897091865782461)},
+ {UINT64CONST(4193189667727651020), UINT64CONST(79310682416114038)}, {UINT64CONST(14464859121514339583), UINT64CONST(99138353020142547)},
+ {UINT64CONST(13469387883465536574), UINT64CONST(123922941275178184)}, {UINT64CONST(8418367427165960359), UINT64CONST(77451838296986365)},
+ {UINT64CONST(15134645302384838353), UINT64CONST(96814797871232956)}, {UINT64CONST(471562554271496325), UINT64CONST(121018497339041196)},
+ {UINT64CONST(9518098633274461011), UINT64CONST(75636560836900747)}, {UINT64CONST(7285937273165688360), UINT64CONST(94545701046125934)},
+ {UINT64CONST(18330793628311886258), UINT64CONST(118182126307657417)}, {UINT64CONST(4539216990053847055), UINT64CONST(73863828942285886)},
+ {UINT64CONST(14897393274422084627), UINT64CONST(92329786177857357)}, {UINT64CONST(4786683537745442072), UINT64CONST(115412232722321697)},
+ {UINT64CONST(14520892257159371055), UINT64CONST(72132645451451060)}, {UINT64CONST(18151115321449213818), UINT64CONST(90165806814313825)},
+ {UINT64CONST(8853836096529353561), UINT64CONST(112707258517892282)}, {UINT64CONST(1843923083806916143), UINT64CONST(140884073147365353)},
+ {UINT64CONST(12681666973447792349), UINT64CONST(88052545717103345)}, {UINT64CONST(2017025661527576725), UINT64CONST(110065682146379182)},
+ {UINT64CONST(11744654113764246714), UINT64CONST(137582102682973977)}, {UINT64CONST(422879793461572340), UINT64CONST(85988814176858736)},
+ {UINT64CONST(528599741826965425), UINT64CONST(107486017721073420)}, {UINT64CONST(660749677283706782), UINT64CONST(134357522151341775)},
+ {UINT64CONST(7330497575943398595), UINT64CONST(83973451344588609)}, {UINT64CONST(13774807988356636147), UINT64CONST(104966814180735761)},
+ {UINT64CONST(3383451930163631472), UINT64CONST(131208517725919702)}, {UINT64CONST(15949715511634433382), UINT64CONST(82005323578699813)},
+ {UINT64CONST(6102086334260878016), UINT64CONST(102506654473374767)}, {UINT64CONST(3015921899398709616), UINT64CONST(128133318091718459)},
+ {UINT64CONST(18025852251620051174), UINT64CONST(80083323807324036)}, {UINT64CONST(4085571240815512351), UINT64CONST(100104154759155046)},
+ {UINT64CONST(14330336087874166247), UINT64CONST(125130193448943807)}, {UINT64CONST(15873989082562435760), UINT64CONST(78206370905589879)},
+ {UINT64CONST(15230800334775656796), UINT64CONST(97757963631987349)}, {UINT64CONST(5203442363187407284), UINT64CONST(122197454539984187)},
+ {UINT64CONST(946308467778435600), UINT64CONST(76373409087490117)}, {UINT64CONST(5794571603150432404), UINT64CONST(95466761359362646)},
+ {UINT64CONST(16466586540792816313), UINT64CONST(119333451699203307)}, {UINT64CONST(7985773578781816244), UINT64CONST(74583407312002067)},
+ {UINT64CONST(5370530955049882401), UINT64CONST(93229259140002584)}, {UINT64CONST(6713163693812353001), UINT64CONST(116536573925003230)},
+ {UINT64CONST(18030785363914884337), UINT64CONST(72835358703127018)}, {UINT64CONST(13315109668038829614), UINT64CONST(91044198378908773)},
+ {UINT64CONST(2808829029766373305), UINT64CONST(113805247973635967)}, {UINT64CONST(17346094342490130344), UINT64CONST(142256559967044958)},
+ {UINT64CONST(6229622945628943561), UINT64CONST(88910349979403099)}, {UINT64CONST(3175342663608791547), UINT64CONST(111137937474253874)},
+ {UINT64CONST(13192550366365765242), UINT64CONST(138922421842817342)}, {UINT64CONST(3633657960551215372), UINT64CONST(86826513651760839)},
+ {UINT64CONST(18377130505971182927), UINT64CONST(108533142064701048)}, {UINT64CONST(4524669058754427043), UINT64CONST(135666427580876311)},
+ {UINT64CONST(9745447189362598758), UINT64CONST(84791517238047694)}, {UINT64CONST(2958436949848472639), UINT64CONST(105989396547559618)},
+ {UINT64CONST(12921418224165366607), UINT64CONST(132486745684449522)}, {UINT64CONST(12687572408530742033), UINT64CONST(82804216052780951)},
+ {UINT64CONST(11247779492236039638), UINT64CONST(103505270065976189)}, {UINT64CONST(224666310012885835), UINT64CONST(129381587582470237)},
+ {UINT64CONST(2446259452971747599), UINT64CONST(80863492239043898)}, {UINT64CONST(12281196353069460307), UINT64CONST(101079365298804872)},
+ {UINT64CONST(15351495441336825384), UINT64CONST(126349206623506090)}, {UINT64CONST(14206370669262903769), UINT64CONST(78968254139691306)},
+ {UINT64CONST(8534591299723853903), UINT64CONST(98710317674614133)}, {UINT64CONST(15279925143082205283), UINT64CONST(123387897093267666)},
+ {UINT64CONST(14161639232853766206), UINT64CONST(77117435683292291)}, {UINT64CONST(13090363022639819853), UINT64CONST(96396794604115364)},
+ {UINT64CONST(16362953778299774816), UINT64CONST(120495993255144205)}, {UINT64CONST(12532689120651053212), UINT64CONST(75309995784465128)},
+ {UINT64CONST(15665861400813816515), UINT64CONST(94137494730581410)}, {UINT64CONST(10358954714162494836), UINT64CONST(117671868413226763)},
+ {UINT64CONST(4168503687137865320), UINT64CONST(73544917758266727)}, {UINT64CONST(598943590494943747), UINT64CONST(91931147197833409)},
+ {UINT64CONST(5360365506546067587), UINT64CONST(114913933997291761)}, {UINT64CONST(11312142901609972388), UINT64CONST(143642417496614701)},
+ {UINT64CONST(9375932322719926695), UINT64CONST(89776510935384188)}, {UINT64CONST(11719915403399908368), UINT64CONST(112220638669230235)},
+ {UINT64CONST(10038208235822497557), UINT64CONST(140275798336537794)}, {UINT64CONST(10885566165816448877), UINT64CONST(87672373960336121)},
+ {UINT64CONST(18218643725697949000), UINT64CONST(109590467450420151)}, {UINT64CONST(18161618638695048346), UINT64CONST(136988084313025189)},
+ {UINT64CONST(13656854658398099168), UINT64CONST(85617552695640743)}, {UINT64CONST(12459382304570236056), UINT64CONST(107021940869550929)},
+ {UINT64CONST(1739169825430631358), UINT64CONST(133777426086938662)}, {UINT64CONST(14922039196176308311), UINT64CONST(83610891304336663)},
+ {UINT64CONST(14040862976792997485), UINT64CONST(104513614130420829)}, {UINT64CONST(3716020665709083144), UINT64CONST(130642017663026037)},
+ {UINT64CONST(4628355925281870917), UINT64CONST(81651261039391273)}, {UINT64CONST(10397130925029726550), UINT64CONST(102064076299239091)},
+ {UINT64CONST(8384727637859770284), UINT64CONST(127580095374048864)}, {UINT64CONST(5240454773662356427), UINT64CONST(79737559608780540)},
+ {UINT64CONST(6550568467077945534), UINT64CONST(99671949510975675)}, {UINT64CONST(3576524565420044014), UINT64CONST(124589936888719594)},
+ {UINT64CONST(6847013871814915412), UINT64CONST(77868710555449746)}, {UINT64CONST(17782139376623420074), UINT64CONST(97335888194312182)},
+ {UINT64CONST(13004302183924499284), UINT64CONST(121669860242890228)}, {UINT64CONST(17351060901807587860), UINT64CONST(76043662651806392)},
+ {UINT64CONST(3242082053549933210), UINT64CONST(95054578314757991)}, {UINT64CONST(17887660622219580224), UINT64CONST(118818222893447488)},
+ {UINT64CONST(11179787888887237640), UINT64CONST(74261389308404680)}, {UINT64CONST(13974734861109047050), UINT64CONST(92826736635505850)},
+ {UINT64CONST(8245046539531533005), UINT64CONST(116033420794382313)}, {UINT64CONST(16682369133275677888), UINT64CONST(72520887996488945)},
+ {UINT64CONST(7017903361312433648), UINT64CONST(90651109995611182)}, {UINT64CONST(17995751238495317868), UINT64CONST(113313887494513977)},
+ {UINT64CONST(8659630992836983623), UINT64CONST(141642359368142472)}, {UINT64CONST(5412269370523114764), UINT64CONST(88526474605089045)},
+ {UINT64CONST(11377022731581281359), UINT64CONST(110658093256361306)}, {UINT64CONST(4997906377621825891), UINT64CONST(138322616570451633)},
+ {UINT64CONST(14652906532082110942), UINT64CONST(86451635356532270)}, {UINT64CONST(9092761128247862869), UINT64CONST(108064544195665338)},
+ {UINT64CONST(2142579373455052779), UINT64CONST(135080680244581673)}, {UINT64CONST(12868327154477877747), UINT64CONST(84425425152863545)},
+ {UINT64CONST(2250350887815183471), UINT64CONST(105531781441079432)}, {UINT64CONST(2812938609768979339), UINT64CONST(131914726801349290)},
+ {UINT64CONST(6369772649532999991), UINT64CONST(82446704250843306)}, {UINT64CONST(17185587848771025797), UINT64CONST(103058380313554132)},
+ {UINT64CONST(3035240737254230630), UINT64CONST(128822975391942666)}, {UINT64CONST(6508711479211282048), UINT64CONST(80514359619964166)},
+ {UINT64CONST(17359261385868878368), UINT64CONST(100642949524955207)}, {UINT64CONST(17087390713908710056), UINT64CONST(125803686906194009)},
+ {UINT64CONST(3762090168551861929), UINT64CONST(78627304316371256)}, {UINT64CONST(4702612710689827411), UINT64CONST(98284130395464070)},
+ {UINT64CONST(15101637925217060072), UINT64CONST(122855162994330087)}, {UINT64CONST(16356052730901744401), UINT64CONST(76784476871456304)},
+ {UINT64CONST(1998321839917628885), UINT64CONST(95980596089320381)}, {UINT64CONST(7109588318324424010), UINT64CONST(119975745111650476)},
+ {UINT64CONST(13666864735807540814), UINT64CONST(74984840694781547)}, {UINT64CONST(12471894901332038114), UINT64CONST(93731050868476934)},
+ {UINT64CONST(6366496589810271835), UINT64CONST(117163813585596168)}, {UINT64CONST(3979060368631419896), UINT64CONST(73227383490997605)},
+ {UINT64CONST(9585511479216662775), UINT64CONST(91534229363747006)}, {UINT64CONST(2758517312166052660), UINT64CONST(114417786704683758)},
+ {UINT64CONST(12671518677062341634), UINT64CONST(143022233380854697)}, {UINT64CONST(1002170145522881665), UINT64CONST(89388895863034186)},
+ {UINT64CONST(10476084718758377889), UINT64CONST(111736119828792732)}, {UINT64CONST(13095105898447972362), UINT64CONST(139670149785990915)},
+ {UINT64CONST(5878598177316288774), UINT64CONST(87293843616244322)}, {UINT64CONST(16571619758500136775), UINT64CONST(109117304520305402)},
+ {UINT64CONST(11491152661270395161), UINT64CONST(136396630650381753)}, {UINT64CONST(264441385652915120), UINT64CONST(85247894156488596)},
+ {UINT64CONST(330551732066143900), UINT64CONST(106559867695610745)}, {UINT64CONST(5024875683510067779), UINT64CONST(133199834619513431)},
+ {UINT64CONST(10058076329834874218), UINT64CONST(83249896637195894)}, {UINT64CONST(3349223375438816964), UINT64CONST(104062370796494868)},
+ {UINT64CONST(4186529219298521205), UINT64CONST(130077963495618585)}, {UINT64CONST(14145795808130045513), UINT64CONST(81298727184761615)},
+ {UINT64CONST(13070558741735168987), UINT64CONST(101623408980952019)}, {UINT64CONST(11726512408741573330), UINT64CONST(127029261226190024)},
+ {UINT64CONST(7329070255463483331), UINT64CONST(79393288266368765)}, {UINT64CONST(13773023837756742068), UINT64CONST(99241610332960956)},
+ {UINT64CONST(17216279797195927585), UINT64CONST(124052012916201195)}, {UINT64CONST(8454331864033760789), UINT64CONST(77532508072625747)},
+ {UINT64CONST(5956228811614813082), UINT64CONST(96915635090782184)}, {UINT64CONST(7445286014518516353), UINT64CONST(121144543863477730)},
+ {UINT64CONST(9264989777501460624), UINT64CONST(75715339914673581)}, {UINT64CONST(16192923240304213684), UINT64CONST(94644174893341976)},
+ {UINT64CONST(1794409976670715490), UINT64CONST(118305218616677471)}, {UINT64CONST(8039035263060279037), UINT64CONST(73940761635423419)},
+ {UINT64CONST(5437108060397960892), UINT64CONST(92425952044279274)}, {UINT64CONST(16019757112352226923), UINT64CONST(115532440055349092)},
+ {UINT64CONST(788976158365366019), UINT64CONST(72207775034593183)}, {UINT64CONST(14821278253238871236), UINT64CONST(90259718793241478)},
+ {UINT64CONST(9303225779693813237), UINT64CONST(112824648491551848)}, {UINT64CONST(11629032224617266546), UINT64CONST(141030810614439810)},
+ {UINT64CONST(11879831158813179495), UINT64CONST(88144256634024881)}, {UINT64CONST(1014730893234310657), UINT64CONST(110180320792531102)},
+ {UINT64CONST(10491785653397664129), UINT64CONST(137725400990663877)}, {UINT64CONST(8863209042587234033), UINT64CONST(86078375619164923)},
+ {UINT64CONST(6467325284806654637), UINT64CONST(107597969523956154)}, {UINT64CONST(17307528642863094104), UINT64CONST(134497461904945192)},
+ {UINT64CONST(10817205401789433815), UINT64CONST(84060913690590745)}, {UINT64CONST(18133192770664180173), UINT64CONST(105076142113238431)},
+ {UINT64CONST(18054804944902837312), UINT64CONST(131345177641548039)}, {UINT64CONST(18201782118205355176), UINT64CONST(82090736025967524)},
+ {UINT64CONST(4305483574047142354), UINT64CONST(102613420032459406)}, {UINT64CONST(14605226504413703751), UINT64CONST(128266775040574257)},
+ {UINT64CONST(2210737537617482988), UINT64CONST(80166734400358911)}, {UINT64CONST(16598479977304017447), UINT64CONST(100208418000448638)},
+ {UINT64CONST(11524727934775246001), UINT64CONST(125260522500560798)}, {UINT64CONST(2591268940807140847), UINT64CONST(78287826562850499)},
+ {UINT64CONST(17074144231291089770), UINT64CONST(97859783203563123)}, {UINT64CONST(16730994270686474309), UINT64CONST(122324729004453904)},
+ {UINT64CONST(10456871419179046443), UINT64CONST(76452955627783690)}, {UINT64CONST(3847717237119032246), UINT64CONST(95566194534729613)},
+ {UINT64CONST(9421332564826178211), UINT64CONST(119457743168412016)}, {UINT64CONST(5888332853016361382), UINT64CONST(74661089480257510)},
+ {UINT64CONST(16583788103125227536), UINT64CONST(93326361850321887)}, {UINT64CONST(16118049110479146516), UINT64CONST(116657952312902359)},
+ {UINT64CONST(16991309721690548428), UINT64CONST(72911220195563974)}, {UINT64CONST(12015765115258409727), UINT64CONST(91139025244454968)},
+ {UINT64CONST(15019706394073012159), UINT64CONST(113923781555568710)}, {UINT64CONST(9551260955736489391), UINT64CONST(142404726944460888)},
+ {UINT64CONST(5969538097335305869), UINT64CONST(89002954340288055)}, {UINT64CONST(2850236603241744433), UINT64CONST(111253692925360069)}
+};
+
+#endif /* RYU_D2S_FULL_TABLE_H */
diff --git a/contrib/libs/libpq/src/common/d2s_intrinsics.h b/contrib/libs/libpq/src/common/d2s_intrinsics.h
new file mode 100644
index 0000000000..ae0f28dbb2
--- /dev/null
+++ b/contrib/libs/libpq/src/common/d2s_intrinsics.h
@@ -0,0 +1,202 @@
+/*---------------------------------------------------------------------------
+ *
+ * Ryu floating-point output for double precision.
+ *
+ * Portions Copyright (c) 2018-2023, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/common/d2s_intrinsics.h
+ *
+ * This is a modification of code taken from github.com/ulfjack/ryu under the
+ * terms of the Boost license (not the Apache license). The original copyright
+ * notice follows:
+ *
+ * Copyright 2018 Ulf Adams
+ *
+ * The contents of this file may be used under the terms of the Apache
+ * License, Version 2.0.
+ *
+ * (See accompanying file LICENSE-Apache or copy at
+ * http://www.apache.org/licenses/LICENSE-2.0)
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * Boost Software License, Version 1.0.
+ *
+ * (See accompanying file LICENSE-Boost or copy at
+ * https://www.boost.org/LICENSE_1_0.txt)
+ *
+ * Unless required by applicable law or agreed to in writing, this software is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.
+ *
+ *---------------------------------------------------------------------------
+ */
+#ifndef RYU_D2S_INTRINSICS_H
+#define RYU_D2S_INTRINSICS_H
+
+#if defined(HAS_64_BIT_INTRINSICS)
+
+#include <intrin.h>
+
+static inline uint64
+umul128(const uint64 a, const uint64 b, uint64 *const productHi)
+{
+ return _umul128(a, b, productHi);
+}
+
+static inline uint64
+shiftright128(const uint64 lo, const uint64 hi, const uint32 dist)
+{
+ /*
+ * For the __shiftright128 intrinsic, the shift value is always modulo 64.
+ * In the current implementation of the double-precision version of Ryu,
+ * the shift value is always < 64. (In the case RYU_OPTIMIZE_SIZE == 0,
+ * the shift value is in the range [49, 58]. Otherwise in the range [2,
+ * 59].) Check this here in case a future change requires larger shift
+ * values. In this case this function needs to be adjusted.
+ */
+ Assert(dist < 64);
+ return __shiftright128(lo, hi, (unsigned char) dist);
+}
+
+#else /* defined(HAS_64_BIT_INTRINSICS) */
+
+static inline uint64
+umul128(const uint64 a, const uint64 b, uint64 *const productHi)
+{
+ /*
+ * The casts here help MSVC to avoid calls to the __allmul library
+ * function.
+ */
+ const uint32 aLo = (uint32) a;
+ const uint32 aHi = (uint32) (a >> 32);
+ const uint32 bLo = (uint32) b;
+ const uint32 bHi = (uint32) (b >> 32);
+
+ const uint64 b00 = (uint64) aLo * bLo;
+ const uint64 b01 = (uint64) aLo * bHi;
+ const uint64 b10 = (uint64) aHi * bLo;
+ const uint64 b11 = (uint64) aHi * bHi;
+
+ const uint32 b00Lo = (uint32) b00;
+ const uint32 b00Hi = (uint32) (b00 >> 32);
+
+ const uint64 mid1 = b10 + b00Hi;
+ const uint32 mid1Lo = (uint32) (mid1);
+ const uint32 mid1Hi = (uint32) (mid1 >> 32);
+
+ const uint64 mid2 = b01 + mid1Lo;
+ const uint32 mid2Lo = (uint32) (mid2);
+ const uint32 mid2Hi = (uint32) (mid2 >> 32);
+
+ const uint64 pHi = b11 + mid1Hi + mid2Hi;
+ const uint64 pLo = ((uint64) mid2Lo << 32) + b00Lo;
+
+ *productHi = pHi;
+ return pLo;
+}
+
+static inline uint64
+shiftright128(const uint64 lo, const uint64 hi, const uint32 dist)
+{
+ /* We don't need to handle the case dist >= 64 here (see above). */
+ Assert(dist < 64);
+#if !defined(RYU_32_BIT_PLATFORM)
+ Assert(dist > 0);
+ return (hi << (64 - dist)) | (lo >> dist);
+#else
+ /* Avoid a 64-bit shift by taking advantage of the range of shift values. */
+ Assert(dist >= 32);
+ return (hi << (64 - dist)) | ((uint32) (lo >> 32) >> (dist - 32));
+#endif
+}
+
+#endif /* // defined(HAS_64_BIT_INTRINSICS) */
+
+#ifdef RYU_32_BIT_PLATFORM
+
+/* Returns the high 64 bits of the 128-bit product of a and b. */
+static inline uint64
+umulh(const uint64 a, const uint64 b)
+{
+ /*
+ * Reuse the umul128 implementation. Optimizers will likely eliminate the
+ * instructions used to compute the low part of the product.
+ */
+ uint64 hi;
+
+ umul128(a, b, &hi);
+ return hi;
+}
+
+/*----
+ * On 32-bit platforms, compilers typically generate calls to library
+ * functions for 64-bit divisions, even if the divisor is a constant.
+ *
+ * E.g.:
+ * https://bugs.llvm.org/show_bug.cgi?id=37932
+ * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=17958
+ * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=37443
+ *
+ * The functions here perform division-by-constant using multiplications
+ * in the same way as 64-bit compilers would do.
+ *
+ * NB:
+ * The multipliers and shift values are the ones generated by clang x64
+ * for expressions like x/5, x/10, etc.
+ *----
+ */
+
+static inline uint64
+div5(const uint64 x)
+{
+ return umulh(x, UINT64CONST(0xCCCCCCCCCCCCCCCD)) >> 2;
+}
+
+static inline uint64
+div10(const uint64 x)
+{
+ return umulh(x, UINT64CONST(0xCCCCCCCCCCCCCCCD)) >> 3;
+}
+
+static inline uint64
+div100(const uint64 x)
+{
+ return umulh(x >> 2, UINT64CONST(0x28F5C28F5C28F5C3)) >> 2;
+}
+
+static inline uint64
+div1e8(const uint64 x)
+{
+ return umulh(x, UINT64CONST(0xABCC77118461CEFD)) >> 26;
+}
+
+#else /* RYU_32_BIT_PLATFORM */
+
+static inline uint64
+div5(const uint64 x)
+{
+ return x / 5;
+}
+
+static inline uint64
+div10(const uint64 x)
+{
+ return x / 10;
+}
+
+static inline uint64
+div100(const uint64 x)
+{
+ return x / 100;
+}
+
+static inline uint64
+div1e8(const uint64 x)
+{
+ return x / 100000000;
+}
+
+#endif /* RYU_32_BIT_PLATFORM */
+
+#endif /* RYU_D2S_INTRINSICS_H */
diff --git a/contrib/libs/libpq/src/common/digit_table.h b/contrib/libs/libpq/src/common/digit_table.h
new file mode 100644
index 0000000000..483aa17142
--- /dev/null
+++ b/contrib/libs/libpq/src/common/digit_table.h
@@ -0,0 +1,21 @@
+#ifndef RYU_DIGIT_TABLE_H
+#define RYU_DIGIT_TABLE_H
+
+/*
+ * A table of all two-digit numbers. This is used to speed up decimal digit
+ * generation by copying pairs of digits into the final output.
+ */
+static const char DIGIT_TABLE[200] = {
+ '0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '0', '6', '0', '7', '0', '8', '0', '9',
+ '1', '0', '1', '1', '1', '2', '1', '3', '1', '4', '1', '5', '1', '6', '1', '7', '1', '8', '1', '9',
+ '2', '0', '2', '1', '2', '2', '2', '3', '2', '4', '2', '5', '2', '6', '2', '7', '2', '8', '2', '9',
+ '3', '0', '3', '1', '3', '2', '3', '3', '3', '4', '3', '5', '3', '6', '3', '7', '3', '8', '3', '9',
+ '4', '0', '4', '1', '4', '2', '4', '3', '4', '4', '4', '5', '4', '6', '4', '7', '4', '8', '4', '9',
+ '5', '0', '5', '1', '5', '2', '5', '3', '5', '4', '5', '5', '5', '6', '5', '7', '5', '8', '5', '9',
+ '6', '0', '6', '1', '6', '2', '6', '3', '6', '4', '6', '5', '6', '6', '6', '7', '6', '8', '6', '9',
+ '7', '0', '7', '1', '7', '2', '7', '3', '7', '4', '7', '5', '7', '6', '7', '7', '7', '8', '7', '9',
+ '8', '0', '8', '1', '8', '2', '8', '3', '8', '4', '8', '5', '8', '6', '8', '7', '8', '8', '8', '9',
+ '9', '0', '9', '1', '9', '2', '9', '3', '9', '4', '9', '5', '9', '6', '9', '7', '9', '8', '9', '9'
+};
+
+#endif /* RYU_DIGIT_TABLE_H */
diff --git a/contrib/libs/libpq/src/common/encnames.c b/contrib/libs/libpq/src/common/encnames.c
new file mode 100644
index 0000000000..0412a8220e
--- /dev/null
+++ b/contrib/libs/libpq/src/common/encnames.c
@@ -0,0 +1,598 @@
+/*-------------------------------------------------------------------------
+ *
+ * encnames.c
+ * Encoding names and routines for working with them.
+ *
+ * Portions Copyright (c) 2001-2023, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/common/encnames.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "c.h"
+
+#include <ctype.h>
+#include <unistd.h>
+
+#include "mb/pg_wchar.h"
+
+
+/* ----------
+ * All encoding names, sorted: *** A L P H A B E T I C ***
+ *
+ * All names must be without irrelevant chars, search routines use
+ * isalnum() chars only. It means ISO-8859-1, iso_8859-1 and Iso8859_1
+ * are always converted to 'iso88591'. All must be lower case.
+ *
+ * The table doesn't contain 'cs' aliases (like csISOLatin1). It's needed?
+ *
+ * Karel Zak, Aug 2001
+ * ----------
+ */
+typedef struct pg_encname
+{
+ const char *name;
+ pg_enc encoding;
+} pg_encname;
+
+static const pg_encname pg_encname_tbl[] =
+{
+ {
+ "abc", PG_WIN1258
+ }, /* alias for WIN1258 */
+ {
+ "alt", PG_WIN866
+ }, /* IBM866 */
+ {
+ "big5", PG_BIG5
+ }, /* Big5; Chinese for Taiwan multibyte set */
+ {
+ "euccn", PG_EUC_CN
+ }, /* EUC-CN; Extended Unix Code for simplified
+ * Chinese */
+ {
+ "eucjis2004", PG_EUC_JIS_2004
+ }, /* EUC-JIS-2004; Extended UNIX Code fixed
+ * Width for Japanese, standard JIS X 0213 */
+ {
+ "eucjp", PG_EUC_JP
+ }, /* EUC-JP; Extended UNIX Code fixed Width for
+ * Japanese, standard OSF */
+ {
+ "euckr", PG_EUC_KR
+ }, /* EUC-KR; Extended Unix Code for Korean , KS
+ * X 1001 standard */
+ {
+ "euctw", PG_EUC_TW
+ }, /* EUC-TW; Extended Unix Code for
+ *
+ * traditional Chinese */
+ {
+ "gb18030", PG_GB18030
+ }, /* GB18030;GB18030 */
+ {
+ "gbk", PG_GBK
+ }, /* GBK; Chinese Windows CodePage 936
+ * simplified Chinese */
+ {
+ "iso88591", PG_LATIN1
+ }, /* ISO-8859-1; RFC1345,KXS2 */
+ {
+ "iso885910", PG_LATIN6
+ }, /* ISO-8859-10; RFC1345,KXS2 */
+ {
+ "iso885913", PG_LATIN7
+ }, /* ISO-8859-13; RFC1345,KXS2 */
+ {
+ "iso885914", PG_LATIN8
+ }, /* ISO-8859-14; RFC1345,KXS2 */
+ {
+ "iso885915", PG_LATIN9
+ }, /* ISO-8859-15; RFC1345,KXS2 */
+ {
+ "iso885916", PG_LATIN10
+ }, /* ISO-8859-16; RFC1345,KXS2 */
+ {
+ "iso88592", PG_LATIN2
+ }, /* ISO-8859-2; RFC1345,KXS2 */
+ {
+ "iso88593", PG_LATIN3
+ }, /* ISO-8859-3; RFC1345,KXS2 */
+ {
+ "iso88594", PG_LATIN4
+ }, /* ISO-8859-4; RFC1345,KXS2 */
+ {
+ "iso88595", PG_ISO_8859_5
+ }, /* ISO-8859-5; RFC1345,KXS2 */
+ {
+ "iso88596", PG_ISO_8859_6
+ }, /* ISO-8859-6; RFC1345,KXS2 */
+ {
+ "iso88597", PG_ISO_8859_7
+ }, /* ISO-8859-7; RFC1345,KXS2 */
+ {
+ "iso88598", PG_ISO_8859_8
+ }, /* ISO-8859-8; RFC1345,KXS2 */
+ {
+ "iso88599", PG_LATIN5
+ }, /* ISO-8859-9; RFC1345,KXS2 */
+ {
+ "johab", PG_JOHAB
+ }, /* JOHAB; Extended Unix Code for simplified
+ * Chinese */
+ {
+ "koi8", PG_KOI8R
+ }, /* _dirty_ alias for KOI8-R (backward
+ * compatibility) */
+ {
+ "koi8r", PG_KOI8R
+ }, /* KOI8-R; RFC1489 */
+ {
+ "koi8u", PG_KOI8U
+ }, /* KOI8-U; RFC2319 */
+ {
+ "latin1", PG_LATIN1
+ }, /* alias for ISO-8859-1 */
+ {
+ "latin10", PG_LATIN10
+ }, /* alias for ISO-8859-16 */
+ {
+ "latin2", PG_LATIN2
+ }, /* alias for ISO-8859-2 */
+ {
+ "latin3", PG_LATIN3
+ }, /* alias for ISO-8859-3 */
+ {
+ "latin4", PG_LATIN4
+ }, /* alias for ISO-8859-4 */
+ {
+ "latin5", PG_LATIN5
+ }, /* alias for ISO-8859-9 */
+ {
+ "latin6", PG_LATIN6
+ }, /* alias for ISO-8859-10 */
+ {
+ "latin7", PG_LATIN7
+ }, /* alias for ISO-8859-13 */
+ {
+ "latin8", PG_LATIN8
+ }, /* alias for ISO-8859-14 */
+ {
+ "latin9", PG_LATIN9
+ }, /* alias for ISO-8859-15 */
+ {
+ "mskanji", PG_SJIS
+ }, /* alias for Shift_JIS */
+ {
+ "muleinternal", PG_MULE_INTERNAL
+ },
+ {
+ "shiftjis", PG_SJIS
+ }, /* Shift_JIS; JIS X 0202-1991 */
+
+ {
+ "shiftjis2004", PG_SHIFT_JIS_2004
+ }, /* SHIFT-JIS-2004; Shift JIS for Japanese,
+ * standard JIS X 0213 */
+ {
+ "sjis", PG_SJIS
+ }, /* alias for Shift_JIS */
+ {
+ "sqlascii", PG_SQL_ASCII
+ },
+ {
+ "tcvn", PG_WIN1258
+ }, /* alias for WIN1258 */
+ {
+ "tcvn5712", PG_WIN1258
+ }, /* alias for WIN1258 */
+ {
+ "uhc", PG_UHC
+ }, /* UHC; Korean Windows CodePage 949 */
+ {
+ "unicode", PG_UTF8
+ }, /* alias for UTF8 */
+ {
+ "utf8", PG_UTF8
+ }, /* alias for UTF8 */
+ {
+ "vscii", PG_WIN1258
+ }, /* alias for WIN1258 */
+ {
+ "win", PG_WIN1251
+ }, /* _dirty_ alias for windows-1251 (backward
+ * compatibility) */
+ {
+ "win1250", PG_WIN1250
+ }, /* alias for Windows-1250 */
+ {
+ "win1251", PG_WIN1251
+ }, /* alias for Windows-1251 */
+ {
+ "win1252", PG_WIN1252
+ }, /* alias for Windows-1252 */
+ {
+ "win1253", PG_WIN1253
+ }, /* alias for Windows-1253 */
+ {
+ "win1254", PG_WIN1254
+ }, /* alias for Windows-1254 */
+ {
+ "win1255", PG_WIN1255
+ }, /* alias for Windows-1255 */
+ {
+ "win1256", PG_WIN1256
+ }, /* alias for Windows-1256 */
+ {
+ "win1257", PG_WIN1257
+ }, /* alias for Windows-1257 */
+ {
+ "win1258", PG_WIN1258
+ }, /* alias for Windows-1258 */
+ {
+ "win866", PG_WIN866
+ }, /* IBM866 */
+ {
+ "win874", PG_WIN874
+ }, /* alias for Windows-874 */
+ {
+ "win932", PG_SJIS
+ }, /* alias for Shift_JIS */
+ {
+ "win936", PG_GBK
+ }, /* alias for GBK */
+ {
+ "win949", PG_UHC
+ }, /* alias for UHC */
+ {
+ "win950", PG_BIG5
+ }, /* alias for BIG5 */
+ {
+ "windows1250", PG_WIN1250
+ }, /* Windows-1251; Microsoft */
+ {
+ "windows1251", PG_WIN1251
+ }, /* Windows-1251; Microsoft */
+ {
+ "windows1252", PG_WIN1252
+ }, /* Windows-1252; Microsoft */
+ {
+ "windows1253", PG_WIN1253
+ }, /* Windows-1253; Microsoft */
+ {
+ "windows1254", PG_WIN1254
+ }, /* Windows-1254; Microsoft */
+ {
+ "windows1255", PG_WIN1255
+ }, /* Windows-1255; Microsoft */
+ {
+ "windows1256", PG_WIN1256
+ }, /* Windows-1256; Microsoft */
+ {
+ "windows1257", PG_WIN1257
+ }, /* Windows-1257; Microsoft */
+ {
+ "windows1258", PG_WIN1258
+ }, /* Windows-1258; Microsoft */
+ {
+ "windows866", PG_WIN866
+ }, /* IBM866 */
+ {
+ "windows874", PG_WIN874
+ }, /* Windows-874; Microsoft */
+ {
+ "windows932", PG_SJIS
+ }, /* alias for Shift_JIS */
+ {
+ "windows936", PG_GBK
+ }, /* alias for GBK */
+ {
+ "windows949", PG_UHC
+ }, /* alias for UHC */
+ {
+ "windows950", PG_BIG5
+ } /* alias for BIG5 */
+};
+
+/* ----------
+ * These are "official" encoding names.
+ * XXX must be sorted by the same order as enum pg_enc (in mb/pg_wchar.h)
+ * ----------
+ */
+#ifndef WIN32
+#define DEF_ENC2NAME(name, codepage) { #name, PG_##name }
+#else
+#define DEF_ENC2NAME(name, codepage) { #name, PG_##name, codepage }
+#endif
+
+const pg_enc2name pg_enc2name_tbl[] =
+{
+ DEF_ENC2NAME(SQL_ASCII, 0),
+ DEF_ENC2NAME(EUC_JP, 20932),
+ DEF_ENC2NAME(EUC_CN, 20936),
+ DEF_ENC2NAME(EUC_KR, 51949),
+ DEF_ENC2NAME(EUC_TW, 0),
+ DEF_ENC2NAME(EUC_JIS_2004, 20932),
+ DEF_ENC2NAME(UTF8, 65001),
+ DEF_ENC2NAME(MULE_INTERNAL, 0),
+ DEF_ENC2NAME(LATIN1, 28591),
+ DEF_ENC2NAME(LATIN2, 28592),
+ DEF_ENC2NAME(LATIN3, 28593),
+ DEF_ENC2NAME(LATIN4, 28594),
+ DEF_ENC2NAME(LATIN5, 28599),
+ DEF_ENC2NAME(LATIN6, 0),
+ DEF_ENC2NAME(LATIN7, 0),
+ DEF_ENC2NAME(LATIN8, 0),
+ DEF_ENC2NAME(LATIN9, 28605),
+ DEF_ENC2NAME(LATIN10, 0),
+ DEF_ENC2NAME(WIN1256, 1256),
+ DEF_ENC2NAME(WIN1258, 1258),
+ DEF_ENC2NAME(WIN866, 866),
+ DEF_ENC2NAME(WIN874, 874),
+ DEF_ENC2NAME(KOI8R, 20866),
+ DEF_ENC2NAME(WIN1251, 1251),
+ DEF_ENC2NAME(WIN1252, 1252),
+ DEF_ENC2NAME(ISO_8859_5, 28595),
+ DEF_ENC2NAME(ISO_8859_6, 28596),
+ DEF_ENC2NAME(ISO_8859_7, 28597),
+ DEF_ENC2NAME(ISO_8859_8, 28598),
+ DEF_ENC2NAME(WIN1250, 1250),
+ DEF_ENC2NAME(WIN1253, 1253),
+ DEF_ENC2NAME(WIN1254, 1254),
+ DEF_ENC2NAME(WIN1255, 1255),
+ DEF_ENC2NAME(WIN1257, 1257),
+ DEF_ENC2NAME(KOI8U, 21866),
+ DEF_ENC2NAME(SJIS, 932),
+ DEF_ENC2NAME(BIG5, 950),
+ DEF_ENC2NAME(GBK, 936),
+ DEF_ENC2NAME(UHC, 949),
+ DEF_ENC2NAME(GB18030, 54936),
+ DEF_ENC2NAME(JOHAB, 0),
+ DEF_ENC2NAME(SHIFT_JIS_2004, 932)
+};
+
+/* ----------
+ * These are encoding names for gettext.
+ *
+ * This covers all encodings except MULE_INTERNAL, which is alien to gettext.
+ * ----------
+ */
+const pg_enc2gettext pg_enc2gettext_tbl[] =
+{
+ {PG_SQL_ASCII, "US-ASCII"},
+ {PG_UTF8, "UTF-8"},
+ {PG_LATIN1, "LATIN1"},
+ {PG_LATIN2, "LATIN2"},
+ {PG_LATIN3, "LATIN3"},
+ {PG_LATIN4, "LATIN4"},
+ {PG_ISO_8859_5, "ISO-8859-5"},
+ {PG_ISO_8859_6, "ISO_8859-6"},
+ {PG_ISO_8859_7, "ISO-8859-7"},
+ {PG_ISO_8859_8, "ISO-8859-8"},
+ {PG_LATIN5, "LATIN5"},
+ {PG_LATIN6, "LATIN6"},
+ {PG_LATIN7, "LATIN7"},
+ {PG_LATIN8, "LATIN8"},
+ {PG_LATIN9, "LATIN-9"},
+ {PG_LATIN10, "LATIN10"},
+ {PG_KOI8R, "KOI8-R"},
+ {PG_KOI8U, "KOI8-U"},
+ {PG_WIN1250, "CP1250"},
+ {PG_WIN1251, "CP1251"},
+ {PG_WIN1252, "CP1252"},
+ {PG_WIN1253, "CP1253"},
+ {PG_WIN1254, "CP1254"},
+ {PG_WIN1255, "CP1255"},
+ {PG_WIN1256, "CP1256"},
+ {PG_WIN1257, "CP1257"},
+ {PG_WIN1258, "CP1258"},
+ {PG_WIN866, "CP866"},
+ {PG_WIN874, "CP874"},
+ {PG_EUC_CN, "EUC-CN"},
+ {PG_EUC_JP, "EUC-JP"},
+ {PG_EUC_KR, "EUC-KR"},
+ {PG_EUC_TW, "EUC-TW"},
+ {PG_EUC_JIS_2004, "EUC-JP"},
+ {PG_SJIS, "SHIFT-JIS"},
+ {PG_BIG5, "BIG5"},
+ {PG_GBK, "GBK"},
+ {PG_UHC, "UHC"},
+ {PG_GB18030, "GB18030"},
+ {PG_JOHAB, "JOHAB"},
+ {PG_SHIFT_JIS_2004, "SHIFT_JISX0213"},
+ {0, NULL}
+};
+
+
+/*
+ * Table of encoding names for ICU (currently covers backend encodings only)
+ *
+ * Reference: <https://ssl.icu-project.org/icu-bin/convexp>
+ *
+ * NULL entries are not supported by ICU, or their mapping is unclear.
+ */
+static const char *const pg_enc2icu_tbl[] =
+{
+ NULL, /* PG_SQL_ASCII */
+ "EUC-JP", /* PG_EUC_JP */
+ "EUC-CN", /* PG_EUC_CN */
+ "EUC-KR", /* PG_EUC_KR */
+ "EUC-TW", /* PG_EUC_TW */
+ NULL, /* PG_EUC_JIS_2004 */
+ "UTF-8", /* PG_UTF8 */
+ NULL, /* PG_MULE_INTERNAL */
+ "ISO-8859-1", /* PG_LATIN1 */
+ "ISO-8859-2", /* PG_LATIN2 */
+ "ISO-8859-3", /* PG_LATIN3 */
+ "ISO-8859-4", /* PG_LATIN4 */
+ "ISO-8859-9", /* PG_LATIN5 */
+ "ISO-8859-10", /* PG_LATIN6 */
+ "ISO-8859-13", /* PG_LATIN7 */
+ "ISO-8859-14", /* PG_LATIN8 */
+ "ISO-8859-15", /* PG_LATIN9 */
+ NULL, /* PG_LATIN10 */
+ "CP1256", /* PG_WIN1256 */
+ "CP1258", /* PG_WIN1258 */
+ "CP866", /* PG_WIN866 */
+ NULL, /* PG_WIN874 */
+ "KOI8-R", /* PG_KOI8R */
+ "CP1251", /* PG_WIN1251 */
+ "CP1252", /* PG_WIN1252 */
+ "ISO-8859-5", /* PG_ISO_8859_5 */
+ "ISO-8859-6", /* PG_ISO_8859_6 */
+ "ISO-8859-7", /* PG_ISO_8859_7 */
+ "ISO-8859-8", /* PG_ISO_8859_8 */
+ "CP1250", /* PG_WIN1250 */
+ "CP1253", /* PG_WIN1253 */
+ "CP1254", /* PG_WIN1254 */
+ "CP1255", /* PG_WIN1255 */
+ "CP1257", /* PG_WIN1257 */
+ "KOI8-U", /* PG_KOI8U */
+};
+
+StaticAssertDecl(lengthof(pg_enc2icu_tbl) == PG_ENCODING_BE_LAST + 1,
+ "pg_enc2icu_tbl incomplete");
+
+
+/*
+ * Is this encoding supported by ICU?
+ */
+bool
+is_encoding_supported_by_icu(int encoding)
+{
+ if (!PG_VALID_BE_ENCODING(encoding))
+ return false;
+ return (pg_enc2icu_tbl[encoding] != NULL);
+}
+
+/*
+ * Returns ICU's name for encoding, or NULL if not supported
+ */
+const char *
+get_encoding_name_for_icu(int encoding)
+{
+ if (!PG_VALID_BE_ENCODING(encoding))
+ return NULL;
+ return pg_enc2icu_tbl[encoding];
+}
+
+
+/* ----------
+ * Encoding checks, for error returns -1 else encoding id
+ * ----------
+ */
+int
+pg_valid_client_encoding(const char *name)
+{
+ int enc;
+
+ if ((enc = pg_char_to_encoding(name)) < 0)
+ return -1;
+
+ if (!PG_VALID_FE_ENCODING(enc))
+ return -1;
+
+ return enc;
+}
+
+int
+pg_valid_server_encoding(const char *name)
+{
+ int enc;
+
+ if ((enc = pg_char_to_encoding(name)) < 0)
+ return -1;
+
+ if (!PG_VALID_BE_ENCODING(enc))
+ return -1;
+
+ return enc;
+}
+
+int
+pg_valid_server_encoding_id(int encoding)
+{
+ return PG_VALID_BE_ENCODING(encoding);
+}
+
+/*
+ * Remove irrelevant chars from encoding name, store at *newkey
+ *
+ * (Caller's responsibility to provide a large enough buffer)
+ */
+static char *
+clean_encoding_name(const char *key, char *newkey)
+{
+ const char *p;
+ char *np;
+
+ for (p = key, np = newkey; *p != '\0'; p++)
+ {
+ if (isalnum((unsigned char) *p))
+ {
+ if (*p >= 'A' && *p <= 'Z')
+ *np++ = *p + 'a' - 'A';
+ else
+ *np++ = *p;
+ }
+ }
+ *np = '\0';
+ return newkey;
+}
+
+/*
+ * Search encoding by encoding name
+ *
+ * Returns encoding ID, or -1 if not recognized
+ */
+int
+pg_char_to_encoding(const char *name)
+{
+ unsigned int nel = lengthof(pg_encname_tbl);
+ const pg_encname *base = pg_encname_tbl,
+ *last = base + nel - 1,
+ *position;
+ int result;
+ char buff[NAMEDATALEN],
+ *key;
+
+ if (name == NULL || *name == '\0')
+ return -1;
+
+ if (strlen(name) >= NAMEDATALEN)
+ return -1; /* it's certainly not in the table */
+
+ key = clean_encoding_name(name, buff);
+
+ while (last >= base)
+ {
+ position = base + ((last - base) >> 1);
+ result = key[0] - position->name[0];
+
+ if (result == 0)
+ {
+ result = strcmp(key, position->name);
+ if (result == 0)
+ return position->encoding;
+ }
+ if (result < 0)
+ last = position - 1;
+ else
+ base = position + 1;
+ }
+ return -1;
+}
+
+const char *
+pg_encoding_to_char(int encoding)
+{
+ if (PG_VALID_ENCODING(encoding))
+ {
+ const pg_enc2name *p = &pg_enc2name_tbl[encoding];
+
+ Assert(encoding == p->encoding);
+ return p->name;
+ }
+ return "";
+}
diff --git a/contrib/libs/libpq/src/common/exec.c b/contrib/libs/libpq/src/common/exec.c
new file mode 100644
index 0000000000..d3a967baa4
--- /dev/null
+++ b/contrib/libs/libpq/src/common/exec.c
@@ -0,0 +1,719 @@
+/*-------------------------------------------------------------------------
+ *
+ * exec.c
+ * Functions for finding and validating executable files
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/common/exec.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/*
+ * On macOS, "man realpath" avers:
+ * Defining _DARWIN_C_SOURCE or _DARWIN_BETTER_REALPATH before including
+ * stdlib.h will cause the provided implementation of realpath() to use
+ * F_GETPATH from fcntl(2) to discover the path.
+ * This should be harmless everywhere else.
+ */
+#define _DARWIN_BETTER_REALPATH
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#include <signal.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#ifdef EXEC_BACKEND
+#if defined(HAVE_SYS_PERSONALITY_H)
+#include <sys/personality.h>
+#elif defined(HAVE_SYS_PROCCTL_H)
+#error #include <sys/procctl.h>
+#endif
+#endif
+
+/* Inhibit mingw CRT's auto-globbing of command line arguments */
+#if defined(WIN32) && !defined(_MSC_VER)
+extern int _CRT_glob = 0; /* 0 turns off globbing; 1 turns it on */
+#endif
+
+/*
+ * Hacky solution to allow expressing both frontend and backend error reports
+ * in one macro call. First argument of log_error is an errcode() call of
+ * some sort (ignored if FRONTEND); the rest are errmsg_internal() arguments,
+ * i.e. message string and any parameters for it.
+ *
+ * Caller must provide the gettext wrapper around the message string, if
+ * appropriate, so that it gets translated in the FRONTEND case; this
+ * motivates using errmsg_internal() not errmsg(). We handle appending a
+ * newline, if needed, inside the macro, so that there's only one translatable
+ * string per call not two.
+ */
+#ifndef FRONTEND
+#define log_error(errcodefn, ...) \
+ ereport(LOG, (errcodefn, errmsg_internal(__VA_ARGS__)))
+#else
+#define log_error(errcodefn, ...) \
+ (fprintf(stderr, __VA_ARGS__), fputc('\n', stderr))
+#endif
+
+static int normalize_exec_path(char *path);
+static char *pg_realpath(const char *fname);
+
+#ifdef WIN32
+static BOOL GetTokenUser(HANDLE hToken, PTOKEN_USER *ppTokenUser);
+#endif
+
+/*
+ * validate_exec -- validate "path" as an executable file
+ *
+ * returns 0 if the file is found and no error is encountered.
+ * -1 if the regular file "path" does not exist or cannot be executed.
+ * -2 if the file is otherwise valid but cannot be read.
+ * in the failure cases, errno is set appropriately
+ */
+int
+validate_exec(const char *path)
+{
+ struct stat buf;
+ int is_r;
+ int is_x;
+
+#ifdef WIN32
+ char path_exe[MAXPGPATH + sizeof(".exe") - 1];
+
+ /* Win32 requires a .exe suffix for stat() */
+ if (strlen(path) < strlen(".exe") ||
+ pg_strcasecmp(path + strlen(path) - strlen(".exe"), ".exe") != 0)
+ {
+ strlcpy(path_exe, path, sizeof(path_exe) - 4);
+ strcat(path_exe, ".exe");
+ path = path_exe;
+ }
+#endif
+
+ /*
+ * Ensure that the file exists and is a regular file.
+ *
+ * XXX if you have a broken system where stat() looks at the symlink
+ * instead of the underlying file, you lose.
+ */
+ if (stat(path, &buf) < 0)
+ return -1;
+
+ if (!S_ISREG(buf.st_mode))
+ {
+ /*
+ * POSIX offers no errno code that's simply "not a regular file". If
+ * it's a directory we can use EISDIR. Otherwise, it's most likely a
+ * device special file, and EPERM (Operation not permitted) isn't too
+ * horribly off base.
+ */
+ errno = S_ISDIR(buf.st_mode) ? EISDIR : EPERM;
+ return -1;
+ }
+
+ /*
+ * Ensure that the file is both executable and readable (required for
+ * dynamic loading).
+ */
+#ifndef WIN32
+ is_r = (access(path, R_OK) == 0);
+ is_x = (access(path, X_OK) == 0);
+ /* access() will set errno if it returns -1 */
+#else
+ is_r = buf.st_mode & S_IRUSR;
+ is_x = buf.st_mode & S_IXUSR;
+ errno = EACCES; /* appropriate thing if we return nonzero */
+#endif
+ return is_x ? (is_r ? 0 : -2) : -1;
+}
+
+
+/*
+ * find_my_exec -- find an absolute path to this program's executable
+ *
+ * argv0 is the name passed on the command line
+ * retpath is the output area (must be of size MAXPGPATH)
+ * Returns 0 if OK, -1 if error.
+ *
+ * The reason we have to work so hard to find an absolute path is that
+ * on some platforms we can't do dynamic loading unless we know the
+ * executable's location. Also, we need an absolute path not a relative
+ * path because we may later change working directory. Finally, we want
+ * a true path not a symlink location, so that we can locate other files
+ * that are part of our installation relative to the executable.
+ */
+int
+find_my_exec(const char *argv0, char *retpath)
+{
+ char *path;
+
+ /*
+ * If argv0 contains a separator, then PATH wasn't used.
+ */
+ strlcpy(retpath, argv0, MAXPGPATH);
+ if (first_dir_separator(retpath) != NULL)
+ {
+ if (validate_exec(retpath) == 0)
+ return normalize_exec_path(retpath);
+
+ log_error(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ _("invalid binary \"%s\": %m"), retpath);
+ return -1;
+ }
+
+#ifdef WIN32
+ /* Win32 checks the current directory first for names without slashes */
+ if (validate_exec(retpath) == 0)
+ return normalize_exec_path(retpath);
+#endif
+
+ /*
+ * Since no explicit path was supplied, the user must have been relying on
+ * PATH. We'll search the same PATH.
+ */
+ if ((path = getenv("PATH")) && *path)
+ {
+ char *startp = NULL,
+ *endp = NULL;
+
+ do
+ {
+ if (!startp)
+ startp = path;
+ else
+ startp = endp + 1;
+
+ endp = first_path_var_separator(startp);
+ if (!endp)
+ endp = startp + strlen(startp); /* point to end */
+
+ strlcpy(retpath, startp, Min(endp - startp + 1, MAXPGPATH));
+
+ join_path_components(retpath, retpath, argv0);
+ canonicalize_path(retpath);
+
+ switch (validate_exec(retpath))
+ {
+ case 0: /* found ok */
+ return normalize_exec_path(retpath);
+ case -1: /* wasn't even a candidate, keep looking */
+ break;
+ case -2: /* found but disqualified */
+ log_error(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ _("could not read binary \"%s\": %m"),
+ retpath);
+ break;
+ }
+ } while (*endp);
+ }
+
+ log_error(errcode(ERRCODE_UNDEFINED_FILE),
+ _("could not find a \"%s\" to execute"), argv0);
+ return -1;
+}
+
+
+/*
+ * normalize_exec_path - resolve symlinks and convert to absolute path
+ *
+ * Given a path that refers to an executable, chase through any symlinks
+ * to find the real file location; then convert that to an absolute path.
+ *
+ * On success, replaces the contents of "path" with the absolute path.
+ * ("path" is assumed to be of size MAXPGPATH.)
+ * Returns 0 if OK, -1 if error.
+ */
+static int
+normalize_exec_path(char *path)
+{
+ /*
+ * We used to do a lot of work ourselves here, but now we just let
+ * realpath(3) do all the heavy lifting.
+ */
+ char *abspath = pg_realpath(path);
+
+ if (abspath == NULL)
+ {
+ log_error(errcode_for_file_access(),
+ _("could not resolve path \"%s\" to absolute form: %m"),
+ path);
+ return -1;
+ }
+ strlcpy(path, abspath, MAXPGPATH);
+ free(abspath);
+
+#ifdef WIN32
+ /* On Windows, be sure to convert '\' to '/' */
+ canonicalize_path(path);
+#endif
+
+ return 0;
+}
+
+
+/*
+ * pg_realpath() - realpath(3) with POSIX.1-2008 semantics
+ *
+ * This is equivalent to realpath(fname, NULL), in that it returns a
+ * malloc'd buffer containing the absolute path equivalent to fname.
+ * On error, returns NULL with errno set.
+ *
+ * On Windows, what you get is spelled per platform conventions,
+ * so you probably want to apply canonicalize_path() to the result.
+ *
+ * For now, this is needed only here so mark it static. If you choose to
+ * move it into its own file, move the _DARWIN_BETTER_REALPATH #define too!
+ */
+static char *
+pg_realpath(const char *fname)
+{
+ char *path;
+
+#ifndef WIN32
+ path = realpath(fname, NULL);
+ if (path == NULL && errno == EINVAL)
+ {
+ /*
+ * Cope with old-POSIX systems that require a user-provided buffer.
+ * Assume MAXPGPATH is enough room on all such systems.
+ */
+ char *buf = malloc(MAXPGPATH);
+
+ if (buf == NULL)
+ return NULL; /* assume errno is set */
+ path = realpath(fname, buf);
+ if (path == NULL) /* don't leak memory */
+ {
+ int save_errno = errno;
+
+ free(buf);
+ errno = save_errno;
+ }
+ }
+#else /* WIN32 */
+
+ /*
+ * Microsoft is resolutely non-POSIX, but _fullpath() does the same thing.
+ * The documentation claims it reports errors by setting errno, which is a
+ * bit surprising for Microsoft, but we'll believe that until it's proven
+ * wrong. Clear errno first, though, so we can at least tell if a failure
+ * occurs and doesn't set it.
+ */
+ errno = 0;
+ path = _fullpath(NULL, fname, 0);
+#endif
+
+ return path;
+}
+
+
+/*
+ * Find another program in our binary's directory,
+ * then make sure it is the proper version.
+ */
+int
+find_other_exec(const char *argv0, const char *target,
+ const char *versionstr, char *retpath)
+{
+ char cmd[MAXPGPATH];
+ char line[MAXPGPATH];
+
+ if (find_my_exec(argv0, retpath) < 0)
+ return -1;
+
+ /* Trim off program name and keep just directory */
+ *last_dir_separator(retpath) = '\0';
+ canonicalize_path(retpath);
+
+ /* Now append the other program's name */
+ snprintf(retpath + strlen(retpath), MAXPGPATH - strlen(retpath),
+ "/%s%s", target, EXE);
+
+ if (validate_exec(retpath) != 0)
+ return -1;
+
+ snprintf(cmd, sizeof(cmd), "\"%s\" -V", retpath);
+
+ if (!pipe_read_line(cmd, line, sizeof(line)))
+ return -1;
+
+ if (strcmp(line, versionstr) != 0)
+ return -2;
+
+ return 0;
+}
+
+
+/*
+ * Execute a command in a pipe and read the first line from it.
+ */
+char *
+pipe_read_line(char *cmd, char *line, int maxsize)
+{
+ FILE *pgver;
+
+ fflush(NULL);
+
+ errno = 0;
+ if ((pgver = popen(cmd, "r")) == NULL)
+ {
+ perror("popen failure");
+ return NULL;
+ }
+
+ errno = 0;
+ if (fgets(line, maxsize, pgver) == NULL)
+ {
+ if (feof(pgver))
+ fprintf(stderr, "no data was returned by command \"%s\"\n", cmd);
+ else
+ perror("fgets failure");
+ pclose(pgver); /* no error checking */
+ return NULL;
+ }
+
+ if (pclose_check(pgver))
+ return NULL;
+
+ return line;
+}
+
+
+/*
+ * pclose() plus useful error reporting
+ */
+int
+pclose_check(FILE *stream)
+{
+ int exitstatus;
+ char *reason;
+
+ exitstatus = pclose(stream);
+
+ if (exitstatus == 0)
+ return 0; /* all is well */
+
+ if (exitstatus == -1)
+ {
+ /* pclose() itself failed, and hopefully set errno */
+ log_error(errcode(ERRCODE_SYSTEM_ERROR),
+ _("%s() failed: %m"), "pclose");
+ }
+ else
+ {
+ reason = wait_result_to_str(exitstatus);
+ log_error(errcode(ERRCODE_SYSTEM_ERROR),
+ "%s", reason);
+ pfree(reason);
+ }
+ return exitstatus;
+}
+
+/*
+ * set_pglocale_pgservice
+ *
+ * Set application-specific locale and service directory
+ *
+ * This function takes the value of argv[0] rather than a full path.
+ *
+ * (You may be wondering why this is in exec.c. It requires this module's
+ * services and doesn't introduce any new dependencies, so this seems as
+ * good as anyplace.)
+ */
+void
+set_pglocale_pgservice(const char *argv0, const char *app)
+{
+ char path[MAXPGPATH];
+ char my_exec_path[MAXPGPATH];
+
+ /* don't set LC_ALL in the backend */
+ if (strcmp(app, PG_TEXTDOMAIN("postgres")) != 0)
+ {
+ setlocale(LC_ALL, "");
+
+ /*
+ * One could make a case for reproducing here PostmasterMain()'s test
+ * for whether the process is multithreaded. Unlike the postmaster,
+ * no frontend program calls sigprocmask() or otherwise provides for
+ * mutual exclusion between signal handlers. While frontends using
+ * fork(), if multithreaded, are formally exposed to undefined
+ * behavior, we have not witnessed a concrete bug. Therefore,
+ * complaining about multithreading here may be mere pedantry.
+ */
+ }
+
+ if (find_my_exec(argv0, my_exec_path) < 0)
+ return;
+
+#ifdef ENABLE_NLS
+ get_locale_path(my_exec_path, path);
+ bindtextdomain(app, path);
+ textdomain(app);
+ /* set for libpq to use, but don't override existing setting */
+ setenv("PGLOCALEDIR", path, 0);
+#endif
+
+ if (getenv("PGSYSCONFDIR") == NULL)
+ {
+ get_etc_path(my_exec_path, path);
+ /* set for libpq to use */
+ setenv("PGSYSCONFDIR", path, 0);
+ }
+}
+
+#ifdef EXEC_BACKEND
+/*
+ * For the benefit of PostgreSQL developers testing EXEC_BACKEND on Unix
+ * systems (code paths normally exercised only on Windows), provide a way to
+ * disable address space layout randomization, if we know how on this platform.
+ * Otherwise, backends may fail to attach to shared memory at the fixed address
+ * chosen by the postmaster. (See also the macOS-specific hack in
+ * sysv_shmem.c.)
+ */
+int
+pg_disable_aslr(void)
+{
+#if defined(HAVE_SYS_PERSONALITY_H)
+ return personality(ADDR_NO_RANDOMIZE);
+#elif defined(HAVE_SYS_PROCCTL_H) && defined(PROC_ASLR_FORCE_DISABLE)
+ int data = PROC_ASLR_FORCE_DISABLE;
+
+ return procctl(P_PID, 0, PROC_ASLR_CTL, &data);
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+#endif
+
+#ifdef WIN32
+
+/*
+ * AddUserToTokenDacl(HANDLE hToken)
+ *
+ * This function adds the current user account to the restricted
+ * token used when we create a restricted process.
+ *
+ * This is required because of some security changes in Windows
+ * that appeared in patches to XP/2K3 and in Vista/2008.
+ *
+ * On these machines, the Administrator account is not included in
+ * the default DACL - you just get Administrators + System. For
+ * regular users you get User + System. Because we strip Administrators
+ * when we create the restricted token, we are left with only System
+ * in the DACL which leads to access denied errors for later CreatePipe()
+ * and CreateProcess() calls when running as Administrator.
+ *
+ * This function fixes this problem by modifying the DACL of the
+ * token the process will use, and explicitly re-adding the current
+ * user account. This is still secure because the Administrator account
+ * inherits its privileges from the Administrators group - it doesn't
+ * have any of its own.
+ */
+BOOL
+AddUserToTokenDacl(HANDLE hToken)
+{
+ int i;
+ ACL_SIZE_INFORMATION asi;
+ ACCESS_ALLOWED_ACE *pace;
+ DWORD dwNewAclSize;
+ DWORD dwSize = 0;
+ DWORD dwTokenInfoLength = 0;
+ PACL pacl = NULL;
+ PTOKEN_USER pTokenUser = NULL;
+ TOKEN_DEFAULT_DACL tddNew;
+ TOKEN_DEFAULT_DACL *ptdd = NULL;
+ TOKEN_INFORMATION_CLASS tic = TokenDefaultDacl;
+ BOOL ret = FALSE;
+
+ /* Figure out the buffer size for the DACL info */
+ if (!GetTokenInformation(hToken, tic, (LPVOID) NULL, dwTokenInfoLength, &dwSize))
+ {
+ if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ {
+ ptdd = (TOKEN_DEFAULT_DACL *) LocalAlloc(LPTR, dwSize);
+ if (ptdd == NULL)
+ {
+ log_error(errcode(ERRCODE_OUT_OF_MEMORY),
+ _("out of memory"));
+ goto cleanup;
+ }
+
+ if (!GetTokenInformation(hToken, tic, (LPVOID) ptdd, dwSize, &dwSize))
+ {
+ log_error(errcode(ERRCODE_SYSTEM_ERROR),
+ "could not get token information: error code %lu",
+ GetLastError());
+ goto cleanup;
+ }
+ }
+ else
+ {
+ log_error(errcode(ERRCODE_SYSTEM_ERROR),
+ "could not get token information buffer size: error code %lu",
+ GetLastError());
+ goto cleanup;
+ }
+ }
+
+ /* Get the ACL info */
+ if (!GetAclInformation(ptdd->DefaultDacl, (LPVOID) &asi,
+ (DWORD) sizeof(ACL_SIZE_INFORMATION),
+ AclSizeInformation))
+ {
+ log_error(errcode(ERRCODE_SYSTEM_ERROR),
+ "could not get ACL information: error code %lu",
+ GetLastError());
+ goto cleanup;
+ }
+
+ /* Get the current user SID */
+ if (!GetTokenUser(hToken, &pTokenUser))
+ goto cleanup; /* callee printed a message */
+
+ /* Figure out the size of the new ACL */
+ dwNewAclSize = asi.AclBytesInUse + sizeof(ACCESS_ALLOWED_ACE) +
+ GetLengthSid(pTokenUser->User.Sid) - sizeof(DWORD);
+
+ /* Allocate the ACL buffer & initialize it */
+ pacl = (PACL) LocalAlloc(LPTR, dwNewAclSize);
+ if (pacl == NULL)
+ {
+ log_error(errcode(ERRCODE_OUT_OF_MEMORY),
+ _("out of memory"));
+ goto cleanup;
+ }
+
+ if (!InitializeAcl(pacl, dwNewAclSize, ACL_REVISION))
+ {
+ log_error(errcode(ERRCODE_SYSTEM_ERROR),
+ "could not initialize ACL: error code %lu", GetLastError());
+ goto cleanup;
+ }
+
+ /* Loop through the existing ACEs, and build the new ACL */
+ for (i = 0; i < (int) asi.AceCount; i++)
+ {
+ if (!GetAce(ptdd->DefaultDacl, i, (LPVOID *) &pace))
+ {
+ log_error(errcode(ERRCODE_SYSTEM_ERROR),
+ "could not get ACE: error code %lu", GetLastError());
+ goto cleanup;
+ }
+
+ if (!AddAce(pacl, ACL_REVISION, MAXDWORD, pace, ((PACE_HEADER) pace)->AceSize))
+ {
+ log_error(errcode(ERRCODE_SYSTEM_ERROR),
+ "could not add ACE: error code %lu", GetLastError());
+ goto cleanup;
+ }
+ }
+
+ /* Add the new ACE for the current user */
+ if (!AddAccessAllowedAceEx(pacl, ACL_REVISION, OBJECT_INHERIT_ACE, GENERIC_ALL, pTokenUser->User.Sid))
+ {
+ log_error(errcode(ERRCODE_SYSTEM_ERROR),
+ "could not add access allowed ACE: error code %lu",
+ GetLastError());
+ goto cleanup;
+ }
+
+ /* Set the new DACL in the token */
+ tddNew.DefaultDacl = pacl;
+
+ if (!SetTokenInformation(hToken, tic, (LPVOID) &tddNew, dwNewAclSize))
+ {
+ log_error(errcode(ERRCODE_SYSTEM_ERROR),
+ "could not set token information: error code %lu",
+ GetLastError());
+ goto cleanup;
+ }
+
+ ret = TRUE;
+
+cleanup:
+ if (pTokenUser)
+ LocalFree((HLOCAL) pTokenUser);
+
+ if (pacl)
+ LocalFree((HLOCAL) pacl);
+
+ if (ptdd)
+ LocalFree((HLOCAL) ptdd);
+
+ return ret;
+}
+
+/*
+ * GetTokenUser(HANDLE hToken, PTOKEN_USER *ppTokenUser)
+ *
+ * Get the users token information from a process token.
+ *
+ * The caller of this function is responsible for calling LocalFree() on the
+ * returned TOKEN_USER memory.
+ */
+static BOOL
+GetTokenUser(HANDLE hToken, PTOKEN_USER *ppTokenUser)
+{
+ DWORD dwLength;
+
+ *ppTokenUser = NULL;
+
+ if (!GetTokenInformation(hToken,
+ TokenUser,
+ NULL,
+ 0,
+ &dwLength))
+ {
+ if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ {
+ *ppTokenUser = (PTOKEN_USER) LocalAlloc(LPTR, dwLength);
+
+ if (*ppTokenUser == NULL)
+ {
+ log_error(errcode(ERRCODE_OUT_OF_MEMORY),
+ _("out of memory"));
+ return FALSE;
+ }
+ }
+ else
+ {
+ log_error(errcode(ERRCODE_SYSTEM_ERROR),
+ "could not get token information buffer size: error code %lu",
+ GetLastError());
+ return FALSE;
+ }
+ }
+
+ if (!GetTokenInformation(hToken,
+ TokenUser,
+ *ppTokenUser,
+ dwLength,
+ &dwLength))
+ {
+ LocalFree(*ppTokenUser);
+ *ppTokenUser = NULL;
+
+ log_error(errcode(ERRCODE_SYSTEM_ERROR),
+ "could not get token information: error code %lu",
+ GetLastError());
+ return FALSE;
+ }
+
+ /* Memory in *ppTokenUser is LocalFree():d by the caller */
+ return TRUE;
+}
+
+#endif
diff --git a/contrib/libs/libpq/src/common/f2s.c b/contrib/libs/libpq/src/common/f2s.c
new file mode 100644
index 0000000000..ba08dcb6aa
--- /dev/null
+++ b/contrib/libs/libpq/src/common/f2s.c
@@ -0,0 +1,803 @@
+/*---------------------------------------------------------------------------
+ *
+ * Ryu floating-point output for single precision.
+ *
+ * Portions Copyright (c) 2018-2023, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/common/f2s.c
+ *
+ * This is a modification of code taken from github.com/ulfjack/ryu under the
+ * terms of the Boost license (not the Apache license). The original copyright
+ * notice follows:
+ *
+ * Copyright 2018 Ulf Adams
+ *
+ * The contents of this file may be used under the terms of the Apache
+ * License, Version 2.0.
+ *
+ * (See accompanying file LICENSE-Apache or copy at
+ * http://www.apache.org/licenses/LICENSE-2.0)
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * Boost Software License, Version 1.0.
+ *
+ * (See accompanying file LICENSE-Boost or copy at
+ * https://www.boost.org/LICENSE_1_0.txt)
+ *
+ * Unless required by applicable law or agreed to in writing, this software is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#include "common/shortest_dec.h"
+#include "digit_table.h"
+#include "ryu_common.h"
+
+#define FLOAT_MANTISSA_BITS 23
+#define FLOAT_EXPONENT_BITS 8
+#define FLOAT_BIAS 127
+
+/*
+ * This table is generated (by the upstream) by PrintFloatLookupTable,
+ * and modified (by us) to add UINT64CONST.
+ */
+#define FLOAT_POW5_INV_BITCOUNT 59
+static const uint64 FLOAT_POW5_INV_SPLIT[31] = {
+ UINT64CONST(576460752303423489), UINT64CONST(461168601842738791), UINT64CONST(368934881474191033), UINT64CONST(295147905179352826),
+ UINT64CONST(472236648286964522), UINT64CONST(377789318629571618), UINT64CONST(302231454903657294), UINT64CONST(483570327845851670),
+ UINT64CONST(386856262276681336), UINT64CONST(309485009821345069), UINT64CONST(495176015714152110), UINT64CONST(396140812571321688),
+ UINT64CONST(316912650057057351), UINT64CONST(507060240091291761), UINT64CONST(405648192073033409), UINT64CONST(324518553658426727),
+ UINT64CONST(519229685853482763), UINT64CONST(415383748682786211), UINT64CONST(332306998946228969), UINT64CONST(531691198313966350),
+ UINT64CONST(425352958651173080), UINT64CONST(340282366920938464), UINT64CONST(544451787073501542), UINT64CONST(435561429658801234),
+ UINT64CONST(348449143727040987), UINT64CONST(557518629963265579), UINT64CONST(446014903970612463), UINT64CONST(356811923176489971),
+ UINT64CONST(570899077082383953), UINT64CONST(456719261665907162), UINT64CONST(365375409332725730)
+};
+#define FLOAT_POW5_BITCOUNT 61
+static const uint64 FLOAT_POW5_SPLIT[47] = {
+ UINT64CONST(1152921504606846976), UINT64CONST(1441151880758558720), UINT64CONST(1801439850948198400), UINT64CONST(2251799813685248000),
+ UINT64CONST(1407374883553280000), UINT64CONST(1759218604441600000), UINT64CONST(2199023255552000000), UINT64CONST(1374389534720000000),
+ UINT64CONST(1717986918400000000), UINT64CONST(2147483648000000000), UINT64CONST(1342177280000000000), UINT64CONST(1677721600000000000),
+ UINT64CONST(2097152000000000000), UINT64CONST(1310720000000000000), UINT64CONST(1638400000000000000), UINT64CONST(2048000000000000000),
+ UINT64CONST(1280000000000000000), UINT64CONST(1600000000000000000), UINT64CONST(2000000000000000000), UINT64CONST(1250000000000000000),
+ UINT64CONST(1562500000000000000), UINT64CONST(1953125000000000000), UINT64CONST(1220703125000000000), UINT64CONST(1525878906250000000),
+ UINT64CONST(1907348632812500000), UINT64CONST(1192092895507812500), UINT64CONST(1490116119384765625), UINT64CONST(1862645149230957031),
+ UINT64CONST(1164153218269348144), UINT64CONST(1455191522836685180), UINT64CONST(1818989403545856475), UINT64CONST(2273736754432320594),
+ UINT64CONST(1421085471520200371), UINT64CONST(1776356839400250464), UINT64CONST(2220446049250313080), UINT64CONST(1387778780781445675),
+ UINT64CONST(1734723475976807094), UINT64CONST(2168404344971008868), UINT64CONST(1355252715606880542), UINT64CONST(1694065894508600678),
+ UINT64CONST(2117582368135750847), UINT64CONST(1323488980084844279), UINT64CONST(1654361225106055349), UINT64CONST(2067951531382569187),
+ UINT64CONST(1292469707114105741), UINT64CONST(1615587133892632177), UINT64CONST(2019483917365790221)
+};
+
+static inline uint32
+pow5Factor(uint32 value)
+{
+ uint32 count = 0;
+
+ for (;;)
+ {
+ Assert(value != 0);
+ const uint32 q = value / 5;
+ const uint32 r = value % 5;
+
+ if (r != 0)
+ break;
+
+ value = q;
+ ++count;
+ }
+ return count;
+}
+
+/* Returns true if value is divisible by 5^p. */
+static inline bool
+multipleOfPowerOf5(const uint32 value, const uint32 p)
+{
+ return pow5Factor(value) >= p;
+}
+
+/* Returns true if value is divisible by 2^p. */
+static inline bool
+multipleOfPowerOf2(const uint32 value, const uint32 p)
+{
+ /* return __builtin_ctz(value) >= p; */
+ return (value & ((1u << p) - 1)) == 0;
+}
+
+/*
+ * It seems to be slightly faster to avoid uint128_t here, although the
+ * generated code for uint128_t looks slightly nicer.
+ */
+static inline uint32
+mulShift(const uint32 m, const uint64 factor, const int32 shift)
+{
+ /*
+ * The casts here help MSVC to avoid calls to the __allmul library
+ * function.
+ */
+ const uint32 factorLo = (uint32) (factor);
+ const uint32 factorHi = (uint32) (factor >> 32);
+ const uint64 bits0 = (uint64) m * factorLo;
+ const uint64 bits1 = (uint64) m * factorHi;
+
+ Assert(shift > 32);
+
+#ifdef RYU_32_BIT_PLATFORM
+
+ /*
+ * On 32-bit platforms we can avoid a 64-bit shift-right since we only
+ * need the upper 32 bits of the result and the shift value is > 32.
+ */
+ const uint32 bits0Hi = (uint32) (bits0 >> 32);
+ uint32 bits1Lo = (uint32) (bits1);
+ uint32 bits1Hi = (uint32) (bits1 >> 32);
+
+ bits1Lo += bits0Hi;
+ bits1Hi += (bits1Lo < bits0Hi);
+
+ const int32 s = shift - 32;
+
+ return (bits1Hi << (32 - s)) | (bits1Lo >> s);
+
+#else /* RYU_32_BIT_PLATFORM */
+
+ const uint64 sum = (bits0 >> 32) + bits1;
+ const uint64 shiftedSum = sum >> (shift - 32);
+
+ Assert(shiftedSum <= PG_UINT32_MAX);
+ return (uint32) shiftedSum;
+
+#endif /* RYU_32_BIT_PLATFORM */
+}
+
+static inline uint32
+mulPow5InvDivPow2(const uint32 m, const uint32 q, const int32 j)
+{
+ return mulShift(m, FLOAT_POW5_INV_SPLIT[q], j);
+}
+
+static inline uint32
+mulPow5divPow2(const uint32 m, const uint32 i, const int32 j)
+{
+ return mulShift(m, FLOAT_POW5_SPLIT[i], j);
+}
+
+static inline uint32
+decimalLength(const uint32 v)
+{
+ /* Function precondition: v is not a 10-digit number. */
+ /* (9 digits are sufficient for round-tripping.) */
+ Assert(v < 1000000000);
+ if (v >= 100000000)
+ {
+ return 9;
+ }
+ if (v >= 10000000)
+ {
+ return 8;
+ }
+ if (v >= 1000000)
+ {
+ return 7;
+ }
+ if (v >= 100000)
+ {
+ return 6;
+ }
+ if (v >= 10000)
+ {
+ return 5;
+ }
+ if (v >= 1000)
+ {
+ return 4;
+ }
+ if (v >= 100)
+ {
+ return 3;
+ }
+ if (v >= 10)
+ {
+ return 2;
+ }
+ return 1;
+}
+
+/* A floating decimal representing m * 10^e. */
+typedef struct floating_decimal_32
+{
+ uint32 mantissa;
+ int32 exponent;
+} floating_decimal_32;
+
+static inline floating_decimal_32
+f2d(const uint32 ieeeMantissa, const uint32 ieeeExponent)
+{
+ int32 e2;
+ uint32 m2;
+
+ if (ieeeExponent == 0)
+ {
+ /* We subtract 2 so that the bounds computation has 2 additional bits. */
+ e2 = 1 - FLOAT_BIAS - FLOAT_MANTISSA_BITS - 2;
+ m2 = ieeeMantissa;
+ }
+ else
+ {
+ e2 = ieeeExponent - FLOAT_BIAS - FLOAT_MANTISSA_BITS - 2;
+ m2 = (1u << FLOAT_MANTISSA_BITS) | ieeeMantissa;
+ }
+
+#if STRICTLY_SHORTEST
+ const bool even = (m2 & 1) == 0;
+ const bool acceptBounds = even;
+#else
+ const bool acceptBounds = false;
+#endif
+
+ /* Step 2: Determine the interval of legal decimal representations. */
+ const uint32 mv = 4 * m2;
+ const uint32 mp = 4 * m2 + 2;
+
+ /* Implicit bool -> int conversion. True is 1, false is 0. */
+ const uint32 mmShift = ieeeMantissa != 0 || ieeeExponent <= 1;
+ const uint32 mm = 4 * m2 - 1 - mmShift;
+
+ /* Step 3: Convert to a decimal power base using 64-bit arithmetic. */
+ uint32 vr,
+ vp,
+ vm;
+ int32 e10;
+ bool vmIsTrailingZeros = false;
+ bool vrIsTrailingZeros = false;
+ uint8 lastRemovedDigit = 0;
+
+ if (e2 >= 0)
+ {
+ const uint32 q = log10Pow2(e2);
+
+ e10 = q;
+
+ const int32 k = FLOAT_POW5_INV_BITCOUNT + pow5bits(q) - 1;
+ const int32 i = -e2 + q + k;
+
+ vr = mulPow5InvDivPow2(mv, q, i);
+ vp = mulPow5InvDivPow2(mp, q, i);
+ vm = mulPow5InvDivPow2(mm, q, i);
+
+ if (q != 0 && (vp - 1) / 10 <= vm / 10)
+ {
+ /*
+ * We need to know one removed digit even if we are not going to
+ * loop below. We could use q = X - 1 above, except that would
+ * require 33 bits for the result, and we've found that 32-bit
+ * arithmetic is faster even on 64-bit machines.
+ */
+ const int32 l = FLOAT_POW5_INV_BITCOUNT + pow5bits(q - 1) - 1;
+
+ lastRemovedDigit = (uint8) (mulPow5InvDivPow2(mv, q - 1, -e2 + q - 1 + l) % 10);
+ }
+ if (q <= 9)
+ {
+ /*
+ * The largest power of 5 that fits in 24 bits is 5^10, but q <= 9
+ * seems to be safe as well.
+ *
+ * Only one of mp, mv, and mm can be a multiple of 5, if any.
+ */
+ if (mv % 5 == 0)
+ {
+ vrIsTrailingZeros = multipleOfPowerOf5(mv, q);
+ }
+ else if (acceptBounds)
+ {
+ vmIsTrailingZeros = multipleOfPowerOf5(mm, q);
+ }
+ else
+ {
+ vp -= multipleOfPowerOf5(mp, q);
+ }
+ }
+ }
+ else
+ {
+ const uint32 q = log10Pow5(-e2);
+
+ e10 = q + e2;
+
+ const int32 i = -e2 - q;
+ const int32 k = pow5bits(i) - FLOAT_POW5_BITCOUNT;
+ int32 j = q - k;
+
+ vr = mulPow5divPow2(mv, i, j);
+ vp = mulPow5divPow2(mp, i, j);
+ vm = mulPow5divPow2(mm, i, j);
+
+ if (q != 0 && (vp - 1) / 10 <= vm / 10)
+ {
+ j = q - 1 - (pow5bits(i + 1) - FLOAT_POW5_BITCOUNT);
+ lastRemovedDigit = (uint8) (mulPow5divPow2(mv, i + 1, j) % 10);
+ }
+ if (q <= 1)
+ {
+ /*
+ * {vr,vp,vm} is trailing zeros if {mv,mp,mm} has at least q
+ * trailing 0 bits.
+ */
+ /* mv = 4 * m2, so it always has at least two trailing 0 bits. */
+ vrIsTrailingZeros = true;
+ if (acceptBounds)
+ {
+ /*
+ * mm = mv - 1 - mmShift, so it has 1 trailing 0 bit iff
+ * mmShift == 1.
+ */
+ vmIsTrailingZeros = mmShift == 1;
+ }
+ else
+ {
+ /*
+ * mp = mv + 2, so it always has at least one trailing 0 bit.
+ */
+ --vp;
+ }
+ }
+ else if (q < 31)
+ {
+ /* TODO(ulfjack):Use a tighter bound here. */
+ vrIsTrailingZeros = multipleOfPowerOf2(mv, q - 1);
+ }
+ }
+
+ /*
+ * Step 4: Find the shortest decimal representation in the interval of
+ * legal representations.
+ */
+ uint32 removed = 0;
+ uint32 output;
+
+ if (vmIsTrailingZeros || vrIsTrailingZeros)
+ {
+ /* General case, which happens rarely (~4.0%). */
+ while (vp / 10 > vm / 10)
+ {
+ vmIsTrailingZeros &= vm - (vm / 10) * 10 == 0;
+ vrIsTrailingZeros &= lastRemovedDigit == 0;
+ lastRemovedDigit = (uint8) (vr % 10);
+ vr /= 10;
+ vp /= 10;
+ vm /= 10;
+ ++removed;
+ }
+ if (vmIsTrailingZeros)
+ {
+ while (vm % 10 == 0)
+ {
+ vrIsTrailingZeros &= lastRemovedDigit == 0;
+ lastRemovedDigit = (uint8) (vr % 10);
+ vr /= 10;
+ vp /= 10;
+ vm /= 10;
+ ++removed;
+ }
+ }
+
+ if (vrIsTrailingZeros && lastRemovedDigit == 5 && vr % 2 == 0)
+ {
+ /* Round even if the exact number is .....50..0. */
+ lastRemovedDigit = 4;
+ }
+
+ /*
+ * We need to take vr + 1 if vr is outside bounds or we need to round
+ * up.
+ */
+ output = vr + ((vr == vm && (!acceptBounds || !vmIsTrailingZeros)) || lastRemovedDigit >= 5);
+ }
+ else
+ {
+ /*
+ * Specialized for the common case (~96.0%). Percentages below are
+ * relative to this.
+ *
+ * Loop iterations below (approximately): 0: 13.6%, 1: 70.7%, 2:
+ * 14.1%, 3: 1.39%, 4: 0.14%, 5+: 0.01%
+ */
+ while (vp / 10 > vm / 10)
+ {
+ lastRemovedDigit = (uint8) (vr % 10);
+ vr /= 10;
+ vp /= 10;
+ vm /= 10;
+ ++removed;
+ }
+
+ /*
+ * We need to take vr + 1 if vr is outside bounds or we need to round
+ * up.
+ */
+ output = vr + (vr == vm || lastRemovedDigit >= 5);
+ }
+
+ const int32 exp = e10 + removed;
+
+ floating_decimal_32 fd;
+
+ fd.exponent = exp;
+ fd.mantissa = output;
+ return fd;
+}
+
+static inline int
+to_chars_f(const floating_decimal_32 v, const uint32 olength, char *const result)
+{
+ /* Step 5: Print the decimal representation. */
+ int index = 0;
+
+ uint32 output = v.mantissa;
+ int32 exp = v.exponent;
+
+ /*----
+ * On entry, mantissa * 10^exp is the result to be output.
+ * Caller has already done the - sign if needed.
+ *
+ * We want to insert the point somewhere depending on the output length
+ * and exponent, which might mean adding zeros:
+ *
+ * exp | format
+ * 1+ | ddddddddd000000
+ * 0 | ddddddddd
+ * -1 .. -len+1 | dddddddd.d to d.ddddddddd
+ * -len ... | 0.ddddddddd to 0.000dddddd
+ */
+ uint32 i = 0;
+ int32 nexp = exp + olength;
+
+ if (nexp <= 0)
+ {
+ /* -nexp is number of 0s to add after '.' */
+ Assert(nexp >= -3);
+ /* 0.000ddddd */
+ index = 2 - nexp;
+ /* copy 8 bytes rather than 5 to let compiler optimize */
+ memcpy(result, "0.000000", 8);
+ }
+ else if (exp < 0)
+ {
+ /*
+ * dddd.dddd; leave space at the start and move the '.' in after
+ */
+ index = 1;
+ }
+ else
+ {
+ /*
+ * We can save some code later by pre-filling with zeros. We know that
+ * there can be no more than 6 output digits in this form, otherwise
+ * we would not choose fixed-point output. memset 8 rather than 6
+ * bytes to let the compiler optimize it.
+ */
+ Assert(exp < 6 && exp + olength <= 6);
+ memset(result, '0', 8);
+ }
+
+ while (output >= 10000)
+ {
+ const uint32 c = output - 10000 * (output / 10000);
+ const uint32 c0 = (c % 100) << 1;
+ const uint32 c1 = (c / 100) << 1;
+
+ output /= 10000;
+
+ memcpy(result + index + olength - i - 2, DIGIT_TABLE + c0, 2);
+ memcpy(result + index + olength - i - 4, DIGIT_TABLE + c1, 2);
+ i += 4;
+ }
+ if (output >= 100)
+ {
+ const uint32 c = (output % 100) << 1;
+
+ output /= 100;
+ memcpy(result + index + olength - i - 2, DIGIT_TABLE + c, 2);
+ i += 2;
+ }
+ if (output >= 10)
+ {
+ const uint32 c = output << 1;
+
+ memcpy(result + index + olength - i - 2, DIGIT_TABLE + c, 2);
+ }
+ else
+ {
+ result[index] = (char) ('0' + output);
+ }
+
+ if (index == 1)
+ {
+ /*
+ * nexp is 1..6 here, representing the number of digits before the
+ * point. A value of 7+ is not possible because we switch to
+ * scientific notation when the display exponent reaches 6.
+ */
+ Assert(nexp < 7);
+ /* gcc only seems to want to optimize memmove for small 2^n */
+ if (nexp & 4)
+ {
+ memmove(result + index - 1, result + index, 4);
+ index += 4;
+ }
+ if (nexp & 2)
+ {
+ memmove(result + index - 1, result + index, 2);
+ index += 2;
+ }
+ if (nexp & 1)
+ {
+ result[index - 1] = result[index];
+ }
+ result[nexp] = '.';
+ index = olength + 1;
+ }
+ else if (exp >= 0)
+ {
+ /* we supplied the trailing zeros earlier, now just set the length. */
+ index = olength + exp;
+ }
+ else
+ {
+ index = olength + (2 - nexp);
+ }
+
+ return index;
+}
+
+static inline int
+to_chars(const floating_decimal_32 v, const bool sign, char *const result)
+{
+ /* Step 5: Print the decimal representation. */
+ int index = 0;
+
+ uint32 output = v.mantissa;
+ uint32 olength = decimalLength(output);
+ int32 exp = v.exponent + olength - 1;
+
+ if (sign)
+ result[index++] = '-';
+
+ /*
+ * The thresholds for fixed-point output are chosen to match printf
+ * defaults. Beware that both the code of to_chars_f and the value of
+ * FLOAT_SHORTEST_DECIMAL_LEN are sensitive to these thresholds.
+ */
+ if (exp >= -4 && exp < 6)
+ return to_chars_f(v, olength, result + index) + sign;
+
+ /*
+ * If v.exponent is exactly 0, we might have reached here via the small
+ * integer fast path, in which case v.mantissa might contain trailing
+ * (decimal) zeros. For scientific notation we need to move these zeros
+ * into the exponent. (For fixed point this doesn't matter, which is why
+ * we do this here rather than above.)
+ *
+ * Since we already calculated the display exponent (exp) above based on
+ * the old decimal length, that value does not change here. Instead, we
+ * just reduce the display length for each digit removed.
+ *
+ * If we didn't get here via the fast path, the raw exponent will not
+ * usually be 0, and there will be no trailing zeros, so we pay no more
+ * than one div10/multiply extra cost. We claw back half of that by
+ * checking for divisibility by 2 before dividing by 10.
+ */
+ if (v.exponent == 0)
+ {
+ while ((output & 1) == 0)
+ {
+ const uint32 q = output / 10;
+ const uint32 r = output - 10 * q;
+
+ if (r != 0)
+ break;
+ output = q;
+ --olength;
+ }
+ }
+
+ /*----
+ * Print the decimal digits.
+ * The following code is equivalent to:
+ *
+ * for (uint32 i = 0; i < olength - 1; ++i) {
+ * const uint32 c = output % 10; output /= 10;
+ * result[index + olength - i] = (char) ('0' + c);
+ * }
+ * result[index] = '0' + output % 10;
+ */
+ uint32 i = 0;
+
+ while (output >= 10000)
+ {
+ const uint32 c = output - 10000 * (output / 10000);
+ const uint32 c0 = (c % 100) << 1;
+ const uint32 c1 = (c / 100) << 1;
+
+ output /= 10000;
+
+ memcpy(result + index + olength - i - 1, DIGIT_TABLE + c0, 2);
+ memcpy(result + index + olength - i - 3, DIGIT_TABLE + c1, 2);
+ i += 4;
+ }
+ if (output >= 100)
+ {
+ const uint32 c = (output % 100) << 1;
+
+ output /= 100;
+ memcpy(result + index + olength - i - 1, DIGIT_TABLE + c, 2);
+ i += 2;
+ }
+ if (output >= 10)
+ {
+ const uint32 c = output << 1;
+
+ /*
+ * We can't use memcpy here: the decimal dot goes between these two
+ * digits.
+ */
+ result[index + olength - i] = DIGIT_TABLE[c + 1];
+ result[index] = DIGIT_TABLE[c];
+ }
+ else
+ {
+ result[index] = (char) ('0' + output);
+ }
+
+ /* Print decimal point if needed. */
+ if (olength > 1)
+ {
+ result[index + 1] = '.';
+ index += olength + 1;
+ }
+ else
+ {
+ ++index;
+ }
+
+ /* Print the exponent. */
+ result[index++] = 'e';
+ if (exp < 0)
+ {
+ result[index++] = '-';
+ exp = -exp;
+ }
+ else
+ result[index++] = '+';
+
+ memcpy(result + index, DIGIT_TABLE + 2 * exp, 2);
+ index += 2;
+
+ return index;
+}
+
+static inline bool
+f2d_small_int(const uint32 ieeeMantissa,
+ const uint32 ieeeExponent,
+ floating_decimal_32 *v)
+{
+ const int32 e2 = (int32) ieeeExponent - FLOAT_BIAS - FLOAT_MANTISSA_BITS;
+
+ /*
+ * Avoid using multiple "return false;" here since it tends to provoke the
+ * compiler into inlining multiple copies of f2d, which is undesirable.
+ */
+
+ if (e2 >= -FLOAT_MANTISSA_BITS && e2 <= 0)
+ {
+ /*----
+ * Since 2^23 <= m2 < 2^24 and 0 <= -e2 <= 23:
+ * 1 <= f = m2 / 2^-e2 < 2^24.
+ *
+ * Test if the lower -e2 bits of the significand are 0, i.e. whether
+ * the fraction is 0. We can use ieeeMantissa here, since the implied
+ * 1 bit can never be tested by this; the implied 1 can only be part
+ * of a fraction if e2 < -FLOAT_MANTISSA_BITS which we already
+ * checked. (e.g. 0.5 gives ieeeMantissa == 0 and e2 == -24)
+ */
+ const uint32 mask = (1U << -e2) - 1;
+ const uint32 fraction = ieeeMantissa & mask;
+
+ if (fraction == 0)
+ {
+ /*----
+ * f is an integer in the range [1, 2^24).
+ * Note: mantissa might contain trailing (decimal) 0's.
+ * Note: since 2^24 < 10^9, there is no need to adjust
+ * decimalLength().
+ */
+ const uint32 m2 = (1U << FLOAT_MANTISSA_BITS) | ieeeMantissa;
+
+ v->mantissa = m2 >> -e2;
+ v->exponent = 0;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/*
+ * Store the shortest decimal representation of the given float as an
+ * UNTERMINATED string in the caller's supplied buffer (which must be at least
+ * FLOAT_SHORTEST_DECIMAL_LEN-1 bytes long).
+ *
+ * Returns the number of bytes stored.
+ */
+int
+float_to_shortest_decimal_bufn(float f, char *result)
+{
+ /*
+ * Step 1: Decode the floating-point number, and unify normalized and
+ * subnormal cases.
+ */
+ const uint32 bits = float_to_bits(f);
+
+ /* Decode bits into sign, mantissa, and exponent. */
+ const bool ieeeSign = ((bits >> (FLOAT_MANTISSA_BITS + FLOAT_EXPONENT_BITS)) & 1) != 0;
+ const uint32 ieeeMantissa = bits & ((1u << FLOAT_MANTISSA_BITS) - 1);
+ const uint32 ieeeExponent = (bits >> FLOAT_MANTISSA_BITS) & ((1u << FLOAT_EXPONENT_BITS) - 1);
+
+ /* Case distinction; exit early for the easy cases. */
+ if (ieeeExponent == ((1u << FLOAT_EXPONENT_BITS) - 1u) || (ieeeExponent == 0 && ieeeMantissa == 0))
+ {
+ return copy_special_str(result, ieeeSign, (ieeeExponent != 0), (ieeeMantissa != 0));
+ }
+
+ floating_decimal_32 v;
+ const bool isSmallInt = f2d_small_int(ieeeMantissa, ieeeExponent, &v);
+
+ if (!isSmallInt)
+ {
+ v = f2d(ieeeMantissa, ieeeExponent);
+ }
+
+ return to_chars(v, ieeeSign, result);
+}
+
+/*
+ * Store the shortest decimal representation of the given float as a
+ * null-terminated string in the caller's supplied buffer (which must be at
+ * least FLOAT_SHORTEST_DECIMAL_LEN bytes long).
+ *
+ * Returns the string length.
+ */
+int
+float_to_shortest_decimal_buf(float f, char *result)
+{
+ const int index = float_to_shortest_decimal_bufn(f, result);
+
+ /* Terminate the string. */
+ Assert(index < FLOAT_SHORTEST_DECIMAL_LEN);
+ result[index] = '\0';
+ return index;
+}
+
+/*
+ * Return the shortest decimal representation as a null-terminated palloc'd
+ * string (outside the backend, uses malloc() instead).
+ *
+ * Caller is responsible for freeing the result.
+ */
+char *
+float_to_shortest_decimal(float f)
+{
+ char *const result = (char *) palloc(FLOAT_SHORTEST_DECIMAL_LEN);
+
+ float_to_shortest_decimal_buf(f, result);
+ return result;
+}
diff --git a/contrib/libs/libpq/src/common/fe_memutils.c b/contrib/libs/libpq/src/common/fe_memutils.c
new file mode 100644
index 0000000000..3bad81eafc
--- /dev/null
+++ b/contrib/libs/libpq/src/common/fe_memutils.c
@@ -0,0 +1,175 @@
+/*-------------------------------------------------------------------------
+ *
+ * fe_memutils.c
+ * memory management support for frontend code
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/common/fe_memutils.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+#error "This file is not expected to be compiled for backend code"
+#endif
+
+#include "postgres_fe.h"
+
+static inline void *
+pg_malloc_internal(size_t size, int flags)
+{
+ void *tmp;
+
+ /* Avoid unportable behavior of malloc(0) */
+ if (size == 0)
+ size = 1;
+ tmp = malloc(size);
+ if (tmp == NULL)
+ {
+ if ((flags & MCXT_ALLOC_NO_OOM) == 0)
+ {
+ fprintf(stderr, _("out of memory\n"));
+ exit(EXIT_FAILURE);
+ }
+ return NULL;
+ }
+
+ if ((flags & MCXT_ALLOC_ZERO) != 0)
+ MemSet(tmp, 0, size);
+ return tmp;
+}
+
+void *
+pg_malloc(size_t size)
+{
+ return pg_malloc_internal(size, 0);
+}
+
+void *
+pg_malloc0(size_t size)
+{
+ return pg_malloc_internal(size, MCXT_ALLOC_ZERO);
+}
+
+void *
+pg_malloc_extended(size_t size, int flags)
+{
+ return pg_malloc_internal(size, flags);
+}
+
+void *
+pg_realloc(void *ptr, size_t size)
+{
+ void *tmp;
+
+ /* Avoid unportable behavior of realloc(NULL, 0) */
+ if (ptr == NULL && size == 0)
+ size = 1;
+ tmp = realloc(ptr, size);
+ if (!tmp)
+ {
+ fprintf(stderr, _("out of memory\n"));
+ exit(EXIT_FAILURE);
+ }
+ return tmp;
+}
+
+/*
+ * "Safe" wrapper around strdup().
+ */
+char *
+pg_strdup(const char *in)
+{
+ char *tmp;
+
+ if (!in)
+ {
+ fprintf(stderr,
+ _("cannot duplicate null pointer (internal error)\n"));
+ exit(EXIT_FAILURE);
+ }
+ tmp = strdup(in);
+ if (!tmp)
+ {
+ fprintf(stderr, _("out of memory\n"));
+ exit(EXIT_FAILURE);
+ }
+ return tmp;
+}
+
+void
+pg_free(void *ptr)
+{
+ free(ptr);
+}
+
+/*
+ * Frontend emulation of backend memory management functions. Useful for
+ * programs that compile backend files.
+ */
+void *
+palloc(Size size)
+{
+ return pg_malloc_internal(size, 0);
+}
+
+void *
+palloc0(Size size)
+{
+ return pg_malloc_internal(size, MCXT_ALLOC_ZERO);
+}
+
+void *
+palloc_extended(Size size, int flags)
+{
+ return pg_malloc_internal(size, flags);
+}
+
+void
+pfree(void *pointer)
+{
+ pg_free(pointer);
+}
+
+char *
+pstrdup(const char *in)
+{
+ return pg_strdup(in);
+}
+
+char *
+pnstrdup(const char *in, Size size)
+{
+ char *tmp;
+ int len;
+
+ if (!in)
+ {
+ fprintf(stderr,
+ _("cannot duplicate null pointer (internal error)\n"));
+ exit(EXIT_FAILURE);
+ }
+
+ len = strnlen(in, size);
+ tmp = malloc(len + 1);
+ if (tmp == NULL)
+ {
+ fprintf(stderr, _("out of memory\n"));
+ exit(EXIT_FAILURE);
+ }
+
+ memcpy(tmp, in, len);
+ tmp[len] = '\0';
+
+ return tmp;
+}
+
+void *
+repalloc(void *pointer, Size size)
+{
+ return pg_realloc(pointer, size);
+}
diff --git a/contrib/libs/libpq/src/common/file_perm.c b/contrib/libs/libpq/src/common/file_perm.c
new file mode 100644
index 0000000000..60f88d2caf
--- /dev/null
+++ b/contrib/libs/libpq/src/common/file_perm.c
@@ -0,0 +1,91 @@
+/*-------------------------------------------------------------------------
+ *
+ * File and directory permission routines
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/common/file_perm.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "c.h"
+
+#include "common/file_perm.h"
+
+/* Modes for creating directories and files in the data directory */
+int pg_dir_create_mode = PG_DIR_MODE_OWNER;
+int pg_file_create_mode = PG_FILE_MODE_OWNER;
+
+/*
+ * Mode mask to pass to umask(). This is more of a preventative measure since
+ * all file/directory creates should be performed using the create modes above.
+ */
+int pg_mode_mask = PG_MODE_MASK_OWNER;
+
+/*
+ * Set create modes and mask to use when writing to PGDATA based on the data
+ * directory mode passed. If group read/execute are present in the mode, then
+ * create modes and mask will be relaxed to allow group read/execute on all
+ * newly created files and directories.
+ */
+void
+SetDataDirectoryCreatePerm(int dataDirMode)
+{
+ /* If the data directory mode has group access */
+ if ((PG_DIR_MODE_GROUP & dataDirMode) == PG_DIR_MODE_GROUP)
+ {
+ pg_dir_create_mode = PG_DIR_MODE_GROUP;
+ pg_file_create_mode = PG_FILE_MODE_GROUP;
+ pg_mode_mask = PG_MODE_MASK_GROUP;
+ }
+ /* Else use default permissions */
+ else
+ {
+ pg_dir_create_mode = PG_DIR_MODE_OWNER;
+ pg_file_create_mode = PG_FILE_MODE_OWNER;
+ pg_mode_mask = PG_MODE_MASK_OWNER;
+ }
+}
+
+#ifdef FRONTEND
+
+/*
+ * Get the create modes and mask to use when writing to PGDATA by examining the
+ * mode of the PGDATA directory and calling SetDataDirectoryCreatePerm().
+ *
+ * Errors are not handled here and should be reported by the application when
+ * false is returned.
+ *
+ * Suppress when on Windows, because there may not be proper support for Unix-y
+ * file permissions.
+ */
+bool
+GetDataDirectoryCreatePerm(const char *dataDir)
+{
+#if !defined(WIN32) && !defined(__CYGWIN__)
+ struct stat statBuf;
+
+ /*
+ * If an error occurs getting the mode then return false. The caller is
+ * responsible for generating an error, if appropriate, indicating that we
+ * were unable to access the data directory.
+ */
+ if (stat(dataDir, &statBuf) == -1)
+ return false;
+
+ /* Set permissions */
+ SetDataDirectoryCreatePerm(statBuf.st_mode);
+ return true;
+#else /* !defined(WIN32) && !defined(__CYGWIN__) */
+ /*
+ * On Windows, we don't have anything to do here since they don't have
+ * Unix-y permissions.
+ */
+ return true;
+#endif
+}
+
+
+#endif /* FRONTEND */
diff --git a/contrib/libs/libpq/src/common/file_utils.c b/contrib/libs/libpq/src/common/file_utils.c
new file mode 100644
index 0000000000..74833c4acb
--- /dev/null
+++ b/contrib/libs/libpq/src/common/file_utils.c
@@ -0,0 +1,582 @@
+/*-------------------------------------------------------------------------
+ *
+ * File-processing utility routines.
+ *
+ * Assorted utility functions to work on files.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/common/file_utils.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#include <dirent.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "common/file_utils.h"
+#ifdef FRONTEND
+#include "common/logging.h"
+#endif
+#include "port/pg_iovec.h"
+
+#ifdef FRONTEND
+
+/* Define PG_FLUSH_DATA_WORKS if we have an implementation for pg_flush_data */
+#if defined(HAVE_SYNC_FILE_RANGE)
+#define PG_FLUSH_DATA_WORKS 1
+#elif defined(USE_POSIX_FADVISE) && defined(POSIX_FADV_DONTNEED)
+#define PG_FLUSH_DATA_WORKS 1
+#endif
+
+/*
+ * pg_xlog has been renamed to pg_wal in version 10.
+ */
+#define MINIMUM_VERSION_FOR_PG_WAL 100000
+
+#ifdef PG_FLUSH_DATA_WORKS
+static int pre_sync_fname(const char *fname, bool isdir);
+#endif
+static void walkdir(const char *path,
+ int (*action) (const char *fname, bool isdir),
+ bool process_symlinks);
+
+/*
+ * Issue fsync recursively on PGDATA and all its contents.
+ *
+ * We fsync regular files and directories wherever they are, but we follow
+ * symlinks only for pg_wal (or pg_xlog) and immediately under pg_tblspc.
+ * Other symlinks are presumed to point at files we're not responsible for
+ * fsyncing, and might not have privileges to write at all.
+ *
+ * serverVersion indicates the version of the server to be fsync'd.
+ */
+void
+fsync_pgdata(const char *pg_data,
+ int serverVersion)
+{
+ bool xlog_is_symlink;
+ char pg_wal[MAXPGPATH];
+ char pg_tblspc[MAXPGPATH];
+
+ /* handle renaming of pg_xlog to pg_wal in post-10 clusters */
+ snprintf(pg_wal, MAXPGPATH, "%s/%s", pg_data,
+ serverVersion < MINIMUM_VERSION_FOR_PG_WAL ? "pg_xlog" : "pg_wal");
+ snprintf(pg_tblspc, MAXPGPATH, "%s/pg_tblspc", pg_data);
+
+ /*
+ * If pg_wal is a symlink, we'll need to recurse into it separately,
+ * because the first walkdir below will ignore it.
+ */
+ xlog_is_symlink = false;
+
+ {
+ struct stat st;
+
+ if (lstat(pg_wal, &st) < 0)
+ pg_log_error("could not stat file \"%s\": %m", pg_wal);
+ else if (S_ISLNK(st.st_mode))
+ xlog_is_symlink = true;
+ }
+
+ /*
+ * If possible, hint to the kernel that we're soon going to fsync the data
+ * directory and its contents.
+ */
+#ifdef PG_FLUSH_DATA_WORKS
+ walkdir(pg_data, pre_sync_fname, false);
+ if (xlog_is_symlink)
+ walkdir(pg_wal, pre_sync_fname, false);
+ walkdir(pg_tblspc, pre_sync_fname, true);
+#endif
+
+ /*
+ * Now we do the fsync()s in the same order.
+ *
+ * The main call ignores symlinks, so in addition to specially processing
+ * pg_wal if it's a symlink, pg_tblspc has to be visited separately with
+ * process_symlinks = true. Note that if there are any plain directories
+ * in pg_tblspc, they'll get fsync'd twice. That's not an expected case
+ * so we don't worry about optimizing it.
+ */
+ walkdir(pg_data, fsync_fname, false);
+ if (xlog_is_symlink)
+ walkdir(pg_wal, fsync_fname, false);
+ walkdir(pg_tblspc, fsync_fname, true);
+}
+
+/*
+ * Issue fsync recursively on the given directory and all its contents.
+ *
+ * This is a convenient wrapper on top of walkdir().
+ */
+void
+fsync_dir_recurse(const char *dir)
+{
+ /*
+ * If possible, hint to the kernel that we're soon going to fsync the data
+ * directory and its contents.
+ */
+#ifdef PG_FLUSH_DATA_WORKS
+ walkdir(dir, pre_sync_fname, false);
+#endif
+
+ walkdir(dir, fsync_fname, false);
+}
+
+/*
+ * walkdir: recursively walk a directory, applying the action to each
+ * regular file and directory (including the named directory itself).
+ *
+ * If process_symlinks is true, the action and recursion are also applied
+ * to regular files and directories that are pointed to by symlinks in the
+ * given directory; otherwise symlinks are ignored. Symlinks are always
+ * ignored in subdirectories, ie we intentionally don't pass down the
+ * process_symlinks flag to recursive calls.
+ *
+ * Errors are reported but not considered fatal.
+ *
+ * See also walkdir in fd.c, which is a backend version of this logic.
+ */
+static void
+walkdir(const char *path,
+ int (*action) (const char *fname, bool isdir),
+ bool process_symlinks)
+{
+ DIR *dir;
+ struct dirent *de;
+
+ dir = opendir(path);
+ if (dir == NULL)
+ {
+ pg_log_error("could not open directory \"%s\": %m", path);
+ return;
+ }
+
+ while (errno = 0, (de = readdir(dir)) != NULL)
+ {
+ char subpath[MAXPGPATH * 2];
+
+ if (strcmp(de->d_name, ".") == 0 ||
+ strcmp(de->d_name, "..") == 0)
+ continue;
+
+ snprintf(subpath, sizeof(subpath), "%s/%s", path, de->d_name);
+
+ switch (get_dirent_type(subpath, de, process_symlinks, PG_LOG_ERROR))
+ {
+ case PGFILETYPE_REG:
+ (*action) (subpath, false);
+ break;
+ case PGFILETYPE_DIR:
+ walkdir(subpath, action, false);
+ break;
+ default:
+
+ /*
+ * Errors are already reported directly by get_dirent_type(),
+ * and any remaining symlinks and unknown file types are
+ * ignored.
+ */
+ break;
+ }
+ }
+
+ if (errno)
+ pg_log_error("could not read directory \"%s\": %m", path);
+
+ (void) closedir(dir);
+
+ /*
+ * It's important to fsync the destination directory itself as individual
+ * file fsyncs don't guarantee that the directory entry for the file is
+ * synced. Recent versions of ext4 have made the window much wider but
+ * it's been an issue for ext3 and other filesystems in the past.
+ */
+ (*action) (path, true);
+}
+
+/*
+ * Hint to the OS that it should get ready to fsync() this file.
+ *
+ * Ignores errors trying to open unreadable files, and reports other errors
+ * non-fatally.
+ */
+#ifdef PG_FLUSH_DATA_WORKS
+
+static int
+pre_sync_fname(const char *fname, bool isdir)
+{
+ int fd;
+
+ fd = open(fname, O_RDONLY | PG_BINARY, 0);
+
+ if (fd < 0)
+ {
+ if (errno == EACCES || (isdir && errno == EISDIR))
+ return 0;
+ pg_log_error("could not open file \"%s\": %m", fname);
+ return -1;
+ }
+
+ /*
+ * We do what pg_flush_data() would do in the backend: prefer to use
+ * sync_file_range, but fall back to posix_fadvise. We ignore errors
+ * because this is only a hint.
+ */
+#if defined(HAVE_SYNC_FILE_RANGE)
+ (void) sync_file_range(fd, 0, 0, SYNC_FILE_RANGE_WRITE);
+#elif defined(USE_POSIX_FADVISE) && defined(POSIX_FADV_DONTNEED)
+ (void) posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED);
+#else
+#error PG_FLUSH_DATA_WORKS should not have been defined
+#endif
+
+ (void) close(fd);
+ return 0;
+}
+
+#endif /* PG_FLUSH_DATA_WORKS */
+
+/*
+ * fsync_fname -- Try to fsync a file or directory
+ *
+ * Ignores errors trying to open unreadable files, or trying to fsync
+ * directories on systems where that isn't allowed/required. All other errors
+ * are fatal.
+ */
+int
+fsync_fname(const char *fname, bool isdir)
+{
+ int fd;
+ int flags;
+ int returncode;
+
+ /*
+ * Some OSs require directories to be opened read-only whereas other
+ * systems don't allow us to fsync files opened read-only; so we need both
+ * cases here. Using O_RDWR will cause us to fail to fsync files that are
+ * not writable by our userid, but we assume that's OK.
+ */
+ flags = PG_BINARY;
+ if (!isdir)
+ flags |= O_RDWR;
+ else
+ flags |= O_RDONLY;
+
+ /*
+ * Open the file, silently ignoring errors about unreadable files (or
+ * unsupported operations, e.g. opening a directory under Windows), and
+ * logging others.
+ */
+ fd = open(fname, flags, 0);
+ if (fd < 0)
+ {
+ if (errno == EACCES || (isdir && errno == EISDIR))
+ return 0;
+ pg_log_error("could not open file \"%s\": %m", fname);
+ return -1;
+ }
+
+ returncode = fsync(fd);
+
+ /*
+ * Some OSes don't allow us to fsync directories at all, so we can ignore
+ * those errors. Anything else needs to be reported.
+ */
+ if (returncode != 0 && !(isdir && (errno == EBADF || errno == EINVAL)))
+ {
+ pg_log_error("could not fsync file \"%s\": %m", fname);
+ (void) close(fd);
+ exit(EXIT_FAILURE);
+ }
+
+ (void) close(fd);
+ return 0;
+}
+
+/*
+ * fsync_parent_path -- fsync the parent path of a file or directory
+ *
+ * This is aimed at making file operations persistent on disk in case of
+ * an OS crash or power failure.
+ */
+int
+fsync_parent_path(const char *fname)
+{
+ char parentpath[MAXPGPATH];
+
+ strlcpy(parentpath, fname, MAXPGPATH);
+ get_parent_directory(parentpath);
+
+ /*
+ * get_parent_directory() returns an empty string if the input argument is
+ * just a file name (see comments in path.c), so handle that as being the
+ * current directory.
+ */
+ if (strlen(parentpath) == 0)
+ strlcpy(parentpath, ".", MAXPGPATH);
+
+ if (fsync_fname(parentpath, true) != 0)
+ return -1;
+
+ return 0;
+}
+
+/*
+ * durable_rename -- rename(2) wrapper, issuing fsyncs required for durability
+ *
+ * Wrapper around rename, similar to the backend version.
+ */
+int
+durable_rename(const char *oldfile, const char *newfile)
+{
+ int fd;
+
+ /*
+ * First fsync the old and target path (if it exists), to ensure that they
+ * are properly persistent on disk. Syncing the target file is not
+ * strictly necessary, but it makes it easier to reason about crashes;
+ * because it's then guaranteed that either source or target file exists
+ * after a crash.
+ */
+ if (fsync_fname(oldfile, false) != 0)
+ return -1;
+
+ fd = open(newfile, PG_BINARY | O_RDWR, 0);
+ if (fd < 0)
+ {
+ if (errno != ENOENT)
+ {
+ pg_log_error("could not open file \"%s\": %m", newfile);
+ return -1;
+ }
+ }
+ else
+ {
+ if (fsync(fd) != 0)
+ {
+ pg_log_error("could not fsync file \"%s\": %m", newfile);
+ close(fd);
+ exit(EXIT_FAILURE);
+ }
+ close(fd);
+ }
+
+ /* Time to do the real deal... */
+ if (rename(oldfile, newfile) != 0)
+ {
+ pg_log_error("could not rename file \"%s\" to \"%s\": %m",
+ oldfile, newfile);
+ return -1;
+ }
+
+ /*
+ * To guarantee renaming the file is persistent, fsync the file with its
+ * new name, and its containing directory.
+ */
+ if (fsync_fname(newfile, false) != 0)
+ return -1;
+
+ if (fsync_parent_path(newfile) != 0)
+ return -1;
+
+ return 0;
+}
+
+#endif /* FRONTEND */
+
+/*
+ * Return the type of a directory entry.
+ *
+ * In frontend code, elevel should be a level from logging.h; in backend code
+ * it should be a level from elog.h.
+ */
+PGFileType
+get_dirent_type(const char *path,
+ const struct dirent *de,
+ bool look_through_symlinks,
+ int elevel)
+{
+ PGFileType result;
+
+ /*
+ * Some systems tell us the type directly in the dirent struct, but that's
+ * a BSD and Linux extension not required by POSIX. Even when the
+ * interface is present, sometimes the type is unknown, depending on the
+ * filesystem.
+ */
+#if defined(DT_REG) && defined(DT_DIR) && defined(DT_LNK)
+ if (de->d_type == DT_REG)
+ result = PGFILETYPE_REG;
+ else if (de->d_type == DT_DIR)
+ result = PGFILETYPE_DIR;
+ else if (de->d_type == DT_LNK && !look_through_symlinks)
+ result = PGFILETYPE_LNK;
+ else
+ result = PGFILETYPE_UNKNOWN;
+#else
+ result = PGFILETYPE_UNKNOWN;
+#endif
+
+ if (result == PGFILETYPE_UNKNOWN)
+ {
+ struct stat fst;
+ int sret;
+
+
+ if (look_through_symlinks)
+ sret = stat(path, &fst);
+ else
+ sret = lstat(path, &fst);
+
+ if (sret < 0)
+ {
+ result = PGFILETYPE_ERROR;
+#ifdef FRONTEND
+ pg_log_generic(elevel, PG_LOG_PRIMARY, "could not stat file \"%s\": %m", path);
+#else
+ ereport(elevel,
+ (errcode_for_file_access(),
+ errmsg("could not stat file \"%s\": %m", path)));
+#endif
+ }
+ else if (S_ISREG(fst.st_mode))
+ result = PGFILETYPE_REG;
+ else if (S_ISDIR(fst.st_mode))
+ result = PGFILETYPE_DIR;
+ else if (S_ISLNK(fst.st_mode))
+ result = PGFILETYPE_LNK;
+ }
+
+ return result;
+}
+
+/*
+ * pg_pwritev_with_retry
+ *
+ * Convenience wrapper for pg_pwritev() that retries on partial write. If an
+ * error is returned, it is unspecified how much has been written.
+ */
+ssize_t
+pg_pwritev_with_retry(int fd, const struct iovec *iov, int iovcnt, off_t offset)
+{
+ struct iovec iov_copy[PG_IOV_MAX];
+ ssize_t sum = 0;
+ ssize_t part;
+
+ /* We'd better have space to make a copy, in case we need to retry. */
+ if (iovcnt > PG_IOV_MAX)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ for (;;)
+ {
+ /* Write as much as we can. */
+ part = pg_pwritev(fd, iov, iovcnt, offset);
+ if (part < 0)
+ return -1;
+
+#ifdef SIMULATE_SHORT_WRITE
+ part = Min(part, 4096);
+#endif
+
+ /* Count our progress. */
+ sum += part;
+ offset += part;
+
+ /* Step over iovecs that are done. */
+ while (iovcnt > 0 && iov->iov_len <= part)
+ {
+ part -= iov->iov_len;
+ ++iov;
+ --iovcnt;
+ }
+
+ /* Are they all done? */
+ if (iovcnt == 0)
+ {
+ /* We don't expect the kernel to write more than requested. */
+ Assert(part == 0);
+ break;
+ }
+
+ /*
+ * Move whatever's left to the front of our mutable copy and adjust
+ * the leading iovec.
+ */
+ Assert(iovcnt > 0);
+ memmove(iov_copy, iov, sizeof(*iov) * iovcnt);
+ Assert(iov->iov_len > part);
+ iov_copy[0].iov_base = (char *) iov_copy[0].iov_base + part;
+ iov_copy[0].iov_len -= part;
+ iov = iov_copy;
+ }
+
+ return sum;
+}
+
+/*
+ * pg_pwrite_zeros
+ *
+ * Writes zeros to file worth "size" bytes at "offset" (from the start of the
+ * file), using vectored I/O.
+ *
+ * Returns the total amount of data written. On failure, a negative value
+ * is returned with errno set.
+ */
+ssize_t
+pg_pwrite_zeros(int fd, size_t size, off_t offset)
+{
+ static const PGIOAlignedBlock zbuffer = {{0}}; /* worth BLCKSZ */
+ void *zerobuf_addr = unconstify(PGIOAlignedBlock *, &zbuffer)->data;
+ struct iovec iov[PG_IOV_MAX];
+ size_t remaining_size = size;
+ ssize_t total_written = 0;
+
+ /* Loop, writing as many blocks as we can for each system call. */
+ while (remaining_size > 0)
+ {
+ int iovcnt = 0;
+ ssize_t written;
+
+ for (; iovcnt < PG_IOV_MAX && remaining_size > 0; iovcnt++)
+ {
+ size_t this_iov_size;
+
+ iov[iovcnt].iov_base = zerobuf_addr;
+
+ if (remaining_size < BLCKSZ)
+ this_iov_size = remaining_size;
+ else
+ this_iov_size = BLCKSZ;
+
+ iov[iovcnt].iov_len = this_iov_size;
+ remaining_size -= this_iov_size;
+ }
+
+ written = pg_pwritev_with_retry(fd, iov, iovcnt, offset);
+
+ if (written < 0)
+ return written;
+
+ offset += written;
+ total_written += written;
+ }
+
+ Assert(total_written == size);
+
+ return total_written;
+}
diff --git a/contrib/libs/libpq/src/common/hashfn.c b/contrib/libs/libpq/src/common/hashfn.c
new file mode 100644
index 0000000000..2490607eea
--- /dev/null
+++ b/contrib/libs/libpq/src/common/hashfn.c
@@ -0,0 +1,692 @@
+/*-------------------------------------------------------------------------
+ *
+ * hashfn.c
+ * Generic hashing functions, and hash functions for use in dynahash.c
+ * hashtables
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/common/hashfn.c
+ *
+ * NOTES
+ * It is expected that every bit of a hash function's 32-bit result is
+ * as random as every other; failure to ensure this is likely to lead
+ * to poor performance of hash tables. In most cases a hash
+ * function should use hash_bytes() or its variant hash_bytes_uint32(),
+ * or the wrappers hash_any() and hash_uint32 defined in hashfn.h.
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "common/hashfn.h"
+#include "port/pg_bitutils.h"
+
+
+/*
+ * This hash function was written by Bob Jenkins
+ * (bob_jenkins@burtleburtle.net), and superficially adapted
+ * for PostgreSQL by Neil Conway. For more information on this
+ * hash function, see http://burtleburtle.net/bob/hash/doobs.html,
+ * or Bob's article in Dr. Dobb's Journal, Sept. 1997.
+ *
+ * In the current code, we have adopted Bob's 2006 update of his hash
+ * function to fetch the data a word at a time when it is suitably aligned.
+ * This makes for a useful speedup, at the cost of having to maintain
+ * four code paths (aligned vs unaligned, and little-endian vs big-endian).
+ * It also uses two separate mixing functions mix() and final(), instead
+ * of a slower multi-purpose function.
+ */
+
+/* Get a bit mask of the bits set in non-uint32 aligned addresses */
+#define UINT32_ALIGN_MASK (sizeof(uint32) - 1)
+
+#define rot(x,k) pg_rotate_left32(x, k)
+
+/*----------
+ * mix -- mix 3 32-bit values reversibly.
+ *
+ * This is reversible, so any information in (a,b,c) before mix() is
+ * still in (a,b,c) after mix().
+ *
+ * If four pairs of (a,b,c) inputs are run through mix(), or through
+ * mix() in reverse, there are at least 32 bits of the output that
+ * are sometimes the same for one pair and different for another pair.
+ * This was tested for:
+ * * pairs that differed by one bit, by two bits, in any combination
+ * of top bits of (a,b,c), or in any combination of bottom bits of
+ * (a,b,c).
+ * * "differ" is defined as +, -, ^, or ~^. For + and -, I transformed
+ * the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
+ * is commonly produced by subtraction) look like a single 1-bit
+ * difference.
+ * * the base values were pseudorandom, all zero but one bit set, or
+ * all zero plus a counter that starts at zero.
+ *
+ * This does not achieve avalanche. There are input bits of (a,b,c)
+ * that fail to affect some output bits of (a,b,c), especially of a. The
+ * most thoroughly mixed value is c, but it doesn't really even achieve
+ * avalanche in c.
+ *
+ * This allows some parallelism. Read-after-writes are good at doubling
+ * the number of bits affected, so the goal of mixing pulls in the opposite
+ * direction from the goal of parallelism. I did what I could. Rotates
+ * seem to cost as much as shifts on every machine I could lay my hands on,
+ * and rotates are much kinder to the top and bottom bits, so I used rotates.
+ *----------
+ */
+#define mix(a,b,c) \
+{ \
+ a -= c; a ^= rot(c, 4); c += b; \
+ b -= a; b ^= rot(a, 6); a += c; \
+ c -= b; c ^= rot(b, 8); b += a; \
+ a -= c; a ^= rot(c,16); c += b; \
+ b -= a; b ^= rot(a,19); a += c; \
+ c -= b; c ^= rot(b, 4); b += a; \
+}
+
+/*----------
+ * final -- final mixing of 3 32-bit values (a,b,c) into c
+ *
+ * Pairs of (a,b,c) values differing in only a few bits will usually
+ * produce values of c that look totally different. This was tested for
+ * * pairs that differed by one bit, by two bits, in any combination
+ * of top bits of (a,b,c), or in any combination of bottom bits of
+ * (a,b,c).
+ * * "differ" is defined as +, -, ^, or ~^. For + and -, I transformed
+ * the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
+ * is commonly produced by subtraction) look like a single 1-bit
+ * difference.
+ * * the base values were pseudorandom, all zero but one bit set, or
+ * all zero plus a counter that starts at zero.
+ *
+ * The use of separate functions for mix() and final() allow for a
+ * substantial performance increase since final() does not need to
+ * do well in reverse, but is does need to affect all output bits.
+ * mix(), on the other hand, does not need to affect all output
+ * bits (affecting 32 bits is enough). The original hash function had
+ * a single mixing operation that had to satisfy both sets of requirements
+ * and was slower as a result.
+ *----------
+ */
+#define final(a,b,c) \
+{ \
+ c ^= b; c -= rot(b,14); \
+ a ^= c; a -= rot(c,11); \
+ b ^= a; b -= rot(a,25); \
+ c ^= b; c -= rot(b,16); \
+ a ^= c; a -= rot(c, 4); \
+ b ^= a; b -= rot(a,14); \
+ c ^= b; c -= rot(b,24); \
+}
+
+/*
+ * hash_bytes() -- hash a variable-length key into a 32-bit value
+ * k : the key (the unaligned variable-length array of bytes)
+ * len : the length of the key, counting by bytes
+ *
+ * Returns a uint32 value. Every bit of the key affects every bit of
+ * the return value. Every 1-bit and 2-bit delta achieves avalanche.
+ * About 6*len+35 instructions. The best hash table sizes are powers
+ * of 2. There is no need to do mod a prime (mod is sooo slow!).
+ * If you need less than 32 bits, use a bitmask.
+ *
+ * This procedure must never throw elog(ERROR); the ResourceOwner code
+ * relies on this not to fail.
+ *
+ * Note: we could easily change this function to return a 64-bit hash value
+ * by using the final values of both b and c. b is perhaps a little less
+ * well mixed than c, however.
+ */
+uint32
+hash_bytes(const unsigned char *k, int keylen)
+{
+ uint32 a,
+ b,
+ c,
+ len;
+
+ /* Set up the internal state */
+ len = keylen;
+ a = b = c = 0x9e3779b9 + len + 3923095;
+
+ /* If the source pointer is word-aligned, we use word-wide fetches */
+ if (((uintptr_t) k & UINT32_ALIGN_MASK) == 0)
+ {
+ /* Code path for aligned source data */
+ const uint32 *ka = (const uint32 *) k;
+
+ /* handle most of the key */
+ while (len >= 12)
+ {
+ a += ka[0];
+ b += ka[1];
+ c += ka[2];
+ mix(a, b, c);
+ ka += 3;
+ len -= 12;
+ }
+
+ /* handle the last 11 bytes */
+ k = (const unsigned char *) ka;
+#ifdef WORDS_BIGENDIAN
+ switch (len)
+ {
+ case 11:
+ c += ((uint32) k[10] << 8);
+ /* fall through */
+ case 10:
+ c += ((uint32) k[9] << 16);
+ /* fall through */
+ case 9:
+ c += ((uint32) k[8] << 24);
+ /* fall through */
+ case 8:
+ /* the lowest byte of c is reserved for the length */
+ b += ka[1];
+ a += ka[0];
+ break;
+ case 7:
+ b += ((uint32) k[6] << 8);
+ /* fall through */
+ case 6:
+ b += ((uint32) k[5] << 16);
+ /* fall through */
+ case 5:
+ b += ((uint32) k[4] << 24);
+ /* fall through */
+ case 4:
+ a += ka[0];
+ break;
+ case 3:
+ a += ((uint32) k[2] << 8);
+ /* fall through */
+ case 2:
+ a += ((uint32) k[1] << 16);
+ /* fall through */
+ case 1:
+ a += ((uint32) k[0] << 24);
+ /* case 0: nothing left to add */
+ }
+#else /* !WORDS_BIGENDIAN */
+ switch (len)
+ {
+ case 11:
+ c += ((uint32) k[10] << 24);
+ /* fall through */
+ case 10:
+ c += ((uint32) k[9] << 16);
+ /* fall through */
+ case 9:
+ c += ((uint32) k[8] << 8);
+ /* fall through */
+ case 8:
+ /* the lowest byte of c is reserved for the length */
+ b += ka[1];
+ a += ka[0];
+ break;
+ case 7:
+ b += ((uint32) k[6] << 16);
+ /* fall through */
+ case 6:
+ b += ((uint32) k[5] << 8);
+ /* fall through */
+ case 5:
+ b += k[4];
+ /* fall through */
+ case 4:
+ a += ka[0];
+ break;
+ case 3:
+ a += ((uint32) k[2] << 16);
+ /* fall through */
+ case 2:
+ a += ((uint32) k[1] << 8);
+ /* fall through */
+ case 1:
+ a += k[0];
+ /* case 0: nothing left to add */
+ }
+#endif /* WORDS_BIGENDIAN */
+ }
+ else
+ {
+ /* Code path for non-aligned source data */
+
+ /* handle most of the key */
+ while (len >= 12)
+ {
+#ifdef WORDS_BIGENDIAN
+ a += (k[3] + ((uint32) k[2] << 8) + ((uint32) k[1] << 16) + ((uint32) k[0] << 24));
+ b += (k[7] + ((uint32) k[6] << 8) + ((uint32) k[5] << 16) + ((uint32) k[4] << 24));
+ c += (k[11] + ((uint32) k[10] << 8) + ((uint32) k[9] << 16) + ((uint32) k[8] << 24));
+#else /* !WORDS_BIGENDIAN */
+ a += (k[0] + ((uint32) k[1] << 8) + ((uint32) k[2] << 16) + ((uint32) k[3] << 24));
+ b += (k[4] + ((uint32) k[5] << 8) + ((uint32) k[6] << 16) + ((uint32) k[7] << 24));
+ c += (k[8] + ((uint32) k[9] << 8) + ((uint32) k[10] << 16) + ((uint32) k[11] << 24));
+#endif /* WORDS_BIGENDIAN */
+ mix(a, b, c);
+ k += 12;
+ len -= 12;
+ }
+
+ /* handle the last 11 bytes */
+#ifdef WORDS_BIGENDIAN
+ switch (len)
+ {
+ case 11:
+ c += ((uint32) k[10] << 8);
+ /* fall through */
+ case 10:
+ c += ((uint32) k[9] << 16);
+ /* fall through */
+ case 9:
+ c += ((uint32) k[8] << 24);
+ /* fall through */
+ case 8:
+ /* the lowest byte of c is reserved for the length */
+ b += k[7];
+ /* fall through */
+ case 7:
+ b += ((uint32) k[6] << 8);
+ /* fall through */
+ case 6:
+ b += ((uint32) k[5] << 16);
+ /* fall through */
+ case 5:
+ b += ((uint32) k[4] << 24);
+ /* fall through */
+ case 4:
+ a += k[3];
+ /* fall through */
+ case 3:
+ a += ((uint32) k[2] << 8);
+ /* fall through */
+ case 2:
+ a += ((uint32) k[1] << 16);
+ /* fall through */
+ case 1:
+ a += ((uint32) k[0] << 24);
+ /* case 0: nothing left to add */
+ }
+#else /* !WORDS_BIGENDIAN */
+ switch (len)
+ {
+ case 11:
+ c += ((uint32) k[10] << 24);
+ /* fall through */
+ case 10:
+ c += ((uint32) k[9] << 16);
+ /* fall through */
+ case 9:
+ c += ((uint32) k[8] << 8);
+ /* fall through */
+ case 8:
+ /* the lowest byte of c is reserved for the length */
+ b += ((uint32) k[7] << 24);
+ /* fall through */
+ case 7:
+ b += ((uint32) k[6] << 16);
+ /* fall through */
+ case 6:
+ b += ((uint32) k[5] << 8);
+ /* fall through */
+ case 5:
+ b += k[4];
+ /* fall through */
+ case 4:
+ a += ((uint32) k[3] << 24);
+ /* fall through */
+ case 3:
+ a += ((uint32) k[2] << 16);
+ /* fall through */
+ case 2:
+ a += ((uint32) k[1] << 8);
+ /* fall through */
+ case 1:
+ a += k[0];
+ /* case 0: nothing left to add */
+ }
+#endif /* WORDS_BIGENDIAN */
+ }
+
+ final(a, b, c);
+
+ /* report the result */
+ return c;
+}
+
+/*
+ * hash_bytes_extended() -- hash into a 64-bit value, using an optional seed
+ * k : the key (the unaligned variable-length array of bytes)
+ * len : the length of the key, counting by bytes
+ * seed : a 64-bit seed (0 means no seed)
+ *
+ * Returns a uint64 value. Otherwise similar to hash_bytes.
+ */
+uint64
+hash_bytes_extended(const unsigned char *k, int keylen, uint64 seed)
+{
+ uint32 a,
+ b,
+ c,
+ len;
+
+ /* Set up the internal state */
+ len = keylen;
+ a = b = c = 0x9e3779b9 + len + 3923095;
+
+ /* If the seed is non-zero, use it to perturb the internal state. */
+ if (seed != 0)
+ {
+ /*
+ * In essence, the seed is treated as part of the data being hashed,
+ * but for simplicity, we pretend that it's padded with four bytes of
+ * zeroes so that the seed constitutes a 12-byte chunk.
+ */
+ a += (uint32) (seed >> 32);
+ b += (uint32) seed;
+ mix(a, b, c);
+ }
+
+ /* If the source pointer is word-aligned, we use word-wide fetches */
+ if (((uintptr_t) k & UINT32_ALIGN_MASK) == 0)
+ {
+ /* Code path for aligned source data */
+ const uint32 *ka = (const uint32 *) k;
+
+ /* handle most of the key */
+ while (len >= 12)
+ {
+ a += ka[0];
+ b += ka[1];
+ c += ka[2];
+ mix(a, b, c);
+ ka += 3;
+ len -= 12;
+ }
+
+ /* handle the last 11 bytes */
+ k = (const unsigned char *) ka;
+#ifdef WORDS_BIGENDIAN
+ switch (len)
+ {
+ case 11:
+ c += ((uint32) k[10] << 8);
+ /* fall through */
+ case 10:
+ c += ((uint32) k[9] << 16);
+ /* fall through */
+ case 9:
+ c += ((uint32) k[8] << 24);
+ /* fall through */
+ case 8:
+ /* the lowest byte of c is reserved for the length */
+ b += ka[1];
+ a += ka[0];
+ break;
+ case 7:
+ b += ((uint32) k[6] << 8);
+ /* fall through */
+ case 6:
+ b += ((uint32) k[5] << 16);
+ /* fall through */
+ case 5:
+ b += ((uint32) k[4] << 24);
+ /* fall through */
+ case 4:
+ a += ka[0];
+ break;
+ case 3:
+ a += ((uint32) k[2] << 8);
+ /* fall through */
+ case 2:
+ a += ((uint32) k[1] << 16);
+ /* fall through */
+ case 1:
+ a += ((uint32) k[0] << 24);
+ /* case 0: nothing left to add */
+ }
+#else /* !WORDS_BIGENDIAN */
+ switch (len)
+ {
+ case 11:
+ c += ((uint32) k[10] << 24);
+ /* fall through */
+ case 10:
+ c += ((uint32) k[9] << 16);
+ /* fall through */
+ case 9:
+ c += ((uint32) k[8] << 8);
+ /* fall through */
+ case 8:
+ /* the lowest byte of c is reserved for the length */
+ b += ka[1];
+ a += ka[0];
+ break;
+ case 7:
+ b += ((uint32) k[6] << 16);
+ /* fall through */
+ case 6:
+ b += ((uint32) k[5] << 8);
+ /* fall through */
+ case 5:
+ b += k[4];
+ /* fall through */
+ case 4:
+ a += ka[0];
+ break;
+ case 3:
+ a += ((uint32) k[2] << 16);
+ /* fall through */
+ case 2:
+ a += ((uint32) k[1] << 8);
+ /* fall through */
+ case 1:
+ a += k[0];
+ /* case 0: nothing left to add */
+ }
+#endif /* WORDS_BIGENDIAN */
+ }
+ else
+ {
+ /* Code path for non-aligned source data */
+
+ /* handle most of the key */
+ while (len >= 12)
+ {
+#ifdef WORDS_BIGENDIAN
+ a += (k[3] + ((uint32) k[2] << 8) + ((uint32) k[1] << 16) + ((uint32) k[0] << 24));
+ b += (k[7] + ((uint32) k[6] << 8) + ((uint32) k[5] << 16) + ((uint32) k[4] << 24));
+ c += (k[11] + ((uint32) k[10] << 8) + ((uint32) k[9] << 16) + ((uint32) k[8] << 24));
+#else /* !WORDS_BIGENDIAN */
+ a += (k[0] + ((uint32) k[1] << 8) + ((uint32) k[2] << 16) + ((uint32) k[3] << 24));
+ b += (k[4] + ((uint32) k[5] << 8) + ((uint32) k[6] << 16) + ((uint32) k[7] << 24));
+ c += (k[8] + ((uint32) k[9] << 8) + ((uint32) k[10] << 16) + ((uint32) k[11] << 24));
+#endif /* WORDS_BIGENDIAN */
+ mix(a, b, c);
+ k += 12;
+ len -= 12;
+ }
+
+ /* handle the last 11 bytes */
+#ifdef WORDS_BIGENDIAN
+ switch (len)
+ {
+ case 11:
+ c += ((uint32) k[10] << 8);
+ /* fall through */
+ case 10:
+ c += ((uint32) k[9] << 16);
+ /* fall through */
+ case 9:
+ c += ((uint32) k[8] << 24);
+ /* fall through */
+ case 8:
+ /* the lowest byte of c is reserved for the length */
+ b += k[7];
+ /* fall through */
+ case 7:
+ b += ((uint32) k[6] << 8);
+ /* fall through */
+ case 6:
+ b += ((uint32) k[5] << 16);
+ /* fall through */
+ case 5:
+ b += ((uint32) k[4] << 24);
+ /* fall through */
+ case 4:
+ a += k[3];
+ /* fall through */
+ case 3:
+ a += ((uint32) k[2] << 8);
+ /* fall through */
+ case 2:
+ a += ((uint32) k[1] << 16);
+ /* fall through */
+ case 1:
+ a += ((uint32) k[0] << 24);
+ /* case 0: nothing left to add */
+ }
+#else /* !WORDS_BIGENDIAN */
+ switch (len)
+ {
+ case 11:
+ c += ((uint32) k[10] << 24);
+ /* fall through */
+ case 10:
+ c += ((uint32) k[9] << 16);
+ /* fall through */
+ case 9:
+ c += ((uint32) k[8] << 8);
+ /* fall through */
+ case 8:
+ /* the lowest byte of c is reserved for the length */
+ b += ((uint32) k[7] << 24);
+ /* fall through */
+ case 7:
+ b += ((uint32) k[6] << 16);
+ /* fall through */
+ case 6:
+ b += ((uint32) k[5] << 8);
+ /* fall through */
+ case 5:
+ b += k[4];
+ /* fall through */
+ case 4:
+ a += ((uint32) k[3] << 24);
+ /* fall through */
+ case 3:
+ a += ((uint32) k[2] << 16);
+ /* fall through */
+ case 2:
+ a += ((uint32) k[1] << 8);
+ /* fall through */
+ case 1:
+ a += k[0];
+ /* case 0: nothing left to add */
+ }
+#endif /* WORDS_BIGENDIAN */
+ }
+
+ final(a, b, c);
+
+ /* report the result */
+ return ((uint64) b << 32) | c;
+}
+
+/*
+ * hash_bytes_uint32() -- hash a 32-bit value to a 32-bit value
+ *
+ * This has the same result as
+ * hash_bytes(&k, sizeof(uint32))
+ * but is faster and doesn't force the caller to store k into memory.
+ */
+uint32
+hash_bytes_uint32(uint32 k)
+{
+ uint32 a,
+ b,
+ c;
+
+ a = b = c = 0x9e3779b9 + (uint32) sizeof(uint32) + 3923095;
+ a += k;
+
+ final(a, b, c);
+
+ /* report the result */
+ return c;
+}
+
+/*
+ * hash_bytes_uint32_extended() -- hash 32-bit value to 64-bit value, with seed
+ *
+ * Like hash_bytes_uint32, this is a convenience function.
+ */
+uint64
+hash_bytes_uint32_extended(uint32 k, uint64 seed)
+{
+ uint32 a,
+ b,
+ c;
+
+ a = b = c = 0x9e3779b9 + (uint32) sizeof(uint32) + 3923095;
+
+ if (seed != 0)
+ {
+ a += (uint32) (seed >> 32);
+ b += (uint32) seed;
+ mix(a, b, c);
+ }
+
+ a += k;
+
+ final(a, b, c);
+
+ /* report the result */
+ return ((uint64) b << 32) | c;
+}
+
+/*
+ * string_hash: hash function for keys that are NUL-terminated strings.
+ *
+ * NOTE: this is the default hash function if none is specified.
+ */
+uint32
+string_hash(const void *key, Size keysize)
+{
+ /*
+ * If the string exceeds keysize-1 bytes, we want to hash only that many,
+ * because when it is copied into the hash table it will be truncated at
+ * that length.
+ */
+ Size s_len = strlen((const char *) key);
+
+ s_len = Min(s_len, keysize - 1);
+ return hash_bytes((const unsigned char *) key, (int) s_len);
+}
+
+/*
+ * tag_hash: hash function for fixed-size tag values
+ */
+uint32
+tag_hash(const void *key, Size keysize)
+{
+ return hash_bytes((const unsigned char *) key, (int) keysize);
+}
+
+/*
+ * uint32_hash: hash function for keys that are uint32 or int32
+ *
+ * (tag_hash works for this case too, but is slower)
+ */
+uint32
+uint32_hash(const void *key, Size keysize)
+{
+ Assert(keysize == sizeof(uint32));
+ return hash_bytes_uint32(*((const uint32 *) key));
+}
diff --git a/contrib/libs/libpq/src/common/hmac_openssl.c b/contrib/libs/libpq/src/common/hmac_openssl.c
new file mode 100644
index 0000000000..9aadbb886c
--- /dev/null
+++ b/contrib/libs/libpq/src/common/hmac_openssl.c
@@ -0,0 +1,348 @@
+/*-------------------------------------------------------------------------
+ *
+ * hmac_openssl.c
+ * Implementation of HMAC with OpenSSL.
+ *
+ * This should only be used if code is compiled with OpenSSL support.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/common/hmac_openssl.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+
+#include <openssl/err.h>
+#include <openssl/hmac.h>
+
+#include "common/hmac.h"
+#include "common/md5.h"
+#include "common/sha1.h"
+#include "common/sha2.h"
+#ifndef FRONTEND
+#error #include "utils/memutils.h"
+#error #include "utils/resowner.h"
+#error #include "utils/resowner_private.h"
+#endif
+
+/*
+ * In backend, use an allocation in TopMemoryContext to count for resowner
+ * cleanup handling if necessary. For versions of OpenSSL where HMAC_CTX is
+ * known, just use palloc(). In frontend, use malloc to be able to return
+ * a failure status back to the caller.
+ */
+#ifndef FRONTEND
+#ifdef HAVE_HMAC_CTX_NEW
+#define ALLOC(size) MemoryContextAlloc(TopMemoryContext, size)
+#else
+#define ALLOC(size) palloc(size)
+#endif
+#define FREE(ptr) pfree(ptr)
+#else /* FRONTEND */
+#define ALLOC(size) malloc(size)
+#define FREE(ptr) free(ptr)
+#endif /* FRONTEND */
+
+/* Set of error states */
+typedef enum pg_hmac_errno
+{
+ PG_HMAC_ERROR_NONE = 0,
+ PG_HMAC_ERROR_DEST_LEN,
+ PG_HMAC_ERROR_OPENSSL
+} pg_hmac_errno;
+
+/* Internal pg_hmac_ctx structure */
+struct pg_hmac_ctx
+{
+ HMAC_CTX *hmacctx;
+ pg_cryptohash_type type;
+ pg_hmac_errno error;
+ const char *errreason;
+
+#ifndef FRONTEND
+ ResourceOwner resowner;
+#endif
+};
+
+static const char *
+SSLerrmessage(unsigned long ecode)
+{
+ if (ecode == 0)
+ return NULL;
+
+ /*
+ * This may return NULL, but we would fall back to a default error path if
+ * that were the case.
+ */
+ return ERR_reason_error_string(ecode);
+}
+
+/*
+ * pg_hmac_create
+ *
+ * Allocate a hash context. Returns NULL on failure for an OOM. The
+ * backend issues an error, without returning.
+ */
+pg_hmac_ctx *
+pg_hmac_create(pg_cryptohash_type type)
+{
+ pg_hmac_ctx *ctx;
+
+ ctx = ALLOC(sizeof(pg_hmac_ctx));
+ if (ctx == NULL)
+ return NULL;
+ memset(ctx, 0, sizeof(pg_hmac_ctx));
+
+ ctx->type = type;
+ ctx->error = PG_HMAC_ERROR_NONE;
+ ctx->errreason = NULL;
+
+
+ /*
+ * Initialization takes care of assigning the correct type for OpenSSL.
+ * Also ensure that there aren't any unconsumed errors in the queue from
+ * previous runs.
+ */
+ ERR_clear_error();
+#ifdef HAVE_HMAC_CTX_NEW
+#ifndef FRONTEND
+ ResourceOwnerEnlargeHMAC(CurrentResourceOwner);
+#endif
+ ctx->hmacctx = HMAC_CTX_new();
+#else
+ ctx->hmacctx = ALLOC(sizeof(HMAC_CTX));
+#endif
+
+ if (ctx->hmacctx == NULL)
+ {
+ explicit_bzero(ctx, sizeof(pg_hmac_ctx));
+ FREE(ctx);
+#ifndef FRONTEND
+ ereport(ERROR,
+ (errcode(ERRCODE_OUT_OF_MEMORY),
+ errmsg("out of memory")));
+#endif
+ return NULL;
+ }
+
+#ifdef HAVE_HMAC_CTX_NEW
+#ifndef FRONTEND
+ ctx->resowner = CurrentResourceOwner;
+ ResourceOwnerRememberHMAC(CurrentResourceOwner, PointerGetDatum(ctx));
+#endif
+#else
+ memset(ctx->hmacctx, 0, sizeof(HMAC_CTX));
+#endif /* HAVE_HMAC_CTX_NEW */
+
+ return ctx;
+}
+
+/*
+ * pg_hmac_init
+ *
+ * Initialize a HMAC context. Returns 0 on success, -1 on failure.
+ */
+int
+pg_hmac_init(pg_hmac_ctx *ctx, const uint8 *key, size_t len)
+{
+ int status = 0;
+
+ if (ctx == NULL)
+ return -1;
+
+ switch (ctx->type)
+ {
+ case PG_MD5:
+ status = HMAC_Init_ex(ctx->hmacctx, key, len, EVP_md5(), NULL);
+ break;
+ case PG_SHA1:
+ status = HMAC_Init_ex(ctx->hmacctx, key, len, EVP_sha1(), NULL);
+ break;
+ case PG_SHA224:
+ status = HMAC_Init_ex(ctx->hmacctx, key, len, EVP_sha224(), NULL);
+ break;
+ case PG_SHA256:
+ status = HMAC_Init_ex(ctx->hmacctx, key, len, EVP_sha256(), NULL);
+ break;
+ case PG_SHA384:
+ status = HMAC_Init_ex(ctx->hmacctx, key, len, EVP_sha384(), NULL);
+ break;
+ case PG_SHA512:
+ status = HMAC_Init_ex(ctx->hmacctx, key, len, EVP_sha512(), NULL);
+ break;
+ }
+
+ /* OpenSSL internals return 1 on success, 0 on failure */
+ if (status <= 0)
+ {
+ ctx->errreason = SSLerrmessage(ERR_get_error());
+ ctx->error = PG_HMAC_ERROR_OPENSSL;
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * pg_hmac_update
+ *
+ * Update a HMAC context. Returns 0 on success, -1 on failure.
+ */
+int
+pg_hmac_update(pg_hmac_ctx *ctx, const uint8 *data, size_t len)
+{
+ int status = 0;
+
+ if (ctx == NULL)
+ return -1;
+
+ status = HMAC_Update(ctx->hmacctx, data, len);
+
+ /* OpenSSL internals return 1 on success, 0 on failure */
+ if (status <= 0)
+ {
+ ctx->errreason = SSLerrmessage(ERR_get_error());
+ ctx->error = PG_HMAC_ERROR_OPENSSL;
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * pg_hmac_final
+ *
+ * Finalize a HMAC context. Returns 0 on success, -1 on failure.
+ */
+int
+pg_hmac_final(pg_hmac_ctx *ctx, uint8 *dest, size_t len)
+{
+ int status = 0;
+ uint32 outlen;
+
+ if (ctx == NULL)
+ return -1;
+
+ switch (ctx->type)
+ {
+ case PG_MD5:
+ if (len < MD5_DIGEST_LENGTH)
+ {
+ ctx->error = PG_HMAC_ERROR_DEST_LEN;
+ return -1;
+ }
+ break;
+ case PG_SHA1:
+ if (len < SHA1_DIGEST_LENGTH)
+ {
+ ctx->error = PG_HMAC_ERROR_DEST_LEN;
+ return -1;
+ }
+ break;
+ case PG_SHA224:
+ if (len < PG_SHA224_DIGEST_LENGTH)
+ {
+ ctx->error = PG_HMAC_ERROR_DEST_LEN;
+ return -1;
+ }
+ break;
+ case PG_SHA256:
+ if (len < PG_SHA256_DIGEST_LENGTH)
+ {
+ ctx->error = PG_HMAC_ERROR_DEST_LEN;
+ return -1;
+ }
+ break;
+ case PG_SHA384:
+ if (len < PG_SHA384_DIGEST_LENGTH)
+ {
+ ctx->error = PG_HMAC_ERROR_DEST_LEN;
+ return -1;
+ }
+ break;
+ case PG_SHA512:
+ if (len < PG_SHA512_DIGEST_LENGTH)
+ {
+ ctx->error = PG_HMAC_ERROR_DEST_LEN;
+ return -1;
+ }
+ break;
+ }
+
+ status = HMAC_Final(ctx->hmacctx, dest, &outlen);
+
+ /* OpenSSL internals return 1 on success, 0 on failure */
+ if (status <= 0)
+ {
+ ctx->errreason = SSLerrmessage(ERR_get_error());
+ ctx->error = PG_HMAC_ERROR_OPENSSL;
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * pg_hmac_free
+ *
+ * Free a HMAC context.
+ */
+void
+pg_hmac_free(pg_hmac_ctx *ctx)
+{
+ if (ctx == NULL)
+ return;
+
+#ifdef HAVE_HMAC_CTX_FREE
+ HMAC_CTX_free(ctx->hmacctx);
+#ifndef FRONTEND
+ ResourceOwnerForgetHMAC(ctx->resowner, PointerGetDatum(ctx));
+#endif
+#else
+ explicit_bzero(ctx->hmacctx, sizeof(HMAC_CTX));
+ FREE(ctx->hmacctx);
+#endif
+
+ explicit_bzero(ctx, sizeof(pg_hmac_ctx));
+ FREE(ctx);
+}
+
+/*
+ * pg_hmac_error
+ *
+ * Returns a static string providing details about an error that happened
+ * during a HMAC computation.
+ */
+const char *
+pg_hmac_error(pg_hmac_ctx *ctx)
+{
+ if (ctx == NULL)
+ return _("out of memory");
+
+ /*
+ * If a reason is provided, rely on it, else fallback to any error code
+ * set.
+ */
+ if (ctx->errreason)
+ return ctx->errreason;
+
+ switch (ctx->error)
+ {
+ case PG_HMAC_ERROR_NONE:
+ return _("success");
+ case PG_HMAC_ERROR_DEST_LEN:
+ return _("destination buffer too small");
+ case PG_HMAC_ERROR_OPENSSL:
+ return _("OpenSSL failure");
+ }
+
+ Assert(false); /* cannot be reached */
+ return _("success");
+}
diff --git a/contrib/libs/libpq/src/common/ip.c b/contrib/libs/libpq/src/common/ip.c
new file mode 100644
index 0000000000..9baad3a337
--- /dev/null
+++ b/contrib/libs/libpq/src/common/ip.c
@@ -0,0 +1,262 @@
+/*-------------------------------------------------------------------------
+ *
+ * ip.c
+ * IPv6-aware network access.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/common/ip.c
+ *
+ * This file and the IPV6 implementation were initially provided by
+ * Nigel Kukard <nkukard@lbsd.net>, Linux Based Systems Design
+ * http://www.lbsd.net.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <sys/file.h>
+
+#include "common/ip.h"
+
+
+
+static int getaddrinfo_unix(const char *path,
+ const struct addrinfo *hintsp,
+ struct addrinfo **result);
+
+static int getnameinfo_unix(const struct sockaddr_un *sa, int salen,
+ char *node, int nodelen,
+ char *service, int servicelen,
+ int flags);
+
+
+/*
+ * pg_getaddrinfo_all - get address info for Unix, IPv4 and IPv6 sockets
+ */
+int
+pg_getaddrinfo_all(const char *hostname, const char *servname,
+ const struct addrinfo *hintp, struct addrinfo **result)
+{
+ int rc;
+
+ /* not all versions of getaddrinfo() zero *result on failure */
+ *result = NULL;
+
+ if (hintp->ai_family == AF_UNIX)
+ return getaddrinfo_unix(servname, hintp, result);
+
+ /* NULL has special meaning to getaddrinfo(). */
+ rc = getaddrinfo((!hostname || hostname[0] == '\0') ? NULL : hostname,
+ servname, hintp, result);
+
+ return rc;
+}
+
+
+/*
+ * pg_freeaddrinfo_all - free addrinfo structures for IPv4, IPv6, or Unix
+ *
+ * Note: the ai_family field of the original hint structure must be passed
+ * so that we can tell whether the addrinfo struct was built by the system's
+ * getaddrinfo() routine or our own getaddrinfo_unix() routine. Some versions
+ * of getaddrinfo() might be willing to return AF_UNIX addresses, so it's
+ * not safe to look at ai_family in the addrinfo itself.
+ */
+void
+pg_freeaddrinfo_all(int hint_ai_family, struct addrinfo *ai)
+{
+ if (hint_ai_family == AF_UNIX)
+ {
+ /* struct was built by getaddrinfo_unix (see pg_getaddrinfo_all) */
+ while (ai != NULL)
+ {
+ struct addrinfo *p = ai;
+
+ ai = ai->ai_next;
+ free(p->ai_addr);
+ free(p);
+ }
+ }
+ else
+ {
+ /* struct was built by getaddrinfo() */
+ if (ai != NULL)
+ freeaddrinfo(ai);
+ }
+}
+
+
+/*
+ * pg_getnameinfo_all - get name info for Unix, IPv4 and IPv6 sockets
+ *
+ * The API of this routine differs from the standard getnameinfo() definition
+ * in two ways: first, the addr parameter is declared as sockaddr_storage
+ * rather than struct sockaddr, and second, the node and service fields are
+ * guaranteed to be filled with something even on failure return.
+ */
+int
+pg_getnameinfo_all(const struct sockaddr_storage *addr, int salen,
+ char *node, int nodelen,
+ char *service, int servicelen,
+ int flags)
+{
+ int rc;
+
+ if (addr && addr->ss_family == AF_UNIX)
+ rc = getnameinfo_unix((const struct sockaddr_un *) addr, salen,
+ node, nodelen,
+ service, servicelen,
+ flags);
+ else
+ rc = getnameinfo((const struct sockaddr *) addr, salen,
+ node, nodelen,
+ service, servicelen,
+ flags);
+
+ if (rc != 0)
+ {
+ if (node)
+ strlcpy(node, "???", nodelen);
+ if (service)
+ strlcpy(service, "???", servicelen);
+ }
+
+ return rc;
+}
+
+
+/* -------
+ * getaddrinfo_unix - get unix socket info using IPv6-compatible API
+ *
+ * Bugs: only one addrinfo is set even though hintsp is NULL or
+ * ai_socktype is 0
+ * AI_CANONNAME is not supported.
+ * -------
+ */
+static int
+getaddrinfo_unix(const char *path, const struct addrinfo *hintsp,
+ struct addrinfo **result)
+{
+ struct addrinfo hints = {0};
+ struct addrinfo *aip;
+ struct sockaddr_un *unp;
+
+ *result = NULL;
+
+ if (strlen(path) >= sizeof(unp->sun_path))
+ return EAI_FAIL;
+
+ if (hintsp == NULL)
+ {
+ hints.ai_family = AF_UNIX;
+ hints.ai_socktype = SOCK_STREAM;
+ }
+ else
+ memcpy(&hints, hintsp, sizeof(hints));
+
+ if (hints.ai_socktype == 0)
+ hints.ai_socktype = SOCK_STREAM;
+
+ if (hints.ai_family != AF_UNIX)
+ {
+ /* shouldn't have been called */
+ return EAI_FAIL;
+ }
+
+ aip = calloc(1, sizeof(struct addrinfo));
+ if (aip == NULL)
+ return EAI_MEMORY;
+
+ unp = calloc(1, sizeof(struct sockaddr_un));
+ if (unp == NULL)
+ {
+ free(aip);
+ return EAI_MEMORY;
+ }
+
+ aip->ai_family = AF_UNIX;
+ aip->ai_socktype = hints.ai_socktype;
+ aip->ai_protocol = hints.ai_protocol;
+ aip->ai_next = NULL;
+ aip->ai_canonname = NULL;
+ *result = aip;
+
+ unp->sun_family = AF_UNIX;
+ aip->ai_addr = (struct sockaddr *) unp;
+ aip->ai_addrlen = sizeof(struct sockaddr_un);
+
+ strcpy(unp->sun_path, path);
+
+ /*
+ * If the supplied path starts with @, replace that with a zero byte for
+ * the internal representation. In that mode, the entire sun_path is the
+ * address, including trailing zero bytes. But we set the address length
+ * to only include the length of the original string. That way the
+ * trailing zero bytes won't show up in any network or socket lists of the
+ * operating system. This is just a convention, also followed by other
+ * packages.
+ */
+ if (path[0] == '@')
+ {
+ unp->sun_path[0] = '\0';
+ aip->ai_addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(path);
+ }
+
+ return 0;
+}
+
+/*
+ * Convert an address to a hostname.
+ */
+static int
+getnameinfo_unix(const struct sockaddr_un *sa, int salen,
+ char *node, int nodelen,
+ char *service, int servicelen,
+ int flags)
+{
+ int ret;
+
+ /* Invalid arguments. */
+ if (sa == NULL || sa->sun_family != AF_UNIX ||
+ (node == NULL && service == NULL))
+ return EAI_FAIL;
+
+ if (node)
+ {
+ ret = snprintf(node, nodelen, "%s", "[local]");
+ if (ret < 0 || ret >= nodelen)
+ return EAI_MEMORY;
+ }
+
+ if (service)
+ {
+ /*
+ * Check whether it looks like an abstract socket, but it could also
+ * just be an empty string.
+ */
+ if (sa->sun_path[0] == '\0' && sa->sun_path[1] != '\0')
+ ret = snprintf(service, servicelen, "@%s", sa->sun_path + 1);
+ else
+ ret = snprintf(service, servicelen, "%s", sa->sun_path);
+ if (ret < 0 || ret >= servicelen)
+ return EAI_MEMORY;
+ }
+
+ return 0;
+}
diff --git a/contrib/libs/libpq/src/common/jsonapi.c b/contrib/libs/libpq/src/common/jsonapi.c
new file mode 100644
index 0000000000..bb8178e91d
--- /dev/null
+++ b/contrib/libs/libpq/src/common/jsonapi.c
@@ -0,0 +1,1206 @@
+/*-------------------------------------------------------------------------
+ *
+ * jsonapi.c
+ * JSON parser and lexer interfaces
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/common/jsonapi.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#include "common/jsonapi.h"
+#include "mb/pg_wchar.h"
+#include "port/pg_lfind.h"
+
+#ifndef FRONTEND
+#error #include "miscadmin.h"
+#endif
+
+/*
+ * The context of the parser is maintained by the recursive descent
+ * mechanism, but is passed explicitly to the error reporting routine
+ * for better diagnostics.
+ */
+typedef enum /* contexts of JSON parser */
+{
+ JSON_PARSE_VALUE, /* expecting a value */
+ JSON_PARSE_STRING, /* expecting a string (for a field name) */
+ JSON_PARSE_ARRAY_START, /* saw '[', expecting value or ']' */
+ JSON_PARSE_ARRAY_NEXT, /* saw array element, expecting ',' or ']' */
+ JSON_PARSE_OBJECT_START, /* saw '{', expecting label or '}' */
+ JSON_PARSE_OBJECT_LABEL, /* saw object label, expecting ':' */
+ JSON_PARSE_OBJECT_NEXT, /* saw object value, expecting ',' or '}' */
+ JSON_PARSE_OBJECT_COMMA, /* saw object ',', expecting next label */
+ JSON_PARSE_END /* saw the end of a document, expect nothing */
+} JsonParseContext;
+
+static inline JsonParseErrorType json_lex_string(JsonLexContext *lex);
+static inline JsonParseErrorType json_lex_number(JsonLexContext *lex, char *s,
+ bool *num_err, int *total_len);
+static inline JsonParseErrorType parse_scalar(JsonLexContext *lex, JsonSemAction *sem);
+static JsonParseErrorType parse_object_field(JsonLexContext *lex, JsonSemAction *sem);
+static JsonParseErrorType parse_object(JsonLexContext *lex, JsonSemAction *sem);
+static JsonParseErrorType parse_array_element(JsonLexContext *lex, JsonSemAction *sem);
+static JsonParseErrorType parse_array(JsonLexContext *lex, JsonSemAction *sem);
+static JsonParseErrorType report_parse_error(JsonParseContext ctx, JsonLexContext *lex);
+
+/* the null action object used for pure validation */
+JsonSemAction nullSemAction =
+{
+ NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL
+};
+
+/* Recursive Descent parser support routines */
+
+/*
+ * lex_peek
+ *
+ * what is the current look_ahead token?
+*/
+static inline JsonTokenType
+lex_peek(JsonLexContext *lex)
+{
+ return lex->token_type;
+}
+
+/*
+ * lex_expect
+ *
+ * move the lexer to the next token if the current look_ahead token matches
+ * the parameter token. Otherwise, report an error.
+ */
+static inline JsonParseErrorType
+lex_expect(JsonParseContext ctx, JsonLexContext *lex, JsonTokenType token)
+{
+ if (lex_peek(lex) == token)
+ return json_lex(lex);
+ else
+ return report_parse_error(ctx, lex);
+}
+
+/* chars to consider as part of an alphanumeric token */
+#define JSON_ALPHANUMERIC_CHAR(c) \
+ (((c) >= 'a' && (c) <= 'z') || \
+ ((c) >= 'A' && (c) <= 'Z') || \
+ ((c) >= '0' && (c) <= '9') || \
+ (c) == '_' || \
+ IS_HIGHBIT_SET(c))
+
+/*
+ * Utility function to check if a string is a valid JSON number.
+ *
+ * str is of length len, and need not be null-terminated.
+ */
+bool
+IsValidJsonNumber(const char *str, int len)
+{
+ bool numeric_error;
+ int total_len;
+ JsonLexContext dummy_lex;
+
+ if (len <= 0)
+ return false;
+
+ /*
+ * json_lex_number expects a leading '-' to have been eaten already.
+ *
+ * having to cast away the constness of str is ugly, but there's not much
+ * easy alternative.
+ */
+ if (*str == '-')
+ {
+ dummy_lex.input = unconstify(char *, str) + 1;
+ dummy_lex.input_length = len - 1;
+ }
+ else
+ {
+ dummy_lex.input = unconstify(char *, str);
+ dummy_lex.input_length = len;
+ }
+
+ json_lex_number(&dummy_lex, dummy_lex.input, &numeric_error, &total_len);
+
+ return (!numeric_error) && (total_len == dummy_lex.input_length);
+}
+
+/*
+ * makeJsonLexContextCstringLen
+ *
+ * lex constructor, with or without StringInfo object for de-escaped lexemes.
+ *
+ * Without is better as it makes the processing faster, so only make one
+ * if really required.
+ */
+JsonLexContext *
+makeJsonLexContextCstringLen(char *json, int len, int encoding, bool need_escapes)
+{
+ JsonLexContext *lex = palloc0(sizeof(JsonLexContext));
+
+ lex->input = lex->token_terminator = lex->line_start = json;
+ lex->line_number = 1;
+ lex->input_length = len;
+ lex->input_encoding = encoding;
+ if (need_escapes)
+ lex->strval = makeStringInfo();
+ return lex;
+}
+
+/*
+ * pg_parse_json
+ *
+ * Publicly visible entry point for the JSON parser.
+ *
+ * lex is a lexing context, set up for the json to be processed by calling
+ * makeJsonLexContext(). sem is a structure of function pointers to semantic
+ * action routines to be called at appropriate spots during parsing, and a
+ * pointer to a state object to be passed to those routines.
+ */
+JsonParseErrorType
+pg_parse_json(JsonLexContext *lex, JsonSemAction *sem)
+{
+ JsonTokenType tok;
+ JsonParseErrorType result;
+
+ /* get the initial token */
+ result = json_lex(lex);
+ if (result != JSON_SUCCESS)
+ return result;
+
+ tok = lex_peek(lex);
+
+ /* parse by recursive descent */
+ switch (tok)
+ {
+ case JSON_TOKEN_OBJECT_START:
+ result = parse_object(lex, sem);
+ break;
+ case JSON_TOKEN_ARRAY_START:
+ result = parse_array(lex, sem);
+ break;
+ default:
+ result = parse_scalar(lex, sem); /* json can be a bare scalar */
+ }
+
+ if (result == JSON_SUCCESS)
+ result = lex_expect(JSON_PARSE_END, lex, JSON_TOKEN_END);
+
+ return result;
+}
+
+/*
+ * json_count_array_elements
+ *
+ * Returns number of array elements in lex context at start of array token
+ * until end of array token at same nesting level.
+ *
+ * Designed to be called from array_start routines.
+ */
+JsonParseErrorType
+json_count_array_elements(JsonLexContext *lex, int *elements)
+{
+ JsonLexContext copylex;
+ int count;
+ JsonParseErrorType result;
+
+ /*
+ * It's safe to do this with a shallow copy because the lexical routines
+ * don't scribble on the input. They do scribble on the other pointers
+ * etc, so doing this with a copy makes that safe.
+ */
+ memcpy(&copylex, lex, sizeof(JsonLexContext));
+ copylex.strval = NULL; /* not interested in values here */
+ copylex.lex_level++;
+
+ count = 0;
+ result = lex_expect(JSON_PARSE_ARRAY_START, &copylex,
+ JSON_TOKEN_ARRAY_START);
+ if (result != JSON_SUCCESS)
+ return result;
+ if (lex_peek(&copylex) != JSON_TOKEN_ARRAY_END)
+ {
+ while (1)
+ {
+ count++;
+ result = parse_array_element(&copylex, &nullSemAction);
+ if (result != JSON_SUCCESS)
+ return result;
+ if (copylex.token_type != JSON_TOKEN_COMMA)
+ break;
+ result = json_lex(&copylex);
+ if (result != JSON_SUCCESS)
+ return result;
+ }
+ }
+ result = lex_expect(JSON_PARSE_ARRAY_NEXT, &copylex,
+ JSON_TOKEN_ARRAY_END);
+ if (result != JSON_SUCCESS)
+ return result;
+
+ *elements = count;
+ return JSON_SUCCESS;
+}
+
+/*
+ * Recursive Descent parse routines. There is one for each structural
+ * element in a json document:
+ * - scalar (string, number, true, false, null)
+ * - array ( [ ] )
+ * - array element
+ * - object ( { } )
+ * - object field
+ */
+static inline JsonParseErrorType
+parse_scalar(JsonLexContext *lex, JsonSemAction *sem)
+{
+ char *val = NULL;
+ json_scalar_action sfunc = sem->scalar;
+ JsonTokenType tok = lex_peek(lex);
+ JsonParseErrorType result;
+
+ /* a scalar must be a string, a number, true, false, or null */
+ if (tok != JSON_TOKEN_STRING && tok != JSON_TOKEN_NUMBER &&
+ tok != JSON_TOKEN_TRUE && tok != JSON_TOKEN_FALSE &&
+ tok != JSON_TOKEN_NULL)
+ return report_parse_error(JSON_PARSE_VALUE, lex);
+
+ /* if no semantic function, just consume the token */
+ if (sfunc == NULL)
+ return json_lex(lex);
+
+ /* extract the de-escaped string value, or the raw lexeme */
+ if (lex_peek(lex) == JSON_TOKEN_STRING)
+ {
+ if (lex->strval != NULL)
+ val = pstrdup(lex->strval->data);
+ }
+ else
+ {
+ int len = (lex->token_terminator - lex->token_start);
+
+ val = palloc(len + 1);
+ memcpy(val, lex->token_start, len);
+ val[len] = '\0';
+ }
+
+ /* consume the token */
+ result = json_lex(lex);
+ if (result != JSON_SUCCESS)
+ return result;
+
+ /* invoke the callback */
+ result = (*sfunc) (sem->semstate, val, tok);
+
+ return result;
+}
+
+static JsonParseErrorType
+parse_object_field(JsonLexContext *lex, JsonSemAction *sem)
+{
+ /*
+ * An object field is "fieldname" : value where value can be a scalar,
+ * object or array. Note: in user-facing docs and error messages, we
+ * generally call a field name a "key".
+ */
+
+ char *fname = NULL; /* keep compiler quiet */
+ json_ofield_action ostart = sem->object_field_start;
+ json_ofield_action oend = sem->object_field_end;
+ bool isnull;
+ JsonTokenType tok;
+ JsonParseErrorType result;
+
+ if (lex_peek(lex) != JSON_TOKEN_STRING)
+ return report_parse_error(JSON_PARSE_STRING, lex);
+ if ((ostart != NULL || oend != NULL) && lex->strval != NULL)
+ fname = pstrdup(lex->strval->data);
+ result = json_lex(lex);
+ if (result != JSON_SUCCESS)
+ return result;
+
+ result = lex_expect(JSON_PARSE_OBJECT_LABEL, lex, JSON_TOKEN_COLON);
+ if (result != JSON_SUCCESS)
+ return result;
+
+ tok = lex_peek(lex);
+ isnull = tok == JSON_TOKEN_NULL;
+
+ if (ostart != NULL)
+ {
+ result = (*ostart) (sem->semstate, fname, isnull);
+ if (result != JSON_SUCCESS)
+ return result;
+ }
+
+ switch (tok)
+ {
+ case JSON_TOKEN_OBJECT_START:
+ result = parse_object(lex, sem);
+ break;
+ case JSON_TOKEN_ARRAY_START:
+ result = parse_array(lex, sem);
+ break;
+ default:
+ result = parse_scalar(lex, sem);
+ }
+ if (result != JSON_SUCCESS)
+ return result;
+
+ if (oend != NULL)
+ {
+ result = (*oend) (sem->semstate, fname, isnull);
+ if (result != JSON_SUCCESS)
+ return result;
+ }
+
+ return JSON_SUCCESS;
+}
+
+static JsonParseErrorType
+parse_object(JsonLexContext *lex, JsonSemAction *sem)
+{
+ /*
+ * an object is a possibly empty sequence of object fields, separated by
+ * commas and surrounded by curly braces.
+ */
+ json_struct_action ostart = sem->object_start;
+ json_struct_action oend = sem->object_end;
+ JsonTokenType tok;
+ JsonParseErrorType result;
+
+#ifndef FRONTEND
+ check_stack_depth();
+#endif
+
+ if (ostart != NULL)
+ {
+ result = (*ostart) (sem->semstate);
+ if (result != JSON_SUCCESS)
+ return result;
+ }
+
+ /*
+ * Data inside an object is at a higher nesting level than the object
+ * itself. Note that we increment this after we call the semantic routine
+ * for the object start and restore it before we call the routine for the
+ * object end.
+ */
+ lex->lex_level++;
+
+ Assert(lex_peek(lex) == JSON_TOKEN_OBJECT_START);
+ result = json_lex(lex);
+ if (result != JSON_SUCCESS)
+ return result;
+
+ tok = lex_peek(lex);
+ switch (tok)
+ {
+ case JSON_TOKEN_STRING:
+ result = parse_object_field(lex, sem);
+ while (result == JSON_SUCCESS && lex_peek(lex) == JSON_TOKEN_COMMA)
+ {
+ result = json_lex(lex);
+ if (result != JSON_SUCCESS)
+ break;
+ result = parse_object_field(lex, sem);
+ }
+ break;
+ case JSON_TOKEN_OBJECT_END:
+ break;
+ default:
+ /* case of an invalid initial token inside the object */
+ result = report_parse_error(JSON_PARSE_OBJECT_START, lex);
+ }
+ if (result != JSON_SUCCESS)
+ return result;
+
+ result = lex_expect(JSON_PARSE_OBJECT_NEXT, lex, JSON_TOKEN_OBJECT_END);
+ if (result != JSON_SUCCESS)
+ return result;
+
+ lex->lex_level--;
+
+ if (oend != NULL)
+ {
+ result = (*oend) (sem->semstate);
+ if (result != JSON_SUCCESS)
+ return result;
+ }
+
+ return JSON_SUCCESS;
+}
+
+static JsonParseErrorType
+parse_array_element(JsonLexContext *lex, JsonSemAction *sem)
+{
+ json_aelem_action astart = sem->array_element_start;
+ json_aelem_action aend = sem->array_element_end;
+ JsonTokenType tok = lex_peek(lex);
+ JsonParseErrorType result;
+ bool isnull;
+
+ isnull = tok == JSON_TOKEN_NULL;
+
+ if (astart != NULL)
+ {
+ result = (*astart) (sem->semstate, isnull);
+ if (result != JSON_SUCCESS)
+ return result;
+ }
+
+ /* an array element is any object, array or scalar */
+ switch (tok)
+ {
+ case JSON_TOKEN_OBJECT_START:
+ result = parse_object(lex, sem);
+ break;
+ case JSON_TOKEN_ARRAY_START:
+ result = parse_array(lex, sem);
+ break;
+ default:
+ result = parse_scalar(lex, sem);
+ }
+
+ if (result != JSON_SUCCESS)
+ return result;
+
+ if (aend != NULL)
+ {
+ result = (*aend) (sem->semstate, isnull);
+ if (result != JSON_SUCCESS)
+ return result;
+ }
+
+ return JSON_SUCCESS;
+}
+
+static JsonParseErrorType
+parse_array(JsonLexContext *lex, JsonSemAction *sem)
+{
+ /*
+ * an array is a possibly empty sequence of array elements, separated by
+ * commas and surrounded by square brackets.
+ */
+ json_struct_action astart = sem->array_start;
+ json_struct_action aend = sem->array_end;
+ JsonParseErrorType result;
+
+#ifndef FRONTEND
+ check_stack_depth();
+#endif
+
+ if (astart != NULL)
+ {
+ result = (*astart) (sem->semstate);
+ if (result != JSON_SUCCESS)
+ return result;
+ }
+
+ /*
+ * Data inside an array is at a higher nesting level than the array
+ * itself. Note that we increment this after we call the semantic routine
+ * for the array start and restore it before we call the routine for the
+ * array end.
+ */
+ lex->lex_level++;
+
+ result = lex_expect(JSON_PARSE_ARRAY_START, lex, JSON_TOKEN_ARRAY_START);
+ if (result == JSON_SUCCESS && lex_peek(lex) != JSON_TOKEN_ARRAY_END)
+ {
+ result = parse_array_element(lex, sem);
+
+ while (result == JSON_SUCCESS && lex_peek(lex) == JSON_TOKEN_COMMA)
+ {
+ result = json_lex(lex);
+ if (result != JSON_SUCCESS)
+ break;
+ result = parse_array_element(lex, sem);
+ }
+ }
+ if (result != JSON_SUCCESS)
+ return result;
+
+ result = lex_expect(JSON_PARSE_ARRAY_NEXT, lex, JSON_TOKEN_ARRAY_END);
+ if (result != JSON_SUCCESS)
+ return result;
+
+ lex->lex_level--;
+
+ if (aend != NULL)
+ {
+ result = (*aend) (sem->semstate);
+ if (result != JSON_SUCCESS)
+ return result;
+ }
+
+ return JSON_SUCCESS;
+}
+
+/*
+ * Lex one token from the input stream.
+ */
+JsonParseErrorType
+json_lex(JsonLexContext *lex)
+{
+ char *s;
+ char *const end = lex->input + lex->input_length;
+ JsonParseErrorType result;
+
+ /* Skip leading whitespace. */
+ s = lex->token_terminator;
+ while (s < end && (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r'))
+ {
+ if (*s++ == '\n')
+ {
+ ++lex->line_number;
+ lex->line_start = s;
+ }
+ }
+ lex->token_start = s;
+
+ /* Determine token type. */
+ if (s >= end)
+ {
+ lex->token_start = NULL;
+ lex->prev_token_terminator = lex->token_terminator;
+ lex->token_terminator = s;
+ lex->token_type = JSON_TOKEN_END;
+ }
+ else
+ {
+ switch (*s)
+ {
+ /* Single-character token, some kind of punctuation mark. */
+ case '{':
+ lex->prev_token_terminator = lex->token_terminator;
+ lex->token_terminator = s + 1;
+ lex->token_type = JSON_TOKEN_OBJECT_START;
+ break;
+ case '}':
+ lex->prev_token_terminator = lex->token_terminator;
+ lex->token_terminator = s + 1;
+ lex->token_type = JSON_TOKEN_OBJECT_END;
+ break;
+ case '[':
+ lex->prev_token_terminator = lex->token_terminator;
+ lex->token_terminator = s + 1;
+ lex->token_type = JSON_TOKEN_ARRAY_START;
+ break;
+ case ']':
+ lex->prev_token_terminator = lex->token_terminator;
+ lex->token_terminator = s + 1;
+ lex->token_type = JSON_TOKEN_ARRAY_END;
+ break;
+ case ',':
+ lex->prev_token_terminator = lex->token_terminator;
+ lex->token_terminator = s + 1;
+ lex->token_type = JSON_TOKEN_COMMA;
+ break;
+ case ':':
+ lex->prev_token_terminator = lex->token_terminator;
+ lex->token_terminator = s + 1;
+ lex->token_type = JSON_TOKEN_COLON;
+ break;
+ case '"':
+ /* string */
+ result = json_lex_string(lex);
+ if (result != JSON_SUCCESS)
+ return result;
+ lex->token_type = JSON_TOKEN_STRING;
+ break;
+ case '-':
+ /* Negative number. */
+ result = json_lex_number(lex, s + 1, NULL, NULL);
+ if (result != JSON_SUCCESS)
+ return result;
+ lex->token_type = JSON_TOKEN_NUMBER;
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ /* Positive number. */
+ result = json_lex_number(lex, s, NULL, NULL);
+ if (result != JSON_SUCCESS)
+ return result;
+ lex->token_type = JSON_TOKEN_NUMBER;
+ break;
+ default:
+ {
+ char *p;
+
+ /*
+ * We're not dealing with a string, number, legal
+ * punctuation mark, or end of string. The only legal
+ * tokens we might find here are true, false, and null,
+ * but for error reporting purposes we scan until we see a
+ * non-alphanumeric character. That way, we can report
+ * the whole word as an unexpected token, rather than just
+ * some unintuitive prefix thereof.
+ */
+ for (p = s; p < end && JSON_ALPHANUMERIC_CHAR(*p); p++)
+ /* skip */ ;
+
+ /*
+ * We got some sort of unexpected punctuation or an
+ * otherwise unexpected character, so just complain about
+ * that one character.
+ */
+ if (p == s)
+ {
+ lex->prev_token_terminator = lex->token_terminator;
+ lex->token_terminator = s + 1;
+ return JSON_INVALID_TOKEN;
+ }
+
+ /*
+ * We've got a real alphanumeric token here. If it
+ * happens to be true, false, or null, all is well. If
+ * not, error out.
+ */
+ lex->prev_token_terminator = lex->token_terminator;
+ lex->token_terminator = p;
+ if (p - s == 4)
+ {
+ if (memcmp(s, "true", 4) == 0)
+ lex->token_type = JSON_TOKEN_TRUE;
+ else if (memcmp(s, "null", 4) == 0)
+ lex->token_type = JSON_TOKEN_NULL;
+ else
+ return JSON_INVALID_TOKEN;
+ }
+ else if (p - s == 5 && memcmp(s, "false", 5) == 0)
+ lex->token_type = JSON_TOKEN_FALSE;
+ else
+ return JSON_INVALID_TOKEN;
+ }
+ } /* end of switch */
+ }
+
+ return JSON_SUCCESS;
+}
+
+/*
+ * The next token in the input stream is known to be a string; lex it.
+ *
+ * If lex->strval isn't NULL, fill it with the decoded string.
+ * Set lex->token_terminator to the end of the decoded input, and in
+ * success cases, transfer its previous value to lex->prev_token_terminator.
+ * Return JSON_SUCCESS or an error code.
+ *
+ * Note: be careful that all error exits advance lex->token_terminator
+ * to the point after the character we detected the error on.
+ */
+static inline JsonParseErrorType
+json_lex_string(JsonLexContext *lex)
+{
+ char *s;
+ char *const end = lex->input + lex->input_length;
+ int hi_surrogate = -1;
+
+ /* Convenience macros for error exits */
+#define FAIL_AT_CHAR_START(code) \
+ do { \
+ lex->token_terminator = s; \
+ return code; \
+ } while (0)
+#define FAIL_AT_CHAR_END(code) \
+ do { \
+ lex->token_terminator = \
+ s + pg_encoding_mblen_bounded(lex->input_encoding, s); \
+ return code; \
+ } while (0)
+
+ if (lex->strval != NULL)
+ resetStringInfo(lex->strval);
+
+ Assert(lex->input_length > 0);
+ s = lex->token_start;
+ for (;;)
+ {
+ s++;
+ /* Premature end of the string. */
+ if (s >= end)
+ FAIL_AT_CHAR_START(JSON_INVALID_TOKEN);
+ else if (*s == '"')
+ break;
+ else if (*s == '\\')
+ {
+ /* OK, we have an escape character. */
+ s++;
+ if (s >= end)
+ FAIL_AT_CHAR_START(JSON_INVALID_TOKEN);
+ else if (*s == 'u')
+ {
+ int i;
+ int ch = 0;
+
+ for (i = 1; i <= 4; i++)
+ {
+ s++;
+ if (s >= end)
+ FAIL_AT_CHAR_START(JSON_INVALID_TOKEN);
+ else if (*s >= '0' && *s <= '9')
+ ch = (ch * 16) + (*s - '0');
+ else if (*s >= 'a' && *s <= 'f')
+ ch = (ch * 16) + (*s - 'a') + 10;
+ else if (*s >= 'A' && *s <= 'F')
+ ch = (ch * 16) + (*s - 'A') + 10;
+ else
+ FAIL_AT_CHAR_END(JSON_UNICODE_ESCAPE_FORMAT);
+ }
+ if (lex->strval != NULL)
+ {
+ /*
+ * Combine surrogate pairs.
+ */
+ if (is_utf16_surrogate_first(ch))
+ {
+ if (hi_surrogate != -1)
+ FAIL_AT_CHAR_END(JSON_UNICODE_HIGH_SURROGATE);
+ hi_surrogate = ch;
+ continue;
+ }
+ else if (is_utf16_surrogate_second(ch))
+ {
+ if (hi_surrogate == -1)
+ FAIL_AT_CHAR_END(JSON_UNICODE_LOW_SURROGATE);
+ ch = surrogate_pair_to_codepoint(hi_surrogate, ch);
+ hi_surrogate = -1;
+ }
+
+ if (hi_surrogate != -1)
+ FAIL_AT_CHAR_END(JSON_UNICODE_LOW_SURROGATE);
+
+ /*
+ * Reject invalid cases. We can't have a value above
+ * 0xFFFF here (since we only accepted 4 hex digits
+ * above), so no need to test for out-of-range chars.
+ */
+ if (ch == 0)
+ {
+ /* We can't allow this, since our TEXT type doesn't */
+ FAIL_AT_CHAR_END(JSON_UNICODE_CODE_POINT_ZERO);
+ }
+
+ /*
+ * Add the represented character to lex->strval. In the
+ * backend, we can let pg_unicode_to_server_noerror()
+ * handle any required character set conversion; in
+ * frontend, we can only deal with trivial conversions.
+ */
+#ifndef FRONTEND
+ {
+ char cbuf[MAX_UNICODE_EQUIVALENT_STRING + 1];
+
+ if (!pg_unicode_to_server_noerror(ch, (unsigned char *) cbuf))
+ FAIL_AT_CHAR_END(JSON_UNICODE_UNTRANSLATABLE);
+ appendStringInfoString(lex->strval, cbuf);
+ }
+#else
+ if (lex->input_encoding == PG_UTF8)
+ {
+ /* OK, we can map the code point to UTF8 easily */
+ char utf8str[5];
+ int utf8len;
+
+ unicode_to_utf8(ch, (unsigned char *) utf8str);
+ utf8len = pg_utf_mblen((unsigned char *) utf8str);
+ appendBinaryStringInfo(lex->strval, utf8str, utf8len);
+ }
+ else if (ch <= 0x007f)
+ {
+ /* The ASCII range is the same in all encodings */
+ appendStringInfoChar(lex->strval, (char) ch);
+ }
+ else
+ FAIL_AT_CHAR_END(JSON_UNICODE_HIGH_ESCAPE);
+#endif /* FRONTEND */
+ }
+ }
+ else if (lex->strval != NULL)
+ {
+ if (hi_surrogate != -1)
+ FAIL_AT_CHAR_END(JSON_UNICODE_LOW_SURROGATE);
+
+ switch (*s)
+ {
+ case '"':
+ case '\\':
+ case '/':
+ appendStringInfoChar(lex->strval, *s);
+ break;
+ case 'b':
+ appendStringInfoChar(lex->strval, '\b');
+ break;
+ case 'f':
+ appendStringInfoChar(lex->strval, '\f');
+ break;
+ case 'n':
+ appendStringInfoChar(lex->strval, '\n');
+ break;
+ case 'r':
+ appendStringInfoChar(lex->strval, '\r');
+ break;
+ case 't':
+ appendStringInfoChar(lex->strval, '\t');
+ break;
+ default:
+
+ /*
+ * Not a valid string escape, so signal error. We
+ * adjust token_start so that just the escape sequence
+ * is reported, not the whole string.
+ */
+ lex->token_start = s;
+ FAIL_AT_CHAR_END(JSON_ESCAPING_INVALID);
+ }
+ }
+ else if (strchr("\"\\/bfnrt", *s) == NULL)
+ {
+ /*
+ * Simpler processing if we're not bothered about de-escaping
+ *
+ * It's very tempting to remove the strchr() call here and
+ * replace it with a switch statement, but testing so far has
+ * shown it's not a performance win.
+ */
+ lex->token_start = s;
+ FAIL_AT_CHAR_END(JSON_ESCAPING_INVALID);
+ }
+ }
+ else
+ {
+ char *p = s;
+
+ if (hi_surrogate != -1)
+ FAIL_AT_CHAR_END(JSON_UNICODE_LOW_SURROGATE);
+
+ /*
+ * Skip to the first byte that requires special handling, so we
+ * can batch calls to appendBinaryStringInfo.
+ */
+ while (p < end - sizeof(Vector8) &&
+ !pg_lfind8('\\', (uint8 *) p, sizeof(Vector8)) &&
+ !pg_lfind8('"', (uint8 *) p, sizeof(Vector8)) &&
+ !pg_lfind8_le(31, (uint8 *) p, sizeof(Vector8)))
+ p += sizeof(Vector8);
+
+ for (; p < end; p++)
+ {
+ if (*p == '\\' || *p == '"')
+ break;
+ else if ((unsigned char) *p <= 31)
+ {
+ /* Per RFC4627, these characters MUST be escaped. */
+ /*
+ * Since *p isn't printable, exclude it from the context
+ * string
+ */
+ lex->token_terminator = p;
+ return JSON_ESCAPING_REQUIRED;
+ }
+ }
+
+ if (lex->strval != NULL)
+ appendBinaryStringInfo(lex->strval, s, p - s);
+
+ /*
+ * s will be incremented at the top of the loop, so set it to just
+ * behind our lookahead position
+ */
+ s = p - 1;
+ }
+ }
+
+ if (hi_surrogate != -1)
+ {
+ lex->token_terminator = s + 1;
+ return JSON_UNICODE_LOW_SURROGATE;
+ }
+
+ /* Hooray, we found the end of the string! */
+ lex->prev_token_terminator = lex->token_terminator;
+ lex->token_terminator = s + 1;
+ return JSON_SUCCESS;
+
+#undef FAIL_AT_CHAR_START
+#undef FAIL_AT_CHAR_END
+}
+
+/*
+ * The next token in the input stream is known to be a number; lex it.
+ *
+ * In JSON, a number consists of four parts:
+ *
+ * (1) An optional minus sign ('-').
+ *
+ * (2) Either a single '0', or a string of one or more digits that does not
+ * begin with a '0'.
+ *
+ * (3) An optional decimal part, consisting of a period ('.') followed by
+ * one or more digits. (Note: While this part can be omitted
+ * completely, it's not OK to have only the decimal point without
+ * any digits afterwards.)
+ *
+ * (4) An optional exponent part, consisting of 'e' or 'E', optionally
+ * followed by '+' or '-', followed by one or more digits. (Note:
+ * As with the decimal part, if 'e' or 'E' is present, it must be
+ * followed by at least one digit.)
+ *
+ * The 's' argument to this function points to the ostensible beginning
+ * of part 2 - i.e. the character after any optional minus sign, or the
+ * first character of the string if there is none.
+ *
+ * If num_err is not NULL, we return an error flag to *num_err rather than
+ * raising an error for a badly-formed number. Also, if total_len is not NULL
+ * the distance from lex->input to the token end+1 is returned to *total_len.
+ */
+static inline JsonParseErrorType
+json_lex_number(JsonLexContext *lex, char *s,
+ bool *num_err, int *total_len)
+{
+ bool error = false;
+ int len = s - lex->input;
+
+ /* Part (1): leading sign indicator. */
+ /* Caller already did this for us; so do nothing. */
+
+ /* Part (2): parse main digit string. */
+ if (len < lex->input_length && *s == '0')
+ {
+ s++;
+ len++;
+ }
+ else if (len < lex->input_length && *s >= '1' && *s <= '9')
+ {
+ do
+ {
+ s++;
+ len++;
+ } while (len < lex->input_length && *s >= '0' && *s <= '9');
+ }
+ else
+ error = true;
+
+ /* Part (3): parse optional decimal portion. */
+ if (len < lex->input_length && *s == '.')
+ {
+ s++;
+ len++;
+ if (len == lex->input_length || *s < '0' || *s > '9')
+ error = true;
+ else
+ {
+ do
+ {
+ s++;
+ len++;
+ } while (len < lex->input_length && *s >= '0' && *s <= '9');
+ }
+ }
+
+ /* Part (4): parse optional exponent. */
+ if (len < lex->input_length && (*s == 'e' || *s == 'E'))
+ {
+ s++;
+ len++;
+ if (len < lex->input_length && (*s == '+' || *s == '-'))
+ {
+ s++;
+ len++;
+ }
+ if (len == lex->input_length || *s < '0' || *s > '9')
+ error = true;
+ else
+ {
+ do
+ {
+ s++;
+ len++;
+ } while (len < lex->input_length && *s >= '0' && *s <= '9');
+ }
+ }
+
+ /*
+ * Check for trailing garbage. As in json_lex(), any alphanumeric stuff
+ * here should be considered part of the token for error-reporting
+ * purposes.
+ */
+ for (; len < lex->input_length && JSON_ALPHANUMERIC_CHAR(*s); s++, len++)
+ error = true;
+
+ if (total_len != NULL)
+ *total_len = len;
+
+ if (num_err != NULL)
+ {
+ /* let the caller handle any error */
+ *num_err = error;
+ }
+ else
+ {
+ /* return token endpoint */
+ lex->prev_token_terminator = lex->token_terminator;
+ lex->token_terminator = s;
+ /* handle error if any */
+ if (error)
+ return JSON_INVALID_TOKEN;
+ }
+
+ return JSON_SUCCESS;
+}
+
+/*
+ * Report a parse error.
+ *
+ * lex->token_start and lex->token_terminator must identify the current token.
+ */
+static JsonParseErrorType
+report_parse_error(JsonParseContext ctx, JsonLexContext *lex)
+{
+ /* Handle case where the input ended prematurely. */
+ if (lex->token_start == NULL || lex->token_type == JSON_TOKEN_END)
+ return JSON_EXPECTED_MORE;
+
+ /* Otherwise choose the error type based on the parsing context. */
+ switch (ctx)
+ {
+ case JSON_PARSE_END:
+ return JSON_EXPECTED_END;
+ case JSON_PARSE_VALUE:
+ return JSON_EXPECTED_JSON;
+ case JSON_PARSE_STRING:
+ return JSON_EXPECTED_STRING;
+ case JSON_PARSE_ARRAY_START:
+ return JSON_EXPECTED_ARRAY_FIRST;
+ case JSON_PARSE_ARRAY_NEXT:
+ return JSON_EXPECTED_ARRAY_NEXT;
+ case JSON_PARSE_OBJECT_START:
+ return JSON_EXPECTED_OBJECT_FIRST;
+ case JSON_PARSE_OBJECT_LABEL:
+ return JSON_EXPECTED_COLON;
+ case JSON_PARSE_OBJECT_NEXT:
+ return JSON_EXPECTED_OBJECT_NEXT;
+ case JSON_PARSE_OBJECT_COMMA:
+ return JSON_EXPECTED_STRING;
+ }
+
+ /*
+ * We don't use a default: case, so that the compiler will warn about
+ * unhandled enum values.
+ */
+ Assert(false);
+ return JSON_SUCCESS; /* silence stupider compilers */
+}
+
+
+#ifndef FRONTEND
+/*
+ * Extract the current token from a lexing context, for error reporting.
+ */
+static char *
+extract_token(JsonLexContext *lex)
+{
+ int toklen = lex->token_terminator - lex->token_start;
+ char *token = palloc(toklen + 1);
+
+ memcpy(token, lex->token_start, toklen);
+ token[toklen] = '\0';
+ return token;
+}
+
+/*
+ * Construct an (already translated) detail message for a JSON error.
+ *
+ * Note that the error message generated by this routine may not be
+ * palloc'd, making it unsafe for frontend code as there is no way to
+ * know if this can be safely pfree'd or not.
+ */
+char *
+json_errdetail(JsonParseErrorType error, JsonLexContext *lex)
+{
+ switch (error)
+ {
+ case JSON_SUCCESS:
+ /* fall through to the error code after switch */
+ break;
+ case JSON_ESCAPING_INVALID:
+ return psprintf(_("Escape sequence \"\\%s\" is invalid."),
+ extract_token(lex));
+ case JSON_ESCAPING_REQUIRED:
+ return psprintf(_("Character with value 0x%02x must be escaped."),
+ (unsigned char) *(lex->token_terminator));
+ case JSON_EXPECTED_END:
+ return psprintf(_("Expected end of input, but found \"%s\"."),
+ extract_token(lex));
+ case JSON_EXPECTED_ARRAY_FIRST:
+ return psprintf(_("Expected array element or \"]\", but found \"%s\"."),
+ extract_token(lex));
+ case JSON_EXPECTED_ARRAY_NEXT:
+ return psprintf(_("Expected \",\" or \"]\", but found \"%s\"."),
+ extract_token(lex));
+ case JSON_EXPECTED_COLON:
+ return psprintf(_("Expected \":\", but found \"%s\"."),
+ extract_token(lex));
+ case JSON_EXPECTED_JSON:
+ return psprintf(_("Expected JSON value, but found \"%s\"."),
+ extract_token(lex));
+ case JSON_EXPECTED_MORE:
+ return _("The input string ended unexpectedly.");
+ case JSON_EXPECTED_OBJECT_FIRST:
+ return psprintf(_("Expected string or \"}\", but found \"%s\"."),
+ extract_token(lex));
+ case JSON_EXPECTED_OBJECT_NEXT:
+ return psprintf(_("Expected \",\" or \"}\", but found \"%s\"."),
+ extract_token(lex));
+ case JSON_EXPECTED_STRING:
+ return psprintf(_("Expected string, but found \"%s\"."),
+ extract_token(lex));
+ case JSON_INVALID_TOKEN:
+ return psprintf(_("Token \"%s\" is invalid."),
+ extract_token(lex));
+ case JSON_UNICODE_CODE_POINT_ZERO:
+ return _("\\u0000 cannot be converted to text.");
+ case JSON_UNICODE_ESCAPE_FORMAT:
+ return _("\"\\u\" must be followed by four hexadecimal digits.");
+ case JSON_UNICODE_HIGH_ESCAPE:
+ /* note: this case is only reachable in frontend not backend */
+ return _("Unicode escape values cannot be used for code point values above 007F when the encoding is not UTF8.");
+ case JSON_UNICODE_UNTRANSLATABLE:
+ /* note: this case is only reachable in backend not frontend */
+ return psprintf(_("Unicode escape value could not be translated to the server's encoding %s."),
+ GetDatabaseEncodingName());
+ case JSON_UNICODE_HIGH_SURROGATE:
+ return _("Unicode high surrogate must not follow a high surrogate.");
+ case JSON_UNICODE_LOW_SURROGATE:
+ return _("Unicode low surrogate must follow a high surrogate.");
+ case JSON_SEM_ACTION_FAILED:
+ /* fall through to the error code after switch */
+ break;
+ }
+
+ /*
+ * We don't use a default: case, so that the compiler will warn about
+ * unhandled enum values. But this needs to be here anyway to cover the
+ * possibility of an incorrect input.
+ */
+ elog(ERROR, "unexpected json parse error type: %d", (int) error);
+ return NULL;
+}
+#endif
diff --git a/contrib/libs/libpq/src/common/keywords.c b/contrib/libs/libpq/src/common/keywords.c
new file mode 100644
index 0000000000..b72f0d554f
--- /dev/null
+++ b/contrib/libs/libpq/src/common/keywords.c
@@ -0,0 +1,48 @@
+/*-------------------------------------------------------------------------
+ *
+ * keywords.c
+ * PostgreSQL's list of SQL keywords
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/common/keywords.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "c.h"
+
+#include "common/keywords.h"
+
+
+/* ScanKeywordList lookup data for SQL keywords */
+
+#include "kwlist_d.h"
+
+/* Keyword categories for SQL keywords */
+
+#define PG_KEYWORD(kwname, value, category, collabel) category,
+
+const uint8 ScanKeywordCategories[SCANKEYWORDS_NUM_KEYWORDS] = {
+#include "parser/kwlist.h"
+};
+
+#undef PG_KEYWORD
+
+/* Keyword can-be-bare-label flags for SQL keywords */
+
+#define PG_KEYWORD(kwname, value, category, collabel) collabel,
+
+#define BARE_LABEL true
+#define AS_LABEL false
+
+const bool ScanKeywordBareLabel[SCANKEYWORDS_NUM_KEYWORDS] = {
+#include "parser/kwlist.h"
+};
+
+#undef PG_KEYWORD
+#undef BARE_LABEL
+#undef AS_LABEL
diff --git a/contrib/libs/libpq/src/common/kwlist_d.h b/contrib/libs/libpq/src/common/kwlist_d.h
new file mode 100644
index 0000000000..e8af260237
--- /dev/null
+++ b/contrib/libs/libpq/src/common/kwlist_d.h
@@ -0,0 +1,1119 @@
+/*-------------------------------------------------------------------------
+ *
+ * kwlist_d.h
+ * List of keywords represented as a ScanKeywordList.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/tools/gen_keywordlist.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef KWLIST_D_H
+#define KWLIST_D_H
+
+#include "common/kwlookup.h"
+
+static const char ScanKeywords_kw_string[] =
+ "abort\0"
+ "absent\0"
+ "absolute\0"
+ "access\0"
+ "action\0"
+ "add\0"
+ "admin\0"
+ "after\0"
+ "aggregate\0"
+ "all\0"
+ "also\0"
+ "alter\0"
+ "always\0"
+ "analyse\0"
+ "analyze\0"
+ "and\0"
+ "any\0"
+ "array\0"
+ "as\0"
+ "asc\0"
+ "asensitive\0"
+ "assertion\0"
+ "assignment\0"
+ "asymmetric\0"
+ "at\0"
+ "atomic\0"
+ "attach\0"
+ "attribute\0"
+ "authorization\0"
+ "backward\0"
+ "before\0"
+ "begin\0"
+ "between\0"
+ "bigint\0"
+ "binary\0"
+ "bit\0"
+ "boolean\0"
+ "both\0"
+ "breadth\0"
+ "by\0"
+ "cache\0"
+ "call\0"
+ "called\0"
+ "cascade\0"
+ "cascaded\0"
+ "case\0"
+ "cast\0"
+ "catalog\0"
+ "chain\0"
+ "char\0"
+ "character\0"
+ "characteristics\0"
+ "check\0"
+ "checkpoint\0"
+ "class\0"
+ "close\0"
+ "cluster\0"
+ "coalesce\0"
+ "collate\0"
+ "collation\0"
+ "column\0"
+ "columns\0"
+ "comment\0"
+ "comments\0"
+ "commit\0"
+ "committed\0"
+ "compression\0"
+ "concurrently\0"
+ "configuration\0"
+ "conflict\0"
+ "connection\0"
+ "constraint\0"
+ "constraints\0"
+ "content\0"
+ "continue\0"
+ "conversion\0"
+ "copy\0"
+ "cost\0"
+ "create\0"
+ "cross\0"
+ "csv\0"
+ "cube\0"
+ "current\0"
+ "current_catalog\0"
+ "current_date\0"
+ "current_role\0"
+ "current_schema\0"
+ "current_time\0"
+ "current_timestamp\0"
+ "current_user\0"
+ "cursor\0"
+ "cycle\0"
+ "data\0"
+ "database\0"
+ "day\0"
+ "deallocate\0"
+ "dec\0"
+ "decimal\0"
+ "declare\0"
+ "default\0"
+ "defaults\0"
+ "deferrable\0"
+ "deferred\0"
+ "definer\0"
+ "delete\0"
+ "delimiter\0"
+ "delimiters\0"
+ "depends\0"
+ "depth\0"
+ "desc\0"
+ "detach\0"
+ "dictionary\0"
+ "disable\0"
+ "discard\0"
+ "distinct\0"
+ "do\0"
+ "document\0"
+ "domain\0"
+ "double\0"
+ "drop\0"
+ "each\0"
+ "else\0"
+ "enable\0"
+ "encoding\0"
+ "encrypted\0"
+ "end\0"
+ "enum\0"
+ "escape\0"
+ "event\0"
+ "except\0"
+ "exclude\0"
+ "excluding\0"
+ "exclusive\0"
+ "execute\0"
+ "exists\0"
+ "explain\0"
+ "expression\0"
+ "extension\0"
+ "external\0"
+ "extract\0"
+ "false\0"
+ "family\0"
+ "fetch\0"
+ "filter\0"
+ "finalize\0"
+ "first\0"
+ "float\0"
+ "following\0"
+ "for\0"
+ "force\0"
+ "foreign\0"
+ "format\0"
+ "forward\0"
+ "freeze\0"
+ "from\0"
+ "full\0"
+ "function\0"
+ "functions\0"
+ "generated\0"
+ "global\0"
+ "grant\0"
+ "granted\0"
+ "greatest\0"
+ "group\0"
+ "grouping\0"
+ "groups\0"
+ "handler\0"
+ "having\0"
+ "header\0"
+ "hold\0"
+ "hour\0"
+ "identity\0"
+ "if\0"
+ "ilike\0"
+ "immediate\0"
+ "immutable\0"
+ "implicit\0"
+ "import\0"
+ "in\0"
+ "include\0"
+ "including\0"
+ "increment\0"
+ "indent\0"
+ "index\0"
+ "indexes\0"
+ "inherit\0"
+ "inherits\0"
+ "initially\0"
+ "inline\0"
+ "inner\0"
+ "inout\0"
+ "input\0"
+ "insensitive\0"
+ "insert\0"
+ "instead\0"
+ "int\0"
+ "integer\0"
+ "intersect\0"
+ "interval\0"
+ "into\0"
+ "invoker\0"
+ "is\0"
+ "isnull\0"
+ "isolation\0"
+ "join\0"
+ "json\0"
+ "json_array\0"
+ "json_arrayagg\0"
+ "json_object\0"
+ "json_objectagg\0"
+ "key\0"
+ "keys\0"
+ "label\0"
+ "language\0"
+ "large\0"
+ "last\0"
+ "lateral\0"
+ "leading\0"
+ "leakproof\0"
+ "least\0"
+ "left\0"
+ "level\0"
+ "like\0"
+ "limit\0"
+ "listen\0"
+ "load\0"
+ "local\0"
+ "localtime\0"
+ "localtimestamp\0"
+ "location\0"
+ "lock\0"
+ "locked\0"
+ "logged\0"
+ "mapping\0"
+ "match\0"
+ "matched\0"
+ "materialized\0"
+ "maxvalue\0"
+ "merge\0"
+ "method\0"
+ "minute\0"
+ "minvalue\0"
+ "mode\0"
+ "month\0"
+ "move\0"
+ "name\0"
+ "names\0"
+ "national\0"
+ "natural\0"
+ "nchar\0"
+ "new\0"
+ "next\0"
+ "nfc\0"
+ "nfd\0"
+ "nfkc\0"
+ "nfkd\0"
+ "no\0"
+ "none\0"
+ "normalize\0"
+ "normalized\0"
+ "not\0"
+ "nothing\0"
+ "notify\0"
+ "notnull\0"
+ "nowait\0"
+ "null\0"
+ "nullif\0"
+ "nulls\0"
+ "numeric\0"
+ "object\0"
+ "of\0"
+ "off\0"
+ "offset\0"
+ "oids\0"
+ "old\0"
+ "on\0"
+ "only\0"
+ "operator\0"
+ "option\0"
+ "options\0"
+ "or\0"
+ "order\0"
+ "ordinality\0"
+ "others\0"
+ "out\0"
+ "outer\0"
+ "over\0"
+ "overlaps\0"
+ "overlay\0"
+ "overriding\0"
+ "owned\0"
+ "owner\0"
+ "parallel\0"
+ "parameter\0"
+ "parser\0"
+ "partial\0"
+ "partition\0"
+ "passing\0"
+ "password\0"
+ "placing\0"
+ "plans\0"
+ "policy\0"
+ "position\0"
+ "preceding\0"
+ "precision\0"
+ "prepare\0"
+ "prepared\0"
+ "preserve\0"
+ "primary\0"
+ "prior\0"
+ "privileges\0"
+ "procedural\0"
+ "procedure\0"
+ "procedures\0"
+ "program\0"
+ "publication\0"
+ "quote\0"
+ "range\0"
+ "read\0"
+ "real\0"
+ "reassign\0"
+ "recheck\0"
+ "recursive\0"
+ "ref\0"
+ "references\0"
+ "referencing\0"
+ "refresh\0"
+ "reindex\0"
+ "relative\0"
+ "release\0"
+ "rename\0"
+ "repeatable\0"
+ "replace\0"
+ "replica\0"
+ "reset\0"
+ "restart\0"
+ "restrict\0"
+ "return\0"
+ "returning\0"
+ "returns\0"
+ "revoke\0"
+ "right\0"
+ "role\0"
+ "rollback\0"
+ "rollup\0"
+ "routine\0"
+ "routines\0"
+ "row\0"
+ "rows\0"
+ "rule\0"
+ "savepoint\0"
+ "scalar\0"
+ "schema\0"
+ "schemas\0"
+ "scroll\0"
+ "search\0"
+ "second\0"
+ "security\0"
+ "select\0"
+ "sequence\0"
+ "sequences\0"
+ "serializable\0"
+ "server\0"
+ "session\0"
+ "session_user\0"
+ "set\0"
+ "setof\0"
+ "sets\0"
+ "share\0"
+ "show\0"
+ "similar\0"
+ "simple\0"
+ "skip\0"
+ "smallint\0"
+ "snapshot\0"
+ "some\0"
+ "sql\0"
+ "stable\0"
+ "standalone\0"
+ "start\0"
+ "statement\0"
+ "statistics\0"
+ "stdin\0"
+ "stdout\0"
+ "storage\0"
+ "stored\0"
+ "strict\0"
+ "strip\0"
+ "subscription\0"
+ "substring\0"
+ "support\0"
+ "symmetric\0"
+ "sysid\0"
+ "system\0"
+ "system_user\0"
+ "table\0"
+ "tables\0"
+ "tablesample\0"
+ "tablespace\0"
+ "temp\0"
+ "template\0"
+ "temporary\0"
+ "text\0"
+ "then\0"
+ "ties\0"
+ "time\0"
+ "timestamp\0"
+ "to\0"
+ "trailing\0"
+ "transaction\0"
+ "transform\0"
+ "treat\0"
+ "trigger\0"
+ "trim\0"
+ "true\0"
+ "truncate\0"
+ "trusted\0"
+ "type\0"
+ "types\0"
+ "uescape\0"
+ "unbounded\0"
+ "uncommitted\0"
+ "unencrypted\0"
+ "union\0"
+ "unique\0"
+ "unknown\0"
+ "unlisten\0"
+ "unlogged\0"
+ "until\0"
+ "update\0"
+ "user\0"
+ "using\0"
+ "vacuum\0"
+ "valid\0"
+ "validate\0"
+ "validator\0"
+ "value\0"
+ "values\0"
+ "varchar\0"
+ "variadic\0"
+ "varying\0"
+ "verbose\0"
+ "version\0"
+ "view\0"
+ "views\0"
+ "volatile\0"
+ "when\0"
+ "where\0"
+ "whitespace\0"
+ "window\0"
+ "with\0"
+ "within\0"
+ "without\0"
+ "work\0"
+ "wrapper\0"
+ "write\0"
+ "xml\0"
+ "xmlattributes\0"
+ "xmlconcat\0"
+ "xmlelement\0"
+ "xmlexists\0"
+ "xmlforest\0"
+ "xmlnamespaces\0"
+ "xmlparse\0"
+ "xmlpi\0"
+ "xmlroot\0"
+ "xmlserialize\0"
+ "xmltable\0"
+ "year\0"
+ "yes\0"
+ "zone";
+
+static const uint16 ScanKeywords_kw_offsets[] = {
+ 0,
+ 6,
+ 13,
+ 22,
+ 29,
+ 36,
+ 40,
+ 46,
+ 52,
+ 62,
+ 66,
+ 71,
+ 77,
+ 84,
+ 92,
+ 100,
+ 104,
+ 108,
+ 114,
+ 117,
+ 121,
+ 132,
+ 142,
+ 153,
+ 164,
+ 167,
+ 174,
+ 181,
+ 191,
+ 205,
+ 214,
+ 221,
+ 227,
+ 235,
+ 242,
+ 249,
+ 253,
+ 261,
+ 266,
+ 274,
+ 277,
+ 283,
+ 288,
+ 295,
+ 303,
+ 312,
+ 317,
+ 322,
+ 330,
+ 336,
+ 341,
+ 351,
+ 367,
+ 373,
+ 384,
+ 390,
+ 396,
+ 404,
+ 413,
+ 421,
+ 431,
+ 438,
+ 446,
+ 454,
+ 463,
+ 470,
+ 480,
+ 492,
+ 505,
+ 519,
+ 528,
+ 539,
+ 550,
+ 562,
+ 570,
+ 579,
+ 590,
+ 595,
+ 600,
+ 607,
+ 613,
+ 617,
+ 622,
+ 630,
+ 646,
+ 659,
+ 672,
+ 687,
+ 700,
+ 718,
+ 731,
+ 738,
+ 744,
+ 749,
+ 758,
+ 762,
+ 773,
+ 777,
+ 785,
+ 793,
+ 801,
+ 810,
+ 821,
+ 830,
+ 838,
+ 845,
+ 855,
+ 866,
+ 874,
+ 880,
+ 885,
+ 892,
+ 903,
+ 911,
+ 919,
+ 928,
+ 931,
+ 940,
+ 947,
+ 954,
+ 959,
+ 964,
+ 969,
+ 976,
+ 985,
+ 995,
+ 999,
+ 1004,
+ 1011,
+ 1017,
+ 1024,
+ 1032,
+ 1042,
+ 1052,
+ 1060,
+ 1067,
+ 1075,
+ 1086,
+ 1096,
+ 1105,
+ 1113,
+ 1119,
+ 1126,
+ 1132,
+ 1139,
+ 1148,
+ 1154,
+ 1160,
+ 1170,
+ 1174,
+ 1180,
+ 1188,
+ 1195,
+ 1203,
+ 1210,
+ 1215,
+ 1220,
+ 1229,
+ 1239,
+ 1249,
+ 1256,
+ 1262,
+ 1270,
+ 1279,
+ 1285,
+ 1294,
+ 1301,
+ 1309,
+ 1316,
+ 1323,
+ 1328,
+ 1333,
+ 1342,
+ 1345,
+ 1351,
+ 1361,
+ 1371,
+ 1380,
+ 1387,
+ 1390,
+ 1398,
+ 1408,
+ 1418,
+ 1425,
+ 1431,
+ 1439,
+ 1447,
+ 1456,
+ 1466,
+ 1473,
+ 1479,
+ 1485,
+ 1491,
+ 1503,
+ 1510,
+ 1518,
+ 1522,
+ 1530,
+ 1540,
+ 1549,
+ 1554,
+ 1562,
+ 1565,
+ 1572,
+ 1582,
+ 1587,
+ 1592,
+ 1603,
+ 1617,
+ 1629,
+ 1644,
+ 1648,
+ 1653,
+ 1659,
+ 1668,
+ 1674,
+ 1679,
+ 1687,
+ 1695,
+ 1705,
+ 1711,
+ 1716,
+ 1722,
+ 1727,
+ 1733,
+ 1740,
+ 1745,
+ 1751,
+ 1761,
+ 1776,
+ 1785,
+ 1790,
+ 1797,
+ 1804,
+ 1812,
+ 1818,
+ 1826,
+ 1839,
+ 1848,
+ 1854,
+ 1861,
+ 1868,
+ 1877,
+ 1882,
+ 1888,
+ 1893,
+ 1898,
+ 1904,
+ 1913,
+ 1921,
+ 1927,
+ 1931,
+ 1936,
+ 1940,
+ 1944,
+ 1949,
+ 1954,
+ 1957,
+ 1962,
+ 1972,
+ 1983,
+ 1987,
+ 1995,
+ 2002,
+ 2010,
+ 2017,
+ 2022,
+ 2029,
+ 2035,
+ 2043,
+ 2050,
+ 2053,
+ 2057,
+ 2064,
+ 2069,
+ 2073,
+ 2076,
+ 2081,
+ 2090,
+ 2097,
+ 2105,
+ 2108,
+ 2114,
+ 2125,
+ 2132,
+ 2136,
+ 2142,
+ 2147,
+ 2156,
+ 2164,
+ 2175,
+ 2181,
+ 2187,
+ 2196,
+ 2206,
+ 2213,
+ 2221,
+ 2231,
+ 2239,
+ 2248,
+ 2256,
+ 2262,
+ 2269,
+ 2278,
+ 2288,
+ 2298,
+ 2306,
+ 2315,
+ 2324,
+ 2332,
+ 2338,
+ 2349,
+ 2360,
+ 2370,
+ 2381,
+ 2389,
+ 2401,
+ 2407,
+ 2413,
+ 2418,
+ 2423,
+ 2432,
+ 2440,
+ 2450,
+ 2454,
+ 2465,
+ 2477,
+ 2485,
+ 2493,
+ 2502,
+ 2510,
+ 2517,
+ 2528,
+ 2536,
+ 2544,
+ 2550,
+ 2558,
+ 2567,
+ 2574,
+ 2584,
+ 2592,
+ 2599,
+ 2605,
+ 2610,
+ 2619,
+ 2626,
+ 2634,
+ 2643,
+ 2647,
+ 2652,
+ 2657,
+ 2667,
+ 2674,
+ 2681,
+ 2689,
+ 2696,
+ 2703,
+ 2710,
+ 2719,
+ 2726,
+ 2735,
+ 2745,
+ 2758,
+ 2765,
+ 2773,
+ 2786,
+ 2790,
+ 2796,
+ 2801,
+ 2807,
+ 2812,
+ 2820,
+ 2827,
+ 2832,
+ 2841,
+ 2850,
+ 2855,
+ 2859,
+ 2866,
+ 2877,
+ 2883,
+ 2893,
+ 2904,
+ 2910,
+ 2917,
+ 2925,
+ 2932,
+ 2939,
+ 2945,
+ 2958,
+ 2968,
+ 2976,
+ 2986,
+ 2992,
+ 2999,
+ 3011,
+ 3017,
+ 3024,
+ 3036,
+ 3047,
+ 3052,
+ 3061,
+ 3071,
+ 3076,
+ 3081,
+ 3086,
+ 3091,
+ 3101,
+ 3104,
+ 3113,
+ 3125,
+ 3135,
+ 3141,
+ 3149,
+ 3154,
+ 3159,
+ 3168,
+ 3176,
+ 3181,
+ 3187,
+ 3195,
+ 3205,
+ 3217,
+ 3229,
+ 3235,
+ 3242,
+ 3250,
+ 3259,
+ 3268,
+ 3274,
+ 3281,
+ 3286,
+ 3292,
+ 3299,
+ 3305,
+ 3314,
+ 3324,
+ 3330,
+ 3337,
+ 3345,
+ 3354,
+ 3362,
+ 3370,
+ 3378,
+ 3383,
+ 3389,
+ 3398,
+ 3403,
+ 3409,
+ 3420,
+ 3427,
+ 3432,
+ 3439,
+ 3447,
+ 3452,
+ 3460,
+ 3466,
+ 3470,
+ 3484,
+ 3494,
+ 3505,
+ 3515,
+ 3525,
+ 3539,
+ 3548,
+ 3554,
+ 3562,
+ 3575,
+ 3584,
+ 3589,
+ 3593,
+};
+
+#define SCANKEYWORDS_NUM_KEYWORDS 471
+
+static int
+ScanKeywords_hash_func(const void *key, size_t keylen)
+{
+ static const int16 h[943] = {
+ 543, -186, 201, 0, 32767, 32767, 32767, 32767,
+ 221, -207, 32767, 0, 135, 283, 32767, 454,
+ 14, 79, 32767, 32767, 77, 32767, 102, 160,
+ 0, 32767, 151, 32767, 30, 392, -322, 452,
+ 32767, 0, 32767, 0, 0, 32767, 32767, 32767,
+ 234, 32767, 0, 32767, 0, 631, 32767, 368,
+ 80, 0, 0, -115, 32767, 285, 32767, 423,
+ 0, 32767, 155, 229, 32767, 126, 291, 165,
+ -22, 400, 327, 32767, 32767, 32767, 32767, -399,
+ 0, 406, 32767, 210, 1102, -203, 32767, 32767,
+ 32767, -944, 0, -188, 32767, 32767, 0, 347,
+ 32767, 0, 559, 316, 133, 32767, 202, 32767,
+ 305, 0, 32767, -94, 32767, 0, 32767, -222,
+ 32767, 138, 32767, -52, 32767, 32767, 279, 69,
+ -136, 0, 32767, 32767, 189, 32767, 32767, 88,
+ 0, 32767, 32767, 274, 32767, 514, 769, 248,
+ 32767, 32767, 32767, 32767, 32767, 32767, 0, 81,
+ 8, -29, 32767, 32767, 32767, -174, 258, 0,
+ 465, 211, 32767, 0, -229, 32767, -191, 32767,
+ 1263, 48, 32767, 343, 0, 58, 0, 32767,
+ 32767, 855, 0, 415, 0, -217, 32767, 1195,
+ 32767, 32767, 166, 32767, 42, 262, -736, 0,
+ 32767, 32767, 418, 178, 122, 32767, 46, 32767,
+ 32767, 32767, 229, 443, 32767, 32767, 250, 32767,
+ -300, 0, 32767, 1153, 32767, 108, 32767, -462,
+ 266, 32767, 478, -220, 235, 32767, 32767, -127,
+ 32767, 32767, 32767, 427, -231, 156, 32767, 0,
+ 0, 148, -218, 142, 73, 420, 32767, 32767,
+ 523, 32767, -36, 32767, 32767, 467, 844, -415,
+ 32767, 32767, -148, 179, 361, 32767, 151, 0,
+ 0, 32767, 145, 32767, 248, 110, 29, 125,
+ 282, 32767, -36, 43, 32767, 1125, 32767, 530,
+ 251, 519, 191, 0, 32767, -34, -502, 313,
+ 462, 845, 32767, 32767, -255, 412, 32767, 78,
+ 0, 32767, 444, 161, 0, 32767, 308, 32767,
+ -273, 400, 32767, 296, 32767, 32767, 72, 32767,
+ 32767, 34, 32767, 364, 151, -63, 4, 229,
+ 0, -276, 32767, 32767, 32767, 32767, -406, 32767,
+ 203, 32767, 140, 187, 160, 32767, 286, 0,
+ 32767, 32767, -88, 0, 100, -361, 32767, 9,
+ 0, -456, 32767, -37, -404, 32767, -969, 32767,
+ 371, 95, 0, 703, -31, 263, 373, -745,
+ 507, 14, 32767, -159, 0, 32767, 47, 299,
+ -126, 0, 32767, 83, 32767, 32767, 420, 236,
+ 32767, 32767, 0, 310, 89, 233, 32767, 93,
+ 32767, 0, 816, 60, 301, 211, 193, 0,
+ 452, -107, -403, -242, 353, 18, 32767, 32767,
+ 32767, 243, 104, 32767, 32767, 32767, -305, 32767,
+ -1048, 54, 0, 383, 32767, 32767, 32767, 226,
+ 319, 0, 32767, 32767, 32767, -130, 537, 32767,
+ 0, -206, 240, 696, 121, 32767, 180, 164,
+ 32767, 390, 185, 32767, 220, 545, 29, 32767,
+ 0, 32767, 32767, 1120, -163, 32767, 32767, 32767,
+ -368, 136, 445, 171, 233, 32767, 73, 32767,
+ 92, 32767, 0, 32767, 0, 208, 354, 32767,
+ 54, 32767, 32767, -246, -93, 389, 32767, 32767,
+ 32767, 32767, 50, 32767, 32767, 308, 32767, -278,
+ 0, 32767, 32767, -1172, 32767, 8, 32767, 0,
+ 32767, 341, 304, 242, -174, -92, 76, 419,
+ 32767, 87, 32767, -262, 32767, 32767, 32767, 109,
+ 200, 0, 32767, 0, 85, 530, 32767, -316,
+ 32767, 0, -286, 32767, 193, 268, 32767, 32767,
+ 278, 32767, 32767, 155, 445, 95, -310, 32767,
+ 207, -56, 32767, 32767, 0, -127, 232, -283,
+ 103, 32767, 1, 0, 32767, 32767, -485, 350,
+ 79, -56, -354, 32767, 121, 24, 81, 20,
+ 325, 40, 248, 32767, 32767, 32767, 358, 32767,
+ -56, 32767, 0, 174, -28, -301, -92, 32767,
+ 114, 295, 32767, 363, -355, 32767, 290, 0,
+ 32767, 32767, 32767, 122, 55, -142, 32767, 50,
+ 32767, 32767, 152, 571, 1397, 0, 472, -448,
+ 185, 140, 228, 435, 0, 32767, 32767, 414,
+ 32767, 379, 92, 185, 23, 299, 32767, 32767,
+ 0, 32767, 32767, 32767, 306, 439, -198, 219,
+ 340, 32767, 416, 0, -123, 377, 32767, 32767,
+ 0, 32767, 670, -670, 339, 32767, 32767, 32767,
+ 0, -256, 70, 514, 331, 0, 302, 469,
+ 0, 370, 32767, 32767, 42, 255, 212, 0,
+ 322, 277, 32767, -163, 32767, 216, 32767, 32767,
+ 0, 32767, 190, 32767, 32767, 0, 32767, 0,
+ -409, 1366, 32767, 32767, 32767, 193, 32767, 325,
+ 32767, 0, 142, 466, 32767, 32767, 32767, 113,
+ 32767, 32767, 62, 0, -62, 113, -90, 34,
+ -256, 32767, 32767, -936, 32767, 32767, 32767, 0,
+ -64, 0, -34, 451, 290, 108, 32767, 276,
+ 842, 0, 556, -153, 32767, 412, -168, 32767,
+ 32767, 1331, 407, 234, -60, 115, 457, -73,
+ 502, 772, 32767, 33, 404, -925, 32767, 32767,
+ 421, -123, 32767, 32767, 32767, 0, 0, 32767,
+ 32767, 32767, 429, 0, 3, 769, -81, 306,
+ 64, 32767, 192, 96, 0, 63, 44, 32767,
+ 32767, 32767, 32767, 0, 284, 32767, 575, 32767,
+ 32767, 12, 32767, 516, 116, 32767, 32767, 150,
+ 442, 134, 32767, 198, -45, 249, 40, 373,
+ 32767, 0, 32767, 32767, 0, 0, 352, 32767,
+ 117, 32767, 426, 0, 0, 32767, 32767, 32767,
+ 32767, -92, 32767, -442, 32767, 269, 32767, 32767,
+ 32767, 429, 32767, 0, 32767, 0, 143, 32767,
+ 508, -66, 32767, 280, 32767, 39, 162, 32767,
+ 32767, 0, 32767, 31, 32767, 32767, 32767, 0,
+ 32767, 257, -90, -249, 224, 272, 32767, 32767,
+ 313, -467, 214, 0, -85, 32767, 48, 0,
+ 32767, -336, 202, 0, 447, 90, 264, 32767,
+ 32767, 0, 101, 32767, 32767, 32767, 0, 32767,
+ 32767, 227, -1093, 32767, 0, 32767, 27, 174,
+ 32767, 7, 32767, -621, 146, 32767, 32767, 32767,
+ 854, 0, 32767, 161, 0, 137, 32767, 32767,
+ 32767, 32767, 0, 391, 219, 276, 32767, 168,
+ 32767, 32767, 0, 32767, 32767, 32767, 1, -4,
+ 32767, 0, 293, 0, 374, 256, 0, 0,
+ 32767, 355, 212, 404, 0, 186, 32767, 0,
+ 359, 32767, 32767, 172, 32767, 32767, -131, 0,
+ 402, 0, 56, 32767, 462, 389, 82, 0,
+ 32767, 0, 32767, 0, 32767, 32767, 32767, 32767,
+ 106, 425, -160, 31, 32767, 55, 0, 0,
+ 32767, 32767, 430, 1224, 179, -179, 0, 397,
+ 32767, 0, 0, 0, -60, 47, 32767, 396,
+ 32767, 326, 383, 369, 32767, 368, 32767
+ };
+
+ const unsigned char *k = (const unsigned char *) key;
+ uint32 a = 0;
+ uint32 b = 0;
+
+ while (keylen--)
+ {
+ unsigned char c = *k++ | 0x20;
+
+ a = a * 257 + c;
+ b = b * 31 + c;
+ }
+ return h[a % 943] + h[b % 943];
+}
+
+const ScanKeywordList ScanKeywords = {
+ ScanKeywords_kw_string,
+ ScanKeywords_kw_offsets,
+ ScanKeywords_hash_func,
+ SCANKEYWORDS_NUM_KEYWORDS,
+ 17
+};
+
+#endif /* KWLIST_D_H */
diff --git a/contrib/libs/libpq/src/common/kwlookup.c b/contrib/libs/libpq/src/common/kwlookup.c
new file mode 100644
index 0000000000..7e49825c7b
--- /dev/null
+++ b/contrib/libs/libpq/src/common/kwlookup.c
@@ -0,0 +1,85 @@
+/*-------------------------------------------------------------------------
+ *
+ * kwlookup.c
+ * Key word lookup for PostgreSQL
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/common/kwlookup.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "c.h"
+
+#include "common/kwlookup.h"
+
+
+/*
+ * ScanKeywordLookup - see if a given word is a keyword
+ *
+ * The list of keywords to be matched against is passed as a ScanKeywordList.
+ *
+ * Returns the keyword number (0..N-1) of the keyword, or -1 if no match.
+ * Callers typically use the keyword number to index into information
+ * arrays, but that is no concern of this code.
+ *
+ * The match is done case-insensitively. Note that we deliberately use a
+ * dumbed-down case conversion that will only translate 'A'-'Z' into 'a'-'z',
+ * even if we are in a locale where tolower() would produce more or different
+ * translations. This is to conform to the SQL99 spec, which says that
+ * keywords are to be matched in this way even though non-keyword identifiers
+ * receive a different case-normalization mapping.
+ */
+int
+ScanKeywordLookup(const char *str,
+ const ScanKeywordList *keywords)
+{
+ size_t len;
+ int h;
+ const char *kw;
+
+ /*
+ * Reject immediately if too long to be any keyword. This saves useless
+ * hashing and downcasing work on long strings.
+ */
+ len = strlen(str);
+ if (len > keywords->max_kw_len)
+ return -1;
+
+ /*
+ * Compute the hash function. We assume it was generated to produce
+ * case-insensitive results. Since it's a perfect hash, we need only
+ * match to the specific keyword it identifies.
+ */
+ h = keywords->hash(str, len);
+
+ /* An out-of-range result implies no match */
+ if (h < 0 || h >= keywords->num_keywords)
+ return -1;
+
+ /*
+ * Compare character-by-character to see if we have a match, applying an
+ * ASCII-only downcasing to the input characters. We must not use
+ * tolower() since it may produce the wrong translation in some locales
+ * (eg, Turkish).
+ */
+ kw = GetScanKeyword(h, keywords);
+ while (*str != '\0')
+ {
+ char ch = *str++;
+
+ if (ch >= 'A' && ch <= 'Z')
+ ch += 'a' - 'A';
+ if (ch != *kw++)
+ return -1;
+ }
+ if (*kw != '\0')
+ return -1;
+
+ /* Success! */
+ return h;
+}
diff --git a/contrib/libs/libpq/src/common/link-canary.c b/contrib/libs/libpq/src/common/link-canary.c
new file mode 100644
index 0000000000..f84331a9a4
--- /dev/null
+++ b/contrib/libs/libpq/src/common/link-canary.c
@@ -0,0 +1,36 @@
+/*-------------------------------------------------------------------------
+ * link-canary.c
+ * Detect whether src/common functions came from frontend or backend.
+ *
+ * Copyright (c) 2018-2023, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/common/link-canary.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "c.h"
+
+#include "common/link-canary.h"
+
+/*
+ * This function just reports whether this file was compiled for frontend
+ * or backend environment. We need this because in some systems, mainly
+ * ELF-based platforms, it is possible for a shlib (such as libpq) loaded
+ * into the backend to call a backend function named XYZ in preference to
+ * the shlib's own function XYZ. That's bad if the two functions don't
+ * act identically. This exact situation comes up for many functions in
+ * src/common and src/port, where the same function names exist in both
+ * libpq and the backend but they don't act quite identically. To verify
+ * that appropriate measures have been taken to prevent incorrect symbol
+ * resolution, libpq should test that this function returns true.
+ */
+bool
+pg_link_canary_is_frontend(void)
+{
+#ifdef FRONTEND
+ return true;
+#else
+ return false;
+#endif
+}
diff --git a/contrib/libs/libpq/src/common/logging.c b/contrib/libs/libpq/src/common/logging.c
new file mode 100644
index 0000000000..dab718b482
--- /dev/null
+++ b/contrib/libs/libpq/src/common/logging.c
@@ -0,0 +1,334 @@
+/*-------------------------------------------------------------------------
+ * Logging framework for frontend programs
+ *
+ * Copyright (c) 2018-2023, PostgreSQL Global Development Group
+ *
+ * src/common/logging.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+#error "This file is not expected to be compiled for backend code"
+#endif
+
+#include "postgres_fe.h"
+
+#include <unistd.h>
+
+#include "common/logging.h"
+
+enum pg_log_level __pg_log_level;
+
+static const char *progname;
+static int log_flags;
+
+static void (*log_pre_callback) (void);
+static void (*log_locus_callback) (const char **, uint64 *);
+
+static const char *sgr_error = NULL;
+static const char *sgr_warning = NULL;
+static const char *sgr_note = NULL;
+static const char *sgr_locus = NULL;
+
+#define SGR_ERROR_DEFAULT "01;31"
+#define SGR_WARNING_DEFAULT "01;35"
+#define SGR_NOTE_DEFAULT "01;36"
+#define SGR_LOCUS_DEFAULT "01"
+
+#define ANSI_ESCAPE_FMT "\x1b[%sm"
+#define ANSI_ESCAPE_RESET "\x1b[0m"
+
+#ifdef WIN32
+
+#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
+#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
+#endif
+
+/*
+ * Attempt to enable VT100 sequence processing for colorization on Windows.
+ * If current environment is not VT100-compatible or if this mode could not
+ * be enabled, return false.
+ */
+static bool
+enable_vt_processing(void)
+{
+ /* Check stderr */
+ HANDLE hOut = GetStdHandle(STD_ERROR_HANDLE);
+ DWORD dwMode = 0;
+
+ if (hOut == INVALID_HANDLE_VALUE)
+ return false;
+
+ /*
+ * Look for the current console settings and check if VT100 is already
+ * enabled.
+ */
+ if (!GetConsoleMode(hOut, &dwMode))
+ return false;
+ if ((dwMode & ENABLE_VIRTUAL_TERMINAL_PROCESSING) != 0)
+ return true;
+
+ dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
+ if (!SetConsoleMode(hOut, dwMode))
+ return false;
+ return true;
+}
+#endif /* WIN32 */
+
+/*
+ * This should be called before any output happens.
+ */
+void
+pg_logging_init(const char *argv0)
+{
+ const char *pg_color_env = getenv("PG_COLOR");
+ bool log_color = false;
+ bool color_terminal = isatty(fileno(stderr));
+
+#ifdef WIN32
+
+ /*
+ * On Windows, check if environment is VT100-compatible if using a
+ * terminal.
+ */
+ if (color_terminal)
+ color_terminal = enable_vt_processing();
+#endif
+
+ /* usually the default, but not on Windows */
+ setvbuf(stderr, NULL, _IONBF, 0);
+
+ progname = get_progname(argv0);
+ __pg_log_level = PG_LOG_INFO;
+
+ if (pg_color_env)
+ {
+ if (strcmp(pg_color_env, "always") == 0 ||
+ (strcmp(pg_color_env, "auto") == 0 && color_terminal))
+ log_color = true;
+ }
+
+ if (log_color)
+ {
+ const char *pg_colors_env = getenv("PG_COLORS");
+
+ if (pg_colors_env)
+ {
+ char *colors = strdup(pg_colors_env);
+
+ if (colors)
+ {
+ for (char *token = strtok(colors, ":"); token; token = strtok(NULL, ":"))
+ {
+ char *e = strchr(token, '=');
+
+ if (e)
+ {
+ char *name;
+ char *value;
+
+ *e = '\0';
+ name = token;
+ value = e + 1;
+
+ if (strcmp(name, "error") == 0)
+ sgr_error = strdup(value);
+ if (strcmp(name, "warning") == 0)
+ sgr_warning = strdup(value);
+ if (strcmp(name, "note") == 0)
+ sgr_note = strdup(value);
+ if (strcmp(name, "locus") == 0)
+ sgr_locus = strdup(value);
+ }
+ }
+
+ free(colors);
+ }
+ }
+ else
+ {
+ sgr_error = SGR_ERROR_DEFAULT;
+ sgr_warning = SGR_WARNING_DEFAULT;
+ sgr_note = SGR_NOTE_DEFAULT;
+ sgr_locus = SGR_LOCUS_DEFAULT;
+ }
+ }
+}
+
+/*
+ * Change the logging flags.
+ */
+void
+pg_logging_config(int new_flags)
+{
+ log_flags = new_flags;
+}
+
+/*
+ * pg_logging_init sets the default log level to INFO. Programs that prefer
+ * a different default should use this to set it, immediately afterward.
+ */
+void
+pg_logging_set_level(enum pg_log_level new_level)
+{
+ __pg_log_level = new_level;
+}
+
+/*
+ * Command line switches such as --verbose should invoke this.
+ */
+void
+pg_logging_increase_verbosity(void)
+{
+ /*
+ * The enum values are chosen such that we have to decrease __pg_log_level
+ * in order to become more verbose.
+ */
+ if (__pg_log_level > PG_LOG_NOTSET + 1)
+ __pg_log_level--;
+}
+
+void
+pg_logging_set_pre_callback(void (*cb) (void))
+{
+ log_pre_callback = cb;
+}
+
+void
+pg_logging_set_locus_callback(void (*cb) (const char **filename, uint64 *lineno))
+{
+ log_locus_callback = cb;
+}
+
+void
+pg_log_generic(enum pg_log_level level, enum pg_log_part part,
+ const char *pg_restrict fmt,...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ pg_log_generic_v(level, part, fmt, ap);
+ va_end(ap);
+}
+
+void
+pg_log_generic_v(enum pg_log_level level, enum pg_log_part part,
+ const char *pg_restrict fmt, va_list ap)
+{
+ int save_errno = errno;
+ const char *filename = NULL;
+ uint64 lineno = 0;
+ va_list ap2;
+ size_t required_len;
+ char *buf;
+
+ Assert(progname);
+ Assert(level);
+ Assert(fmt);
+ Assert(fmt[strlen(fmt) - 1] != '\n');
+
+ /* Do nothing if log level is too low. */
+ if (level < __pg_log_level)
+ return;
+
+ /*
+ * Flush stdout before output to stderr, to ensure sync even when stdout
+ * is buffered.
+ */
+ fflush(stdout);
+
+ if (log_pre_callback)
+ log_pre_callback();
+
+ if (log_locus_callback)
+ log_locus_callback(&filename, &lineno);
+
+ fmt = _(fmt);
+
+ if (!(log_flags & PG_LOG_FLAG_TERSE) || filename)
+ {
+ if (sgr_locus)
+ fprintf(stderr, ANSI_ESCAPE_FMT, sgr_locus);
+ if (!(log_flags & PG_LOG_FLAG_TERSE))
+ fprintf(stderr, "%s:", progname);
+ if (filename)
+ {
+ fprintf(stderr, "%s:", filename);
+ if (lineno > 0)
+ fprintf(stderr, UINT64_FORMAT ":", lineno);
+ }
+ fprintf(stderr, " ");
+ if (sgr_locus)
+ fprintf(stderr, ANSI_ESCAPE_RESET);
+ }
+
+ if (!(log_flags & PG_LOG_FLAG_TERSE))
+ {
+ switch (part)
+ {
+ case PG_LOG_PRIMARY:
+ switch (level)
+ {
+ case PG_LOG_ERROR:
+ if (sgr_error)
+ fprintf(stderr, ANSI_ESCAPE_FMT, sgr_error);
+ fprintf(stderr, _("error: "));
+ if (sgr_error)
+ fprintf(stderr, ANSI_ESCAPE_RESET);
+ break;
+ case PG_LOG_WARNING:
+ if (sgr_warning)
+ fprintf(stderr, ANSI_ESCAPE_FMT, sgr_warning);
+ fprintf(stderr, _("warning: "));
+ if (sgr_warning)
+ fprintf(stderr, ANSI_ESCAPE_RESET);
+ break;
+ default:
+ break;
+ }
+ break;
+ case PG_LOG_DETAIL:
+ if (sgr_note)
+ fprintf(stderr, ANSI_ESCAPE_FMT, sgr_note);
+ fprintf(stderr, _("detail: "));
+ if (sgr_note)
+ fprintf(stderr, ANSI_ESCAPE_RESET);
+ break;
+ case PG_LOG_HINT:
+ if (sgr_note)
+ fprintf(stderr, ANSI_ESCAPE_FMT, sgr_note);
+ fprintf(stderr, _("hint: "));
+ if (sgr_note)
+ fprintf(stderr, ANSI_ESCAPE_RESET);
+ break;
+ }
+ }
+
+ errno = save_errno;
+
+ va_copy(ap2, ap);
+ required_len = vsnprintf(NULL, 0, fmt, ap2) + 1;
+ va_end(ap2);
+
+ buf = pg_malloc_extended(required_len, MCXT_ALLOC_NO_OOM);
+
+ errno = save_errno; /* malloc might change errno */
+
+ if (!buf)
+ {
+ /* memory trouble, just print what we can and get out of here */
+ vfprintf(stderr, fmt, ap);
+ return;
+ }
+
+ vsnprintf(buf, required_len, fmt, ap);
+
+ /* strip one newline, for PQerrorMessage() */
+ if (required_len >= 2 && buf[required_len - 2] == '\n')
+ buf[required_len - 2] = '\0';
+
+ fprintf(stderr, "%s\n", buf);
+
+ free(buf);
+}
diff --git a/contrib/libs/libpq/src/common/md5_common.c b/contrib/libs/libpq/src/common/md5_common.c
new file mode 100644
index 0000000000..82ce75dcf2
--- /dev/null
+++ b/contrib/libs/libpq/src/common/md5_common.c
@@ -0,0 +1,172 @@
+/*-------------------------------------------------------------------------
+ *
+ * md5_common.c
+ * Routines shared between all MD5 implementations used for encrypted
+ * passwords.
+ *
+ * Sverre H. Huseby <sverrehu@online.no>
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/common/md5_common.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#include "common/cryptohash.h"
+#include "common/md5.h"
+
+static void
+bytesToHex(uint8 b[16], char *s)
+{
+ static const char *hex = "0123456789abcdef";
+ int q,
+ w;
+
+ for (q = 0, w = 0; q < 16; q++)
+ {
+ s[w++] = hex[(b[q] >> 4) & 0x0F];
+ s[w++] = hex[b[q] & 0x0F];
+ }
+ s[w] = '\0';
+}
+
+/*
+ * pg_md5_hash
+ *
+ * Calculates the MD5 sum of the bytes in a buffer.
+ *
+ * SYNOPSIS #include "md5.h"
+ * int pg_md5_hash(const void *buff, size_t len, char *hexsum)
+ *
+ * INPUT buff the buffer containing the bytes that you want
+ * the MD5 sum of.
+ * len number of bytes in the buffer.
+ *
+ * OUTPUT hexsum the MD5 sum as a '\0'-terminated string of
+ * hexadecimal digits. an MD5 sum is 16 bytes long.
+ * each byte is represented by two hexadecimal
+ * characters. you thus need to provide an array
+ * of 33 characters, including the trailing '\0'.
+ *
+ * errstr filled with a constant-string error message
+ * on failure return; NULL on success.
+ *
+ * RETURNS false on failure (out of memory for internal buffers
+ * or MD5 computation failure) or true on success.
+ *
+ * STANDARDS MD5 is described in RFC 1321.
+ *
+ * AUTHOR Sverre H. Huseby <sverrehu@online.no>
+ *
+ */
+
+bool
+pg_md5_hash(const void *buff, size_t len, char *hexsum, const char **errstr)
+{
+ uint8 sum[MD5_DIGEST_LENGTH];
+ pg_cryptohash_ctx *ctx;
+
+ *errstr = NULL;
+ ctx = pg_cryptohash_create(PG_MD5);
+ if (ctx == NULL)
+ {
+ *errstr = pg_cryptohash_error(NULL); /* returns OOM */
+ return false;
+ }
+
+ if (pg_cryptohash_init(ctx) < 0 ||
+ pg_cryptohash_update(ctx, buff, len) < 0 ||
+ pg_cryptohash_final(ctx, sum, sizeof(sum)) < 0)
+ {
+ *errstr = pg_cryptohash_error(ctx);
+ pg_cryptohash_free(ctx);
+ return false;
+ }
+
+ bytesToHex(sum, hexsum);
+ pg_cryptohash_free(ctx);
+ return true;
+}
+
+/*
+ * pg_md5_binary
+ *
+ * As above, except that the MD5 digest is returned as a binary string
+ * (of size MD5_DIGEST_LENGTH) rather than being converted to ASCII hex.
+ */
+bool
+pg_md5_binary(const void *buff, size_t len, void *outbuf, const char **errstr)
+{
+ pg_cryptohash_ctx *ctx;
+
+ *errstr = NULL;
+ ctx = pg_cryptohash_create(PG_MD5);
+ if (ctx == NULL)
+ {
+ *errstr = pg_cryptohash_error(NULL); /* returns OOM */
+ return false;
+ }
+
+ if (pg_cryptohash_init(ctx) < 0 ||
+ pg_cryptohash_update(ctx, buff, len) < 0 ||
+ pg_cryptohash_final(ctx, outbuf, MD5_DIGEST_LENGTH) < 0)
+ {
+ *errstr = pg_cryptohash_error(ctx);
+ pg_cryptohash_free(ctx);
+ return false;
+ }
+
+ pg_cryptohash_free(ctx);
+ return true;
+}
+
+
+/*
+ * Computes MD5 checksum of "passwd" (a null-terminated string) followed
+ * by "salt" (which need not be null-terminated).
+ *
+ * Output format is "md5" followed by a 32-hex-digit MD5 checksum.
+ * Hence, the output buffer "buf" must be at least 36 bytes long.
+ *
+ * Returns true if okay, false on error with *errstr providing some
+ * error context.
+ */
+bool
+pg_md5_encrypt(const char *passwd, const char *salt, size_t salt_len,
+ char *buf, const char **errstr)
+{
+ size_t passwd_len = strlen(passwd);
+
+ /* +1 here is just to avoid risk of unportable malloc(0) */
+ char *crypt_buf = malloc(passwd_len + salt_len + 1);
+ bool ret;
+
+ if (!crypt_buf)
+ {
+ *errstr = _("out of memory");
+ return false;
+ }
+
+ /*
+ * Place salt at the end because it may be known by users trying to crack
+ * the MD5 output.
+ */
+ memcpy(crypt_buf, passwd, passwd_len);
+ memcpy(crypt_buf + passwd_len, salt, salt_len);
+
+ strcpy(buf, "md5");
+ ret = pg_md5_hash(crypt_buf, passwd_len + salt_len, buf + 3, errstr);
+
+ free(crypt_buf);
+
+ return ret;
+}
diff --git a/contrib/libs/libpq/src/common/percentrepl.c b/contrib/libs/libpq/src/common/percentrepl.c
new file mode 100644
index 0000000000..7aa85fdc94
--- /dev/null
+++ b/contrib/libs/libpq/src/common/percentrepl.c
@@ -0,0 +1,137 @@
+/*-------------------------------------------------------------------------
+ *
+ * percentrepl.c
+ * Common routines to replace percent placeholders in strings
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/common/percentrepl.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#include "common/logging.h"
+#endif
+
+#include "common/percentrepl.h"
+#include "lib/stringinfo.h"
+
+/*
+ * replace_percent_placeholders
+ *
+ * Replace percent-letter placeholders in input string with the supplied
+ * values. For example, to replace %f with foo and %b with bar, call
+ *
+ * replace_percent_placeholders(instr, "param_name", "bf", bar, foo);
+ *
+ * The return value is palloc'd.
+ *
+ * "%%" is replaced by a single "%".
+ *
+ * This throws an error for an unsupported placeholder or a "%" at the end of
+ * the input string.
+ *
+ * A value may be NULL. If the corresponding placeholder is found in the
+ * input string, it will be treated as if an unsupported placeholder was used.
+ * This allows callers to share a "letters" specification but vary the
+ * actually supported placeholders at run time.
+ *
+ * This functions is meant for cases where all the values are readily
+ * available or cheap to compute and most invocations will use most values
+ * (for example for archive_command). Also, it requires that all values are
+ * strings. It won't be a good match for things like log prefixes or prompts
+ * that use a mix of data types and any invocation will only use a few of the
+ * possible values.
+ *
+ * param_name is the name of the underlying GUC parameter, for error
+ * reporting. At the moment, this function is only used for GUC parameters.
+ * If other kinds of uses were added, the error reporting would need to be
+ * revised.
+ */
+char *
+replace_percent_placeholders(const char *instr, const char *param_name, const char *letters,...)
+{
+ StringInfoData result;
+
+ initStringInfo(&result);
+
+ for (const char *sp = instr; *sp; sp++)
+ {
+ if (*sp == '%')
+ {
+ if (sp[1] == '%')
+ {
+ /* Convert %% to a single % */
+ sp++;
+ appendStringInfoChar(&result, *sp);
+ }
+ else if (sp[1] == '\0')
+ {
+ /* Incomplete escape sequence, expected a character afterward */
+#ifdef FRONTEND
+ pg_log_error("invalid value for parameter \"%s\": \"%s\"", param_name, instr);
+ pg_log_error_detail("String ends unexpectedly after escape character \"%%\".");
+ exit(1);
+#else
+ ereport(ERROR,
+ errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("invalid value for parameter \"%s\": \"%s\"", param_name, instr),
+ errdetail("String ends unexpectedly after escape character \"%%\"."));
+#endif
+ }
+ else
+ {
+ /* Look up placeholder character */
+ bool found = false;
+ va_list ap;
+
+ sp++;
+
+ va_start(ap, letters);
+ for (const char *lp = letters; *lp; lp++)
+ {
+ char *val = va_arg(ap, char *);
+
+ if (*sp == *lp)
+ {
+ if (val)
+ {
+ appendStringInfoString(&result, val);
+ found = true;
+ }
+ /* If val is NULL, we will report an error. */
+ break;
+ }
+ }
+ va_end(ap);
+ if (!found)
+ {
+ /* Unknown placeholder */
+#ifdef FRONTEND
+ pg_log_error("invalid value for parameter \"%s\": \"%s\"", param_name, instr);
+ pg_log_error_detail("String contains unexpected placeholder \"%%%c\".", *sp);
+ exit(1);
+#else
+ ereport(ERROR,
+ errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("invalid value for parameter \"%s\": \"%s\"", param_name, instr),
+ errdetail("String contains unexpected placeholder \"%%%c\".", *sp));
+#endif
+ }
+ }
+ }
+ else
+ {
+ appendStringInfoChar(&result, *sp);
+ }
+ }
+
+ return result.data;
+}
diff --git a/contrib/libs/libpq/src/common/pg_get_line.c b/contrib/libs/libpq/src/common/pg_get_line.c
new file mode 100644
index 0000000000..3cdf0908d2
--- /dev/null
+++ b/contrib/libs/libpq/src/common/pg_get_line.c
@@ -0,0 +1,180 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_get_line.c
+ * fgets() with an expansible result buffer
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/common/pg_get_line.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#include <setjmp.h>
+
+#include "common/string.h"
+#include "lib/stringinfo.h"
+
+
+/*
+ * pg_get_line()
+ *
+ * This is meant to be equivalent to fgets(), except that instead of
+ * reading into a caller-supplied, fixed-size buffer, it reads into
+ * a palloc'd (in frontend, really malloc'd) string, which is resized
+ * as needed to handle indefinitely long input lines. The caller is
+ * responsible for pfree'ing the result string when appropriate.
+ *
+ * As with fgets(), returns NULL if there is a read error or if no
+ * characters are available before EOF. The caller can distinguish
+ * these cases by checking ferror(stream).
+ *
+ * Since this is meant to be equivalent to fgets(), the trailing newline
+ * (if any) is not stripped. Callers may wish to apply pg_strip_crlf().
+ *
+ * Note that while I/O errors are reflected back to the caller to be
+ * dealt with, an OOM condition for the palloc'd buffer will not be;
+ * there'll be an ereport(ERROR) or exit(1) inside stringinfo.c.
+ *
+ * Also note that the palloc'd buffer is usually a lot longer than
+ * strictly necessary, so it may be inadvisable to use this function
+ * to collect lots of long-lived data. A less memory-hungry option
+ * is to use pg_get_line_buf() or pg_get_line_append() in a loop,
+ * then pstrdup() each line.
+ *
+ * prompt_ctx can optionally be provided to allow this function to be
+ * canceled via an existing SIGINT signal handler that will longjmp to the
+ * specified place only when *(prompt_ctx->enabled) is true. If canceled,
+ * this function returns NULL, and prompt_ctx->canceled is set to true.
+ */
+char *
+pg_get_line(FILE *stream, PromptInterruptContext *prompt_ctx)
+{
+ StringInfoData buf;
+
+ initStringInfo(&buf);
+
+ if (!pg_get_line_append(stream, &buf, prompt_ctx))
+ {
+ /* ensure that free() doesn't mess up errno */
+ int save_errno = errno;
+
+ pfree(buf.data);
+ errno = save_errno;
+ return NULL;
+ }
+
+ return buf.data;
+}
+
+/*
+ * pg_get_line_buf()
+ *
+ * This has similar behavior to pg_get_line(), and thence to fgets(),
+ * except that the collected data is returned in a caller-supplied
+ * StringInfo buffer. This is a convenient API for code that just
+ * wants to read and process one line at a time, without any artificial
+ * limit on line length.
+ *
+ * Returns true if a line was successfully collected (including the
+ * case of a non-newline-terminated line at EOF). Returns false if
+ * there was an I/O error or no data was available before EOF.
+ * (Check ferror(stream) to distinguish these cases.)
+ *
+ * In the false-result case, buf is reset to empty.
+ */
+bool
+pg_get_line_buf(FILE *stream, StringInfo buf)
+{
+ /* We just need to drop any data from the previous call */
+ resetStringInfo(buf);
+ return pg_get_line_append(stream, buf, NULL);
+}
+
+/*
+ * pg_get_line_append()
+ *
+ * This has similar behavior to pg_get_line(), and thence to fgets(),
+ * except that the collected data is appended to whatever is in *buf.
+ * This is useful in preference to pg_get_line_buf() if the caller wants
+ * to merge some lines together, e.g. to implement backslash continuation.
+ *
+ * Returns true if a line was successfully collected (including the
+ * case of a non-newline-terminated line at EOF). Returns false if
+ * there was an I/O error or no data was available before EOF.
+ * (Check ferror(stream) to distinguish these cases.)
+ *
+ * In the false-result case, the contents of *buf are logically unmodified,
+ * though it's possible that the buffer has been resized.
+ *
+ * prompt_ctx can optionally be provided to allow this function to be
+ * canceled via an existing SIGINT signal handler that will longjmp to the
+ * specified place only when *(prompt_ctx->enabled) is true. If canceled,
+ * this function returns false, and prompt_ctx->canceled is set to true.
+ */
+bool
+pg_get_line_append(FILE *stream, StringInfo buf,
+ PromptInterruptContext *prompt_ctx)
+{
+ int orig_len = buf->len;
+
+ if (prompt_ctx && sigsetjmp(*((sigjmp_buf *) prompt_ctx->jmpbuf), 1) != 0)
+ {
+ /* Got here with longjmp */
+ prompt_ctx->canceled = true;
+ /* Discard any data we collected before detecting error */
+ buf->len = orig_len;
+ buf->data[orig_len] = '\0';
+ return false;
+ }
+
+ /* Loop until newline or EOF/error */
+ for (;;)
+ {
+ char *res;
+
+ /* Enable longjmp while waiting for input */
+ if (prompt_ctx)
+ *(prompt_ctx->enabled) = true;
+
+ /* Read some data, appending it to whatever we already have */
+ res = fgets(buf->data + buf->len, buf->maxlen - buf->len, stream);
+
+ /* Disable longjmp again, then break if fgets failed */
+ if (prompt_ctx)
+ *(prompt_ctx->enabled) = false;
+
+ if (res == NULL)
+ break;
+
+ /* Got data, so update buf->len */
+ buf->len += strlen(buf->data + buf->len);
+
+ /* Done if we have collected a newline */
+ if (buf->len > orig_len && buf->data[buf->len - 1] == '\n')
+ return true;
+
+ /* Make some more room in the buffer, and loop to read more data */
+ enlargeStringInfo(buf, 128);
+ }
+
+ /* Check for I/O errors and EOF */
+ if (ferror(stream) || buf->len == orig_len)
+ {
+ /* Discard any data we collected before detecting error */
+ buf->len = orig_len;
+ buf->data[orig_len] = '\0';
+ return false;
+ }
+
+ /* No newline at EOF, but we did collect some data */
+ return true;
+}
diff --git a/contrib/libs/libpq/src/common/pg_lzcompress.c b/contrib/libs/libpq/src/common/pg_lzcompress.c
new file mode 100644
index 0000000000..95ad3388ef
--- /dev/null
+++ b/contrib/libs/libpq/src/common/pg_lzcompress.c
@@ -0,0 +1,876 @@
+/* ----------
+ * pg_lzcompress.c -
+ *
+ * This is an implementation of LZ compression for PostgreSQL.
+ * It uses a simple history table and generates 2-3 byte tags
+ * capable of backward copy information for 3-273 bytes with
+ * a max offset of 4095.
+ *
+ * Entry routines:
+ *
+ * int32
+ * pglz_compress(const char *source, int32 slen, char *dest,
+ * const PGLZ_Strategy *strategy);
+ *
+ * source is the input data to be compressed.
+ *
+ * slen is the length of the input data.
+ *
+ * dest is the output area for the compressed result.
+ * It must be at least as big as PGLZ_MAX_OUTPUT(slen).
+ *
+ * strategy is a pointer to some information controlling
+ * the compression algorithm. If NULL, the compiled
+ * in default strategy is used.
+ *
+ * The return value is the number of bytes written in the
+ * buffer dest, or -1 if compression fails; in the latter
+ * case the contents of dest are undefined.
+ *
+ * int32
+ * pglz_decompress(const char *source, int32 slen, char *dest,
+ * int32 rawsize, bool check_complete)
+ *
+ * source is the compressed input.
+ *
+ * slen is the length of the compressed input.
+ *
+ * dest is the area where the uncompressed data will be
+ * written to. It is the callers responsibility to
+ * provide enough space.
+ *
+ * The data is written to buff exactly as it was handed
+ * to pglz_compress(). No terminating zero byte is added.
+ *
+ * rawsize is the length of the uncompressed data.
+ *
+ * check_complete is a flag to let us know if -1 should be
+ * returned in cases where we don't reach the end of the
+ * source or dest buffers, or not. This should be false
+ * if the caller is asking for only a partial result and
+ * true otherwise.
+ *
+ * The return value is the number of bytes written in the
+ * buffer dest, or -1 if decompression fails.
+ *
+ * The decompression algorithm and internal data format:
+ *
+ * It is made with the compressed data itself.
+ *
+ * The data representation is easiest explained by describing
+ * the process of decompression.
+ *
+ * If compressed_size == rawsize, then the data
+ * is stored uncompressed as plain bytes. Thus, the decompressor
+ * simply copies rawsize bytes to the destination.
+ *
+ * Otherwise the first byte tells what to do the next 8 times.
+ * We call this the control byte.
+ *
+ * An unset bit in the control byte means, that one uncompressed
+ * byte follows, which is copied from input to output.
+ *
+ * A set bit in the control byte means, that a tag of 2-3 bytes
+ * follows. A tag contains information to copy some bytes, that
+ * are already in the output buffer, to the current location in
+ * the output. Let's call the three tag bytes T1, T2 and T3. The
+ * position of the data to copy is coded as an offset from the
+ * actual output position.
+ *
+ * The offset is in the upper nibble of T1 and in T2.
+ * The length is in the lower nibble of T1.
+ *
+ * So the 16 bits of a 2 byte tag are coded as
+ *
+ * 7---T1--0 7---T2--0
+ * OOOO LLLL OOOO OOOO
+ *
+ * This limits the offset to 1-4095 (12 bits) and the length
+ * to 3-18 (4 bits) because 3 is always added to it. To emit
+ * a tag of 2 bytes with a length of 2 only saves one control
+ * bit. But we lose one byte in the possible length of a tag.
+ *
+ * In the actual implementation, the 2 byte tag's length is
+ * limited to 3-17, because the value 0xF in the length nibble
+ * has special meaning. It means, that the next following
+ * byte (T3) has to be added to the length value of 18. That
+ * makes total limits of 1-4095 for offset and 3-273 for length.
+ *
+ * Now that we have successfully decoded a tag. We simply copy
+ * the output that occurred <offset> bytes back to the current
+ * output location in the specified <length>. Thus, a
+ * sequence of 200 spaces (think about bpchar fields) could be
+ * coded in 4 bytes. One literal space and a three byte tag to
+ * copy 199 bytes with a -1 offset. Whow - that's a compression
+ * rate of 98%! Well, the implementation needs to save the
+ * original data size too, so we need another 4 bytes for it
+ * and end up with a total compression rate of 96%, what's still
+ * worth a Whow.
+ *
+ * The compression algorithm
+ *
+ * The following uses numbers used in the default strategy.
+ *
+ * The compressor works best for attributes of a size between
+ * 1K and 1M. For smaller items there's not that much chance of
+ * redundancy in the character sequence (except for large areas
+ * of identical bytes like trailing spaces) and for bigger ones
+ * our 4K maximum look-back distance is too small.
+ *
+ * The compressor creates a table for lists of positions.
+ * For each input position (except the last 3), a hash key is
+ * built from the 4 next input bytes and the position remembered
+ * in the appropriate list. Thus, the table points to linked
+ * lists of likely to be at least in the first 4 characters
+ * matching strings. This is done on the fly while the input
+ * is compressed into the output area. Table entries are only
+ * kept for the last 4096 input positions, since we cannot use
+ * back-pointers larger than that anyway. The size of the hash
+ * table is chosen based on the size of the input - a larger table
+ * has a larger startup cost, as it needs to be initialized to
+ * zero, but reduces the number of hash collisions on long inputs.
+ *
+ * For each byte in the input, its hash key (built from this
+ * byte and the next 3) is used to find the appropriate list
+ * in the table. The lists remember the positions of all bytes
+ * that had the same hash key in the past in increasing backward
+ * offset order. Now for all entries in the used lists, the
+ * match length is computed by comparing the characters from the
+ * entries position with the characters from the actual input
+ * position.
+ *
+ * The compressor starts with a so called "good_match" of 128.
+ * It is a "prefer speed against compression ratio" optimizer.
+ * So if the first entry looked at already has 128 or more
+ * matching characters, the lookup stops and that position is
+ * used for the next tag in the output.
+ *
+ * For each subsequent entry in the history list, the "good_match"
+ * is lowered by 10%. So the compressor will be more happy with
+ * short matches the further it has to go back in the history.
+ * Another "speed against ratio" preference characteristic of
+ * the algorithm.
+ *
+ * Thus there are 3 stop conditions for the lookup of matches:
+ *
+ * - a match >= good_match is found
+ * - there are no more history entries to look at
+ * - the next history entry is already too far back
+ * to be coded into a tag.
+ *
+ * Finally the match algorithm checks that at least a match
+ * of 3 or more bytes has been found, because that is the smallest
+ * amount of copy information to code into a tag. If so, a tag
+ * is omitted and all the input bytes covered by that are just
+ * scanned for the history add's, otherwise a literal character
+ * is omitted and only his history entry added.
+ *
+ * Acknowledgments:
+ *
+ * Many thanks to Adisak Pochanayon, who's article about SLZ
+ * inspired me to write the PostgreSQL compression this way.
+ *
+ * Jan Wieck
+ *
+ * Copyright (c) 1999-2023, PostgreSQL Global Development Group
+ *
+ * src/common/pg_lzcompress.c
+ * ----------
+ */
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#include <limits.h>
+
+#include "common/pg_lzcompress.h"
+
+
+/* ----------
+ * Local definitions
+ * ----------
+ */
+#define PGLZ_MAX_HISTORY_LISTS 8192 /* must be power of 2 */
+#define PGLZ_HISTORY_SIZE 4096
+#define PGLZ_MAX_MATCH 273
+
+
+/* ----------
+ * PGLZ_HistEntry -
+ *
+ * Linked list for the backward history lookup
+ *
+ * All the entries sharing a hash key are linked in a doubly linked list.
+ * This makes it easy to remove an entry when it's time to recycle it
+ * (because it's more than 4K positions old).
+ * ----------
+ */
+typedef struct PGLZ_HistEntry
+{
+ struct PGLZ_HistEntry *next; /* links for my hash key's list */
+ struct PGLZ_HistEntry *prev;
+ int hindex; /* my current hash key */
+ const char *pos; /* my input position */
+} PGLZ_HistEntry;
+
+
+/* ----------
+ * The provided standard strategies
+ * ----------
+ */
+static const PGLZ_Strategy strategy_default_data = {
+ 32, /* Data chunks less than 32 bytes are not
+ * compressed */
+ INT_MAX, /* No upper limit on what we'll try to
+ * compress */
+ 25, /* Require 25% compression rate, or not worth
+ * it */
+ 1024, /* Give up if no compression in the first 1KB */
+ 128, /* Stop history lookup if a match of 128 bytes
+ * is found */
+ 10 /* Lower good match size by 10% at every loop
+ * iteration */
+};
+const PGLZ_Strategy *const PGLZ_strategy_default = &strategy_default_data;
+
+
+static const PGLZ_Strategy strategy_always_data = {
+ 0, /* Chunks of any size are compressed */
+ INT_MAX,
+ 0, /* It's enough to save one single byte */
+ INT_MAX, /* Never give up early */
+ 128, /* Stop history lookup if a match of 128 bytes
+ * is found */
+ 6 /* Look harder for a good match */
+};
+const PGLZ_Strategy *const PGLZ_strategy_always = &strategy_always_data;
+
+
+/* ----------
+ * Statically allocated work arrays for history
+ * ----------
+ */
+static int16 hist_start[PGLZ_MAX_HISTORY_LISTS];
+static PGLZ_HistEntry hist_entries[PGLZ_HISTORY_SIZE + 1];
+
+/*
+ * Element 0 in hist_entries is unused, and means 'invalid'. Likewise,
+ * INVALID_ENTRY_PTR in next/prev pointers mean 'invalid'.
+ */
+#define INVALID_ENTRY 0
+#define INVALID_ENTRY_PTR (&hist_entries[INVALID_ENTRY])
+
+/* ----------
+ * pglz_hist_idx -
+ *
+ * Computes the history table slot for the lookup by the next 4
+ * characters in the input.
+ *
+ * NB: because we use the next 4 characters, we are not guaranteed to
+ * find 3-character matches; they very possibly will be in the wrong
+ * hash list. This seems an acceptable tradeoff for spreading out the
+ * hash keys more.
+ * ----------
+ */
+#define pglz_hist_idx(_s,_e, _mask) ( \
+ ((((_e) - (_s)) < 4) ? (int) (_s)[0] : \
+ (((_s)[0] << 6) ^ ((_s)[1] << 4) ^ \
+ ((_s)[2] << 2) ^ (_s)[3])) & (_mask) \
+ )
+
+
+/* ----------
+ * pglz_hist_add -
+ *
+ * Adds a new entry to the history table.
+ *
+ * If _recycle is true, then we are recycling a previously used entry,
+ * and must first delink it from its old hashcode's linked list.
+ *
+ * NOTE: beware of multiple evaluations of macro's arguments, and note that
+ * _hn and _recycle are modified in the macro.
+ * ----------
+ */
+#define pglz_hist_add(_hs,_he,_hn,_recycle,_s,_e, _mask) \
+do { \
+ int __hindex = pglz_hist_idx((_s),(_e), (_mask)); \
+ int16 *__myhsp = &(_hs)[__hindex]; \
+ PGLZ_HistEntry *__myhe = &(_he)[_hn]; \
+ if (_recycle) { \
+ if (__myhe->prev == NULL) \
+ (_hs)[__myhe->hindex] = __myhe->next - (_he); \
+ else \
+ __myhe->prev->next = __myhe->next; \
+ if (__myhe->next != NULL) \
+ __myhe->next->prev = __myhe->prev; \
+ } \
+ __myhe->next = &(_he)[*__myhsp]; \
+ __myhe->prev = NULL; \
+ __myhe->hindex = __hindex; \
+ __myhe->pos = (_s); \
+ /* If there was an existing entry in this hash slot, link */ \
+ /* this new entry to it. However, the 0th entry in the */ \
+ /* entries table is unused, so we can freely scribble on it. */ \
+ /* So don't bother checking if the slot was used - we'll */ \
+ /* scribble on the unused entry if it was not, but that's */ \
+ /* harmless. Avoiding the branch in this critical path */ \
+ /* speeds this up a little bit. */ \
+ /* if (*__myhsp != INVALID_ENTRY) */ \
+ (_he)[(*__myhsp)].prev = __myhe; \
+ *__myhsp = _hn; \
+ if (++(_hn) >= PGLZ_HISTORY_SIZE + 1) { \
+ (_hn) = 1; \
+ (_recycle) = true; \
+ } \
+} while (0)
+
+
+/* ----------
+ * pglz_out_ctrl -
+ *
+ * Outputs the last and allocates a new control byte if needed.
+ * ----------
+ */
+#define pglz_out_ctrl(__ctrlp,__ctrlb,__ctrl,__buf) \
+do { \
+ if ((__ctrl & 0xff) == 0) \
+ { \
+ *(__ctrlp) = __ctrlb; \
+ __ctrlp = (__buf)++; \
+ __ctrlb = 0; \
+ __ctrl = 1; \
+ } \
+} while (0)
+
+
+/* ----------
+ * pglz_out_literal -
+ *
+ * Outputs a literal byte to the destination buffer including the
+ * appropriate control bit.
+ * ----------
+ */
+#define pglz_out_literal(_ctrlp,_ctrlb,_ctrl,_buf,_byte) \
+do { \
+ pglz_out_ctrl(_ctrlp,_ctrlb,_ctrl,_buf); \
+ *(_buf)++ = (unsigned char)(_byte); \
+ _ctrl <<= 1; \
+} while (0)
+
+
+/* ----------
+ * pglz_out_tag -
+ *
+ * Outputs a backward reference tag of 2-4 bytes (depending on
+ * offset and length) to the destination buffer including the
+ * appropriate control bit.
+ * ----------
+ */
+#define pglz_out_tag(_ctrlp,_ctrlb,_ctrl,_buf,_len,_off) \
+do { \
+ pglz_out_ctrl(_ctrlp,_ctrlb,_ctrl,_buf); \
+ _ctrlb |= _ctrl; \
+ _ctrl <<= 1; \
+ if (_len > 17) \
+ { \
+ (_buf)[0] = (unsigned char)((((_off) & 0xf00) >> 4) | 0x0f); \
+ (_buf)[1] = (unsigned char)(((_off) & 0xff)); \
+ (_buf)[2] = (unsigned char)((_len) - 18); \
+ (_buf) += 3; \
+ } else { \
+ (_buf)[0] = (unsigned char)((((_off) & 0xf00) >> 4) | ((_len) - 3)); \
+ (_buf)[1] = (unsigned char)((_off) & 0xff); \
+ (_buf) += 2; \
+ } \
+} while (0)
+
+
+/* ----------
+ * pglz_find_match -
+ *
+ * Lookup the history table if the actual input stream matches
+ * another sequence of characters, starting somewhere earlier
+ * in the input buffer.
+ * ----------
+ */
+static inline int
+pglz_find_match(int16 *hstart, const char *input, const char *end,
+ int *lenp, int *offp, int good_match, int good_drop, int mask)
+{
+ PGLZ_HistEntry *hent;
+ int16 hentno;
+ int32 len = 0;
+ int32 off = 0;
+
+ /*
+ * Traverse the linked history list until a good enough match is found.
+ */
+ hentno = hstart[pglz_hist_idx(input, end, mask)];
+ hent = &hist_entries[hentno];
+ while (hent != INVALID_ENTRY_PTR)
+ {
+ const char *ip = input;
+ const char *hp = hent->pos;
+ int32 thisoff;
+ int32 thislen;
+
+ /*
+ * Stop if the offset does not fit into our tag anymore.
+ */
+ thisoff = ip - hp;
+ if (thisoff >= 0x0fff)
+ break;
+
+ /*
+ * Determine length of match. A better match must be larger than the
+ * best so far. And if we already have a match of 16 or more bytes,
+ * it's worth the call overhead to use memcmp() to check if this match
+ * is equal for the same size. After that we must fallback to
+ * character by character comparison to know the exact position where
+ * the diff occurred.
+ */
+ thislen = 0;
+ if (len >= 16)
+ {
+ if (memcmp(ip, hp, len) == 0)
+ {
+ thislen = len;
+ ip += len;
+ hp += len;
+ while (ip < end && *ip == *hp && thislen < PGLZ_MAX_MATCH)
+ {
+ thislen++;
+ ip++;
+ hp++;
+ }
+ }
+ }
+ else
+ {
+ while (ip < end && *ip == *hp && thislen < PGLZ_MAX_MATCH)
+ {
+ thislen++;
+ ip++;
+ hp++;
+ }
+ }
+
+ /*
+ * Remember this match as the best (if it is)
+ */
+ if (thislen > len)
+ {
+ len = thislen;
+ off = thisoff;
+ }
+
+ /*
+ * Advance to the next history entry
+ */
+ hent = hent->next;
+
+ /*
+ * Be happy with lesser good matches the more entries we visited. But
+ * no point in doing calculation if we're at end of list.
+ */
+ if (hent != INVALID_ENTRY_PTR)
+ {
+ if (len >= good_match)
+ break;
+ good_match -= (good_match * good_drop) / 100;
+ }
+ }
+
+ /*
+ * Return match information only if it results at least in one byte
+ * reduction.
+ */
+ if (len > 2)
+ {
+ *lenp = len;
+ *offp = off;
+ return 1;
+ }
+
+ return 0;
+}
+
+
+/* ----------
+ * pglz_compress -
+ *
+ * Compresses source into dest using strategy. Returns the number of
+ * bytes written in buffer dest, or -1 if compression fails.
+ * ----------
+ */
+int32
+pglz_compress(const char *source, int32 slen, char *dest,
+ const PGLZ_Strategy *strategy)
+{
+ unsigned char *bp = (unsigned char *) dest;
+ unsigned char *bstart = bp;
+ int hist_next = 1;
+ bool hist_recycle = false;
+ const char *dp = source;
+ const char *dend = source + slen;
+ unsigned char ctrl_dummy = 0;
+ unsigned char *ctrlp = &ctrl_dummy;
+ unsigned char ctrlb = 0;
+ unsigned char ctrl = 0;
+ bool found_match = false;
+ int32 match_len;
+ int32 match_off;
+ int32 good_match;
+ int32 good_drop;
+ int32 result_size;
+ int32 result_max;
+ int32 need_rate;
+ int hashsz;
+ int mask;
+
+ /*
+ * Our fallback strategy is the default.
+ */
+ if (strategy == NULL)
+ strategy = PGLZ_strategy_default;
+
+ /*
+ * If the strategy forbids compression (at all or if source chunk size out
+ * of range), fail.
+ */
+ if (strategy->match_size_good <= 0 ||
+ slen < strategy->min_input_size ||
+ slen > strategy->max_input_size)
+ return -1;
+
+ /*
+ * Limit the match parameters to the supported range.
+ */
+ good_match = strategy->match_size_good;
+ if (good_match > PGLZ_MAX_MATCH)
+ good_match = PGLZ_MAX_MATCH;
+ else if (good_match < 17)
+ good_match = 17;
+
+ good_drop = strategy->match_size_drop;
+ if (good_drop < 0)
+ good_drop = 0;
+ else if (good_drop > 100)
+ good_drop = 100;
+
+ need_rate = strategy->min_comp_rate;
+ if (need_rate < 0)
+ need_rate = 0;
+ else if (need_rate > 99)
+ need_rate = 99;
+
+ /*
+ * Compute the maximum result size allowed by the strategy, namely the
+ * input size minus the minimum wanted compression rate. This had better
+ * be <= slen, else we might overrun the provided output buffer.
+ */
+ if (slen > (INT_MAX / 100))
+ {
+ /* Approximate to avoid overflow */
+ result_max = (slen / 100) * (100 - need_rate);
+ }
+ else
+ result_max = (slen * (100 - need_rate)) / 100;
+
+ /*
+ * Experiments suggest that these hash sizes work pretty well. A large
+ * hash table minimizes collision, but has a higher startup cost. For a
+ * small input, the startup cost dominates. The table size must be a power
+ * of two.
+ */
+ if (slen < 128)
+ hashsz = 512;
+ else if (slen < 256)
+ hashsz = 1024;
+ else if (slen < 512)
+ hashsz = 2048;
+ else if (slen < 1024)
+ hashsz = 4096;
+ else
+ hashsz = 8192;
+ mask = hashsz - 1;
+
+ /*
+ * Initialize the history lists to empty. We do not need to zero the
+ * hist_entries[] array; its entries are initialized as they are used.
+ */
+ memset(hist_start, 0, hashsz * sizeof(int16));
+
+ /*
+ * Compress the source directly into the output buffer.
+ */
+ while (dp < dend)
+ {
+ /*
+ * If we already exceeded the maximum result size, fail.
+ *
+ * We check once per loop; since the loop body could emit as many as 4
+ * bytes (a control byte and 3-byte tag), PGLZ_MAX_OUTPUT() had better
+ * allow 4 slop bytes.
+ */
+ if (bp - bstart >= result_max)
+ return -1;
+
+ /*
+ * If we've emitted more than first_success_by bytes without finding
+ * anything compressible at all, fail. This lets us fall out
+ * reasonably quickly when looking at incompressible input (such as
+ * pre-compressed data).
+ */
+ if (!found_match && bp - bstart >= strategy->first_success_by)
+ return -1;
+
+ /*
+ * Try to find a match in the history
+ */
+ if (pglz_find_match(hist_start, dp, dend, &match_len,
+ &match_off, good_match, good_drop, mask))
+ {
+ /*
+ * Create the tag and add history entries for all matched
+ * characters.
+ */
+ pglz_out_tag(ctrlp, ctrlb, ctrl, bp, match_len, match_off);
+ while (match_len--)
+ {
+ pglz_hist_add(hist_start, hist_entries,
+ hist_next, hist_recycle,
+ dp, dend, mask);
+ dp++; /* Do not do this ++ in the line above! */
+ /* The macro would do it four times - Jan. */
+ }
+ found_match = true;
+ }
+ else
+ {
+ /*
+ * No match found. Copy one literal byte.
+ */
+ pglz_out_literal(ctrlp, ctrlb, ctrl, bp, *dp);
+ pglz_hist_add(hist_start, hist_entries,
+ hist_next, hist_recycle,
+ dp, dend, mask);
+ dp++; /* Do not do this ++ in the line above! */
+ /* The macro would do it four times - Jan. */
+ }
+ }
+
+ /*
+ * Write out the last control byte and check that we haven't overrun the
+ * output size allowed by the strategy.
+ */
+ *ctrlp = ctrlb;
+ result_size = bp - bstart;
+ if (result_size >= result_max)
+ return -1;
+
+ /* success */
+ return result_size;
+}
+
+
+/* ----------
+ * pglz_decompress -
+ *
+ * Decompresses source into dest. Returns the number of bytes
+ * decompressed into the destination buffer, or -1 if the
+ * compressed data is corrupted.
+ *
+ * If check_complete is true, the data is considered corrupted
+ * if we don't exactly fill the destination buffer. Callers that
+ * are extracting a slice typically can't apply this check.
+ * ----------
+ */
+int32
+pglz_decompress(const char *source, int32 slen, char *dest,
+ int32 rawsize, bool check_complete)
+{
+ const unsigned char *sp;
+ const unsigned char *srcend;
+ unsigned char *dp;
+ unsigned char *destend;
+
+ sp = (const unsigned char *) source;
+ srcend = ((const unsigned char *) source) + slen;
+ dp = (unsigned char *) dest;
+ destend = dp + rawsize;
+
+ while (sp < srcend && dp < destend)
+ {
+ /*
+ * Read one control byte and process the next 8 items (or as many as
+ * remain in the compressed input).
+ */
+ unsigned char ctrl = *sp++;
+ int ctrlc;
+
+ for (ctrlc = 0; ctrlc < 8 && sp < srcend && dp < destend; ctrlc++)
+ {
+ if (ctrl & 1)
+ {
+ /*
+ * Set control bit means we must read a match tag. The match
+ * is coded with two bytes. First byte uses lower nibble to
+ * code length - 3. Higher nibble contains upper 4 bits of the
+ * offset. The next following byte contains the lower 8 bits
+ * of the offset. If the length is coded as 18, another
+ * extension tag byte tells how much longer the match really
+ * was (0-255).
+ */
+ int32 len;
+ int32 off;
+
+ len = (sp[0] & 0x0f) + 3;
+ off = ((sp[0] & 0xf0) << 4) | sp[1];
+ sp += 2;
+ if (len == 18)
+ len += *sp++;
+
+ /*
+ * Check for corrupt data: if we fell off the end of the
+ * source, or if we obtained off = 0, or if off is more than
+ * the distance back to the buffer start, we have problems.
+ * (We must check for off = 0, else we risk an infinite loop
+ * below in the face of corrupt data. Likewise, the upper
+ * limit on off prevents accessing outside the buffer
+ * boundaries.)
+ */
+ if (unlikely(sp > srcend || off == 0 ||
+ off > (dp - (unsigned char *) dest)))
+ return -1;
+
+ /*
+ * Don't emit more data than requested.
+ */
+ len = Min(len, destend - dp);
+
+ /*
+ * Now we copy the bytes specified by the tag from OUTPUT to
+ * OUTPUT (copy len bytes from dp - off to dp). The copied
+ * areas could overlap, so to avoid undefined behavior in
+ * memcpy(), be careful to copy only non-overlapping regions.
+ *
+ * Note that we cannot use memmove() instead, since while its
+ * behavior is well-defined, it's also not what we want.
+ */
+ while (off < len)
+ {
+ /*
+ * We can safely copy "off" bytes since that clearly
+ * results in non-overlapping source and destination.
+ */
+ memcpy(dp, dp - off, off);
+ len -= off;
+ dp += off;
+
+ /*----------
+ * This bit is less obvious: we can double "off" after
+ * each such step. Consider this raw input:
+ * 112341234123412341234
+ * This will be encoded as 5 literal bytes "11234" and
+ * then a match tag with length 16 and offset 4. After
+ * memcpy'ing the first 4 bytes, we will have emitted
+ * 112341234
+ * so we can double "off" to 8, then after the next step
+ * we have emitted
+ * 11234123412341234
+ * Then we can double "off" again, after which it is more
+ * than the remaining "len" so we fall out of this loop
+ * and finish with a non-overlapping copy of the
+ * remainder. In general, a match tag with off < len
+ * implies that the decoded data has a repeat length of
+ * "off". We can handle 1, 2, 4, etc repetitions of the
+ * repeated string per memcpy until we get to a situation
+ * where the final copy step is non-overlapping.
+ *
+ * (Another way to understand this is that we are keeping
+ * the copy source point dp - off the same throughout.)
+ *----------
+ */
+ off += off;
+ }
+ memcpy(dp, dp - off, len);
+ dp += len;
+ }
+ else
+ {
+ /*
+ * An unset control bit means LITERAL BYTE. So we just copy
+ * one from INPUT to OUTPUT.
+ */
+ *dp++ = *sp++;
+ }
+
+ /*
+ * Advance the control bit
+ */
+ ctrl >>= 1;
+ }
+ }
+
+ /*
+ * If requested, check we decompressed the right amount.
+ */
+ if (check_complete && (dp != destend || sp != srcend))
+ return -1;
+
+ /*
+ * That's it.
+ */
+ return (char *) dp - dest;
+}
+
+
+/* ----------
+ * pglz_maximum_compressed_size -
+ *
+ * Calculate the maximum compressed size for a given amount of raw data.
+ * Return the maximum size, or total compressed size if maximum size is
+ * larger than total compressed size.
+ *
+ * We can't use PGLZ_MAX_OUTPUT for this purpose, because that's used to size
+ * the compression buffer (and abort the compression). It does not really say
+ * what's the maximum compressed size for an input of a given length, and it
+ * may happen that while the whole value is compressible (and thus fits into
+ * PGLZ_MAX_OUTPUT nicely), the prefix is not compressible at all.
+ * ----------
+ */
+int32
+pglz_maximum_compressed_size(int32 rawsize, int32 total_compressed_size)
+{
+ int64 compressed_size;
+
+ /*
+ * pglz uses one control bit per byte, so if the entire desired prefix is
+ * represented as literal bytes, we'll need (rawsize * 9) bits. We care
+ * about bytes though, so be sure to round up not down.
+ *
+ * Use int64 here to prevent overflow during calculation.
+ */
+ compressed_size = ((int64) rawsize * 9 + 7) / 8;
+
+ /*
+ * The above fails to account for a corner case: we could have compressed
+ * data that starts with N-1 or N-2 literal bytes and then has a match tag
+ * of 2 or 3 bytes. It's therefore possible that we need to fetch 1 or 2
+ * more bytes in order to have the whole match tag. (Match tags earlier
+ * in the compressed data don't cause a problem, since they should
+ * represent more decompressed bytes than they occupy themselves.)
+ */
+ compressed_size += 2;
+
+ /*
+ * Maximum compressed size can't be larger than total compressed size.
+ * (This also ensures that our result fits in int32.)
+ */
+ compressed_size = Min(compressed_size, total_compressed_size);
+
+ return (int32) compressed_size;
+}
diff --git a/contrib/libs/libpq/src/common/pg_prng.c b/contrib/libs/libpq/src/common/pg_prng.c
new file mode 100644
index 0000000000..c7bb92ede3
--- /dev/null
+++ b/contrib/libs/libpq/src/common/pg_prng.c
@@ -0,0 +1,282 @@
+/*-------------------------------------------------------------------------
+ *
+ * Pseudo-Random Number Generator
+ *
+ * We use Blackman and Vigna's xoroshiro128** 1.0 algorithm
+ * to have a small, fast PRNG suitable for generating reasonably
+ * good-quality 64-bit data. This should not be considered
+ * cryptographically strong, however.
+ *
+ * About these generators: https://prng.di.unimi.it/
+ * See also https://en.wikipedia.org/wiki/List_of_random_number_generators
+ *
+ * Copyright (c) 2021-2023, PostgreSQL Global Development Group
+ *
+ * src/common/pg_prng.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "c.h"
+
+#include <math.h>
+
+#include "common/pg_prng.h"
+#include "port/pg_bitutils.h"
+
+/* X/Open (XSI) requires <math.h> to provide M_PI, but core POSIX does not */
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+
+/* process-wide state vector */
+pg_prng_state pg_global_prng_state;
+
+
+/*
+ * 64-bit rotate left
+ */
+static inline uint64
+rotl(uint64 x, int bits)
+{
+ return (x << bits) | (x >> (64 - bits));
+}
+
+/*
+ * The basic xoroshiro128** algorithm.
+ * Generates and returns a 64-bit uniformly distributed number,
+ * updating the state vector for next time.
+ *
+ * Note: the state vector must not be all-zeroes, as that is a fixed point.
+ */
+static uint64
+xoroshiro128ss(pg_prng_state *state)
+{
+ uint64 s0 = state->s0,
+ sx = state->s1 ^ s0,
+ val = rotl(s0 * 5, 7) * 9;
+
+ /* update state */
+ state->s0 = rotl(s0, 24) ^ sx ^ (sx << 16);
+ state->s1 = rotl(sx, 37);
+
+ return val;
+}
+
+/*
+ * We use this generator just to fill the xoroshiro128** state vector
+ * from a 64-bit seed.
+ */
+static uint64
+splitmix64(uint64 *state)
+{
+ /* state update */
+ uint64 val = (*state += UINT64CONST(0x9E3779B97f4A7C15));
+
+ /* value extraction */
+ val = (val ^ (val >> 30)) * UINT64CONST(0xBF58476D1CE4E5B9);
+ val = (val ^ (val >> 27)) * UINT64CONST(0x94D049BB133111EB);
+
+ return val ^ (val >> 31);
+}
+
+/*
+ * Initialize the PRNG state from a 64-bit integer,
+ * taking care that we don't produce all-zeroes.
+ */
+void
+pg_prng_seed(pg_prng_state *state, uint64 seed)
+{
+ state->s0 = splitmix64(&seed);
+ state->s1 = splitmix64(&seed);
+ /* Let's just make sure we didn't get all-zeroes */
+ (void) pg_prng_seed_check(state);
+}
+
+/*
+ * Initialize the PRNG state from a double in the range [-1.0, 1.0],
+ * taking care that we don't produce all-zeroes.
+ */
+void
+pg_prng_fseed(pg_prng_state *state, double fseed)
+{
+ /* Assume there's about 52 mantissa bits; the sign contributes too. */
+ int64 seed = ((double) ((UINT64CONST(1) << 52) - 1)) * fseed;
+
+ pg_prng_seed(state, (uint64) seed);
+}
+
+/*
+ * Validate a PRNG seed value.
+ */
+bool
+pg_prng_seed_check(pg_prng_state *state)
+{
+ /*
+ * If the seeding mechanism chanced to produce all-zeroes, insert
+ * something nonzero. Anything would do; use Knuth's LCG parameters.
+ */
+ if (unlikely(state->s0 == 0 && state->s1 == 0))
+ {
+ state->s0 = UINT64CONST(0x5851F42D4C957F2D);
+ state->s1 = UINT64CONST(0x14057B7EF767814F);
+ }
+
+ /* As a convenience for the pg_prng_strong_seed macro, return true */
+ return true;
+}
+
+/*
+ * Select a random uint64 uniformly from the range [0, PG_UINT64_MAX].
+ */
+uint64
+pg_prng_uint64(pg_prng_state *state)
+{
+ return xoroshiro128ss(state);
+}
+
+/*
+ * Select a random uint64 uniformly from the range [rmin, rmax].
+ * If the range is empty, rmin is always produced.
+ */
+uint64
+pg_prng_uint64_range(pg_prng_state *state, uint64 rmin, uint64 rmax)
+{
+ uint64 val;
+
+ if (likely(rmax > rmin))
+ {
+ /*
+ * Use bitmask rejection method to generate an offset in 0..range.
+ * Each generated val is less than twice "range", so on average we
+ * should not have to iterate more than twice.
+ */
+ uint64 range = rmax - rmin;
+ uint32 rshift = 63 - pg_leftmost_one_pos64(range);
+
+ do
+ {
+ val = xoroshiro128ss(state) >> rshift;
+ } while (val > range);
+ }
+ else
+ val = 0;
+
+ return rmin + val;
+}
+
+/*
+ * Select a random int64 uniformly from the range [PG_INT64_MIN, PG_INT64_MAX].
+ */
+int64
+pg_prng_int64(pg_prng_state *state)
+{
+ return (int64) xoroshiro128ss(state);
+}
+
+/*
+ * Select a random int64 uniformly from the range [0, PG_INT64_MAX].
+ */
+int64
+pg_prng_int64p(pg_prng_state *state)
+{
+ return (int64) (xoroshiro128ss(state) & UINT64CONST(0x7FFFFFFFFFFFFFFF));
+}
+
+/*
+ * Select a random uint32 uniformly from the range [0, PG_UINT32_MAX].
+ */
+uint32
+pg_prng_uint32(pg_prng_state *state)
+{
+ /*
+ * Although xoroshiro128** is not known to have any weaknesses in
+ * randomness of low-order bits, we prefer to use the upper bits of its
+ * result here and below.
+ */
+ uint64 v = xoroshiro128ss(state);
+
+ return (uint32) (v >> 32);
+}
+
+/*
+ * Select a random int32 uniformly from the range [PG_INT32_MIN, PG_INT32_MAX].
+ */
+int32
+pg_prng_int32(pg_prng_state *state)
+{
+ uint64 v = xoroshiro128ss(state);
+
+ return (int32) (v >> 32);
+}
+
+/*
+ * Select a random int32 uniformly from the range [0, PG_INT32_MAX].
+ */
+int32
+pg_prng_int32p(pg_prng_state *state)
+{
+ uint64 v = xoroshiro128ss(state);
+
+ return (int32) (v >> 33);
+}
+
+/*
+ * Select a random double uniformly from the range [0.0, 1.0).
+ *
+ * Note: if you want a result in the range (0.0, 1.0], the standard way
+ * to get that is "1.0 - pg_prng_double(state)".
+ */
+double
+pg_prng_double(pg_prng_state *state)
+{
+ uint64 v = xoroshiro128ss(state);
+
+ /*
+ * As above, assume there's 52 mantissa bits in a double. This result
+ * could round to 1.0 if double's precision is less than that; but we
+ * assume IEEE float arithmetic elsewhere in Postgres, so this seems OK.
+ */
+ return ldexp((double) (v >> (64 - 52)), -52);
+}
+
+/*
+ * Select a random double from the normal distribution with
+ * mean = 0.0 and stddev = 1.0.
+ *
+ * To get a result from a different normal distribution use
+ * STDDEV * pg_prng_double_normal() + MEAN
+ *
+ * Uses https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform
+ */
+double
+pg_prng_double_normal(pg_prng_state *state)
+{
+ double u1,
+ u2,
+ z0;
+
+ /*
+ * pg_prng_double generates [0, 1), but for the basic version of the
+ * Box-Muller transform the two uniformly distributed random numbers are
+ * expected to be in (0, 1]; in particular we'd better not compute log(0).
+ */
+ u1 = 1.0 - pg_prng_double(state);
+ u2 = 1.0 - pg_prng_double(state);
+
+ /* Apply Box-Muller transform to get one normal-valued output */
+ z0 = sqrt(-2.0 * log(u1)) * sin(2.0 * M_PI * u2);
+ return z0;
+}
+
+/*
+ * Select a random boolean value.
+ */
+bool
+pg_prng_bool(pg_prng_state *state)
+{
+ uint64 v = xoroshiro128ss(state);
+
+ return (bool) (v >> 63);
+}
diff --git a/contrib/libs/libpq/src/common/pgfnames.c b/contrib/libs/libpq/src/common/pgfnames.c
new file mode 100644
index 0000000000..9d2fe9d659
--- /dev/null
+++ b/contrib/libs/libpq/src/common/pgfnames.c
@@ -0,0 +1,94 @@
+/*-------------------------------------------------------------------------
+ *
+ * pgfnames.c
+ * directory handling functions
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/common/pgfnames.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#include <dirent.h>
+
+#ifndef FRONTEND
+#define pg_log_warning(...) elog(WARNING, __VA_ARGS__)
+#else
+#include "common/logging.h"
+#endif
+
+/*
+ * pgfnames
+ *
+ * return a list of the names of objects in the argument directory. Caller
+ * must call pgfnames_cleanup later to free the memory allocated by this
+ * function.
+ */
+char **
+pgfnames(const char *path)
+{
+ DIR *dir;
+ struct dirent *file;
+ char **filenames;
+ int numnames = 0;
+ int fnsize = 200; /* enough for many small dbs */
+
+ dir = opendir(path);
+ if (dir == NULL)
+ {
+ pg_log_warning("could not open directory \"%s\": %m", path);
+ return NULL;
+ }
+
+ filenames = (char **) palloc(fnsize * sizeof(char *));
+
+ while (errno = 0, (file = readdir(dir)) != NULL)
+ {
+ if (strcmp(file->d_name, ".") != 0 && strcmp(file->d_name, "..") != 0)
+ {
+ if (numnames + 1 >= fnsize)
+ {
+ fnsize *= 2;
+ filenames = (char **) repalloc(filenames,
+ fnsize * sizeof(char *));
+ }
+ filenames[numnames++] = pstrdup(file->d_name);
+ }
+ }
+
+ if (errno)
+ pg_log_warning("could not read directory \"%s\": %m", path);
+
+ filenames[numnames] = NULL;
+
+ if (closedir(dir))
+ pg_log_warning("could not close directory \"%s\": %m", path);
+
+ return filenames;
+}
+
+
+/*
+ * pgfnames_cleanup
+ *
+ * deallocate memory used for filenames
+ */
+void
+pgfnames_cleanup(char **filenames)
+{
+ char **fn;
+
+ for (fn = filenames; *fn; fn++)
+ pfree(*fn);
+
+ pfree(filenames);
+}
diff --git a/contrib/libs/libpq/src/common/protocol_openssl.c b/contrib/libs/libpq/src/common/protocol_openssl.c
new file mode 100644
index 0000000000..089cbd33cc
--- /dev/null
+++ b/contrib/libs/libpq/src/common/protocol_openssl.c
@@ -0,0 +1,117 @@
+/*-------------------------------------------------------------------------
+ *
+ * protocol_openssl.c
+ * OpenSSL functionality shared between frontend and backend
+ *
+ * This should only be used if code is compiled with OpenSSL support.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/common/protocol_openssl.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#include "common/openssl.h"
+
+/*
+ * Replacements for APIs introduced in OpenSSL 1.1.0.
+ */
+#ifndef SSL_CTX_set_min_proto_version
+
+/*
+ * OpenSSL versions that support TLS 1.3 shouldn't get here because they
+ * already have these functions. So we don't have to keep updating the below
+ * code for every new TLS version, and eventually it can go away. But let's
+ * just check this to make sure ...
+ */
+#ifdef TLS1_3_VERSION
+#error OpenSSL version mismatch
+#endif
+
+int
+SSL_CTX_set_min_proto_version(SSL_CTX *ctx, int version)
+{
+ int ssl_options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
+
+ if (version > TLS1_VERSION)
+ ssl_options |= SSL_OP_NO_TLSv1;
+
+ /*
+ * Some OpenSSL versions define TLS*_VERSION macros but not the
+ * corresponding SSL_OP_NO_* macro, so in those cases we have to return
+ * unsuccessfully here.
+ */
+#ifdef TLS1_1_VERSION
+ if (version > TLS1_1_VERSION)
+ {
+#ifdef SSL_OP_NO_TLSv1_1
+ ssl_options |= SSL_OP_NO_TLSv1_1;
+#else
+ return 0;
+#endif
+ }
+#endif
+#ifdef TLS1_2_VERSION
+ if (version > TLS1_2_VERSION)
+ {
+#ifdef SSL_OP_NO_TLSv1_2
+ ssl_options |= SSL_OP_NO_TLSv1_2;
+#else
+ return 0;
+#endif
+ }
+#endif
+
+ SSL_CTX_set_options(ctx, ssl_options);
+
+ return 1; /* success */
+}
+
+int
+SSL_CTX_set_max_proto_version(SSL_CTX *ctx, int version)
+{
+ int ssl_options = 0;
+
+ Assert(version != 0);
+
+ /*
+ * Some OpenSSL versions define TLS*_VERSION macros but not the
+ * corresponding SSL_OP_NO_* macro, so in those cases we have to return
+ * unsuccessfully here.
+ */
+#ifdef TLS1_1_VERSION
+ if (version < TLS1_1_VERSION)
+ {
+#ifdef SSL_OP_NO_TLSv1_1
+ ssl_options |= SSL_OP_NO_TLSv1_1;
+#else
+ return 0;
+#endif
+ }
+#endif
+#ifdef TLS1_2_VERSION
+ if (version < TLS1_2_VERSION)
+ {
+#ifdef SSL_OP_NO_TLSv1_2
+ ssl_options |= SSL_OP_NO_TLSv1_2;
+#else
+ return 0;
+#endif
+ }
+#endif
+
+ SSL_CTX_set_options(ctx, ssl_options);
+
+ return 1; /* success */
+}
+
+#endif /* !SSL_CTX_set_min_proto_version */
diff --git a/contrib/libs/libpq/src/common/psprintf.c b/contrib/libs/libpq/src/common/psprintf.c
new file mode 100644
index 0000000000..c8280c0880
--- /dev/null
+++ b/contrib/libs/libpq/src/common/psprintf.c
@@ -0,0 +1,151 @@
+/*-------------------------------------------------------------------------
+ *
+ * psprintf.c
+ * sprintf into an allocated-on-demand buffer
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/common/psprintf.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+
+#include "postgres.h"
+
+#error #include "utils/memutils.h"
+
+#else
+
+#include "postgres_fe.h"
+
+/* It's possible we could use a different value for this in frontend code */
+#define MaxAllocSize ((Size) 0x3fffffff) /* 1 gigabyte - 1 */
+
+#endif
+
+
+/*
+ * psprintf
+ *
+ * Format text data under the control of fmt (an sprintf-style format string)
+ * and return it in an allocated-on-demand buffer. The buffer is allocated
+ * with palloc in the backend, or malloc in frontend builds. Caller is
+ * responsible to free the buffer when no longer needed, if appropriate.
+ *
+ * Errors are not returned to the caller, but are reported via elog(ERROR)
+ * in the backend, or printf-to-stderr-and-exit() in frontend builds.
+ * One should therefore think twice about using this in libpq.
+ */
+char *
+psprintf(const char *fmt,...)
+{
+ int save_errno = errno;
+ size_t len = 128; /* initial assumption about buffer size */
+
+ for (;;)
+ {
+ char *result;
+ va_list args;
+ size_t newlen;
+
+ /*
+ * Allocate result buffer. Note that in frontend this maps to malloc
+ * with exit-on-error.
+ */
+ result = (char *) palloc(len);
+
+ /* Try to format the data. */
+ errno = save_errno;
+ va_start(args, fmt);
+ newlen = pvsnprintf(result, len, fmt, args);
+ va_end(args);
+
+ if (newlen < len)
+ return result; /* success */
+
+ /* Release buffer and loop around to try again with larger len. */
+ pfree(result);
+ len = newlen;
+ }
+}
+
+/*
+ * pvsnprintf
+ *
+ * Attempt to format text data under the control of fmt (an sprintf-style
+ * format string) and insert it into buf (which has length len).
+ *
+ * If successful, return the number of bytes emitted, not counting the
+ * trailing zero byte. This will always be strictly less than len.
+ *
+ * If there's not enough space in buf, return an estimate of the buffer size
+ * needed to succeed (this *must* be more than the given len, else callers
+ * might loop infinitely).
+ *
+ * Other error cases do not return, but exit via elog(ERROR) or exit().
+ * Hence, this shouldn't be used inside libpq.
+ *
+ * Caution: callers must be sure to preserve their entry-time errno
+ * when looping, in case the fmt contains "%m".
+ *
+ * Note that the semantics of the return value are not exactly C99's.
+ * First, we don't promise that the estimated buffer size is exactly right;
+ * callers must be prepared to loop multiple times to get the right size.
+ * (Given a C99-compliant vsnprintf, that won't happen, but it is rumored
+ * that some implementations don't always return the same value ...)
+ * Second, we return the recommended buffer size, not one less than that;
+ * this lets overflow concerns be handled here rather than in the callers.
+ */
+size_t
+pvsnprintf(char *buf, size_t len, const char *fmt, va_list args)
+{
+ int nprinted;
+
+ nprinted = vsnprintf(buf, len, fmt, args);
+
+ /* We assume failure means the fmt is bogus, hence hard failure is OK */
+ if (unlikely(nprinted < 0))
+ {
+#ifndef FRONTEND
+ elog(ERROR, "vsnprintf failed: %m with format string \"%s\"", fmt);
+#else
+ fprintf(stderr, "vsnprintf failed: %s with format string \"%s\"\n",
+ strerror(errno), fmt);
+ exit(EXIT_FAILURE);
+#endif
+ }
+
+ if ((size_t) nprinted < len)
+ {
+ /* Success. Note nprinted does not include trailing null. */
+ return (size_t) nprinted;
+ }
+
+ /*
+ * We assume a C99-compliant vsnprintf, so believe its estimate of the
+ * required space, and add one for the trailing null. (If it's wrong, the
+ * logic will still work, but we may loop multiple times.)
+ *
+ * Choke if the required space would exceed MaxAllocSize. Note we use
+ * this palloc-oriented overflow limit even when in frontend.
+ */
+ if (unlikely((size_t) nprinted > MaxAllocSize - 1))
+ {
+#ifndef FRONTEND
+ ereport(ERROR,
+ (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+ errmsg("out of memory")));
+#else
+ fprintf(stderr, _("out of memory\n"));
+ exit(EXIT_FAILURE);
+#endif
+ }
+
+ return nprinted + 1;
+}
diff --git a/contrib/libs/libpq/src/common/relpath.c b/contrib/libs/libpq/src/common/relpath.c
new file mode 100644
index 0000000000..87de5f6c96
--- /dev/null
+++ b/contrib/libs/libpq/src/common/relpath.c
@@ -0,0 +1,210 @@
+/*-------------------------------------------------------------------------
+ * relpath.c
+ * Shared frontend/backend code to compute pathnames of relation files
+ *
+ * This module also contains some logic associated with fork names.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/common/relpath.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#include "catalog/pg_tablespace_d.h"
+#include "common/relpath.h"
+#include "storage/backendid.h"
+
+
+/*
+ * Lookup table of fork name by fork number.
+ *
+ * If you add a new entry, remember to update the errhint in
+ * forkname_to_number() below, and update the SGML documentation for
+ * pg_relation_size().
+ */
+const char *const forkNames[] = {
+ "main", /* MAIN_FORKNUM */
+ "fsm", /* FSM_FORKNUM */
+ "vm", /* VISIBILITYMAP_FORKNUM */
+ "init" /* INIT_FORKNUM */
+};
+
+StaticAssertDecl(lengthof(forkNames) == (MAX_FORKNUM + 1),
+ "array length mismatch");
+
+/*
+ * forkname_to_number - look up fork number by name
+ *
+ * In backend, we throw an error for no match; in frontend, we just
+ * return InvalidForkNumber.
+ */
+ForkNumber
+forkname_to_number(const char *forkName)
+{
+ ForkNumber forkNum;
+
+ for (forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++)
+ if (strcmp(forkNames[forkNum], forkName) == 0)
+ return forkNum;
+
+#ifndef FRONTEND
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("invalid fork name"),
+ errhint("Valid fork names are \"main\", \"fsm\", "
+ "\"vm\", and \"init\".")));
+#endif
+
+ return InvalidForkNumber;
+}
+
+/*
+ * forkname_chars
+ * We use this to figure out whether a filename could be a relation
+ * fork (as opposed to an oddly named stray file that somehow ended
+ * up in the database directory). If the passed string begins with
+ * a fork name (other than the main fork name), we return its length,
+ * and set *fork (if not NULL) to the fork number. If not, we return 0.
+ *
+ * Note that the present coding assumes that there are no fork names which
+ * are prefixes of other fork names.
+ */
+int
+forkname_chars(const char *str, ForkNumber *fork)
+{
+ ForkNumber forkNum;
+
+ for (forkNum = 1; forkNum <= MAX_FORKNUM; forkNum++)
+ {
+ int len = strlen(forkNames[forkNum]);
+
+ if (strncmp(forkNames[forkNum], str, len) == 0)
+ {
+ if (fork)
+ *fork = forkNum;
+ return len;
+ }
+ }
+ if (fork)
+ *fork = InvalidForkNumber;
+ return 0;
+}
+
+
+/*
+ * GetDatabasePath - construct path to a database directory
+ *
+ * Result is a palloc'd string.
+ *
+ * XXX this must agree with GetRelationPath()!
+ */
+char *
+GetDatabasePath(Oid dbOid, Oid spcOid)
+{
+ if (spcOid == GLOBALTABLESPACE_OID)
+ {
+ /* Shared system relations live in {datadir}/global */
+ Assert(dbOid == 0);
+ return pstrdup("global");
+ }
+ else if (spcOid == DEFAULTTABLESPACE_OID)
+ {
+ /* The default tablespace is {datadir}/base */
+ return psprintf("base/%u", dbOid);
+ }
+ else
+ {
+ /* All other tablespaces are accessed via symlinks */
+ return psprintf("pg_tblspc/%u/%s/%u",
+ spcOid, TABLESPACE_VERSION_DIRECTORY, dbOid);
+ }
+}
+
+/*
+ * GetRelationPath - construct path to a relation's file
+ *
+ * Result is a palloc'd string.
+ *
+ * Note: ideally, backendId would be declared as type BackendId, but relpath.h
+ * would have to include a backend-only header to do that; doesn't seem worth
+ * the trouble considering BackendId is just int anyway.
+ */
+char *
+GetRelationPath(Oid dbOid, Oid spcOid, RelFileNumber relNumber,
+ int backendId, ForkNumber forkNumber)
+{
+ char *path;
+
+ if (spcOid == GLOBALTABLESPACE_OID)
+ {
+ /* Shared system relations live in {datadir}/global */
+ Assert(dbOid == 0);
+ Assert(backendId == InvalidBackendId);
+ if (forkNumber != MAIN_FORKNUM)
+ path = psprintf("global/%u_%s",
+ relNumber, forkNames[forkNumber]);
+ else
+ path = psprintf("global/%u", relNumber);
+ }
+ else if (spcOid == DEFAULTTABLESPACE_OID)
+ {
+ /* The default tablespace is {datadir}/base */
+ if (backendId == InvalidBackendId)
+ {
+ if (forkNumber != MAIN_FORKNUM)
+ path = psprintf("base/%u/%u_%s",
+ dbOid, relNumber,
+ forkNames[forkNumber]);
+ else
+ path = psprintf("base/%u/%u",
+ dbOid, relNumber);
+ }
+ else
+ {
+ if (forkNumber != MAIN_FORKNUM)
+ path = psprintf("base/%u/t%d_%u_%s",
+ dbOid, backendId, relNumber,
+ forkNames[forkNumber]);
+ else
+ path = psprintf("base/%u/t%d_%u",
+ dbOid, backendId, relNumber);
+ }
+ }
+ else
+ {
+ /* All other tablespaces are accessed via symlinks */
+ if (backendId == InvalidBackendId)
+ {
+ if (forkNumber != MAIN_FORKNUM)
+ path = psprintf("pg_tblspc/%u/%s/%u/%u_%s",
+ spcOid, TABLESPACE_VERSION_DIRECTORY,
+ dbOid, relNumber,
+ forkNames[forkNumber]);
+ else
+ path = psprintf("pg_tblspc/%u/%s/%u/%u",
+ spcOid, TABLESPACE_VERSION_DIRECTORY,
+ dbOid, relNumber);
+ }
+ else
+ {
+ if (forkNumber != MAIN_FORKNUM)
+ path = psprintf("pg_tblspc/%u/%s/%u/t%d_%u_%s",
+ spcOid, TABLESPACE_VERSION_DIRECTORY,
+ dbOid, backendId, relNumber,
+ forkNames[forkNumber]);
+ else
+ path = psprintf("pg_tblspc/%u/%s/%u/t%d_%u",
+ spcOid, TABLESPACE_VERSION_DIRECTORY,
+ dbOid, backendId, relNumber);
+ }
+ }
+ return path;
+}
diff --git a/contrib/libs/libpq/src/common/restricted_token.c b/contrib/libs/libpq/src/common/restricted_token.c
new file mode 100644
index 0000000000..4ae1ed1e8a
--- /dev/null
+++ b/contrib/libs/libpq/src/common/restricted_token.c
@@ -0,0 +1,174 @@
+/*-------------------------------------------------------------------------
+ *
+ * restricted_token.c
+ * helper routine to ensure restricted token on Windows
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/common/restricted_token.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+#error "This file is not expected to be compiled for backend code"
+#endif
+
+#include "postgres_fe.h"
+
+#include "common/logging.h"
+#include "common/restricted_token.h"
+
+#ifdef WIN32
+
+/* internal vars */
+char *restrict_env;
+
+/* Windows API define missing from some versions of MingW headers */
+#ifndef DISABLE_MAX_PRIVILEGE
+#define DISABLE_MAX_PRIVILEGE 0x1
+#endif
+
+/*
+ * Create a restricted token and execute the specified process with it.
+ *
+ * Returns restricted token on success and 0 on failure.
+ *
+ * On any system not containing the required functions, do nothing
+ * but still report an error.
+ */
+HANDLE
+CreateRestrictedProcess(char *cmd, PROCESS_INFORMATION *processInfo)
+{
+ BOOL b;
+ STARTUPINFO si;
+ HANDLE origToken;
+ HANDLE restrictedToken;
+ SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
+ SID_AND_ATTRIBUTES dropSids[2];
+
+ ZeroMemory(&si, sizeof(si));
+ si.cb = sizeof(si);
+
+ /* Open the current token to use as a base for the restricted one */
+ if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &origToken))
+ {
+ pg_log_error("could not open process token: error code %lu",
+ GetLastError());
+ return 0;
+ }
+
+ /* Allocate list of SIDs to remove */
+ ZeroMemory(&dropSids, sizeof(dropSids));
+ if (!AllocateAndInitializeSid(&NtAuthority, 2,
+ SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0,
+ 0, &dropSids[0].Sid) ||
+ !AllocateAndInitializeSid(&NtAuthority, 2,
+ SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS, 0, 0, 0, 0, 0,
+ 0, &dropSids[1].Sid))
+ {
+ pg_log_error("could not allocate SIDs: error code %lu",
+ GetLastError());
+ CloseHandle(origToken);
+ return 0;
+ }
+
+ b = CreateRestrictedToken(origToken,
+ DISABLE_MAX_PRIVILEGE,
+ sizeof(dropSids) / sizeof(dropSids[0]),
+ dropSids,
+ 0, NULL,
+ 0, NULL,
+ &restrictedToken);
+
+ FreeSid(dropSids[1].Sid);
+ FreeSid(dropSids[0].Sid);
+ CloseHandle(origToken);
+
+ if (!b)
+ {
+ pg_log_error("could not create restricted token: error code %lu", GetLastError());
+ return 0;
+ }
+
+#ifndef __CYGWIN__
+ AddUserToTokenDacl(restrictedToken);
+#endif
+
+ if (!CreateProcessAsUser(restrictedToken,
+ NULL,
+ cmd,
+ NULL,
+ NULL,
+ TRUE,
+ CREATE_SUSPENDED,
+ NULL,
+ NULL,
+ &si,
+ processInfo))
+
+ {
+ pg_log_error("could not start process for command \"%s\": error code %lu", cmd, GetLastError());
+ return 0;
+ }
+
+ ResumeThread(processInfo->hThread);
+ return restrictedToken;
+}
+#endif
+
+/*
+ * On Windows make sure that we are running with a restricted token,
+ * On other platforms do nothing.
+ */
+void
+get_restricted_token(void)
+{
+#ifdef WIN32
+ HANDLE restrictedToken;
+
+ /*
+ * Before we execute another program, make sure that we are running with a
+ * restricted token. If not, re-execute ourselves with one.
+ */
+
+ if ((restrict_env = getenv("PG_RESTRICT_EXEC")) == NULL
+ || strcmp(restrict_env, "1") != 0)
+ {
+ PROCESS_INFORMATION pi;
+ char *cmdline;
+
+ ZeroMemory(&pi, sizeof(pi));
+
+ cmdline = pg_strdup(GetCommandLine());
+
+ setenv("PG_RESTRICT_EXEC", "1", 1);
+
+ if ((restrictedToken = CreateRestrictedProcess(cmdline, &pi)) == 0)
+ {
+ pg_log_error("could not re-execute with restricted token: error code %lu", GetLastError());
+ }
+ else
+ {
+ /*
+ * Successfully re-executed. Now wait for child process to capture
+ * the exit code.
+ */
+ DWORD x;
+
+ CloseHandle(restrictedToken);
+ CloseHandle(pi.hThread);
+ WaitForSingleObject(pi.hProcess, INFINITE);
+
+ if (!GetExitCodeProcess(pi.hProcess, &x))
+ pg_fatal("could not get exit code from subprocess: error code %lu", GetLastError());
+ exit(x);
+ }
+ pg_free(cmdline);
+ }
+#endif
+}
diff --git a/contrib/libs/libpq/src/common/rmtree.c b/contrib/libs/libpq/src/common/rmtree.c
new file mode 100644
index 0000000000..9d0c32955a
--- /dev/null
+++ b/contrib/libs/libpq/src/common/rmtree.c
@@ -0,0 +1,130 @@
+/*-------------------------------------------------------------------------
+ *
+ * rmtree.c
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/common/rmtree.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#include <unistd.h>
+#include <sys/stat.h>
+
+#include "common/file_utils.h"
+
+#ifndef FRONTEND
+#error #include "storage/fd.h"
+#define pg_log_warning(...) elog(WARNING, __VA_ARGS__)
+#define LOG_LEVEL WARNING
+#define OPENDIR(x) AllocateDir(x)
+#define CLOSEDIR(x) FreeDir(x)
+#else
+#include "common/logging.h"
+#define LOG_LEVEL PG_LOG_WARNING
+#define OPENDIR(x) opendir(x)
+#define CLOSEDIR(x) closedir(x)
+#endif
+
+/*
+ * rmtree
+ *
+ * Delete a directory tree recursively.
+ * Assumes path points to a valid directory.
+ * Deletes everything under path.
+ * If rmtopdir is true deletes the directory too.
+ * Returns true if successful, false if there was any problem.
+ * (The details of the problem are reported already, so caller
+ * doesn't really have to say anything more, but most do.)
+ */
+bool
+rmtree(const char *path, bool rmtopdir)
+{
+ char pathbuf[MAXPGPATH];
+ DIR *dir;
+ struct dirent *de;
+ bool result = true;
+ size_t dirnames_size = 0;
+ size_t dirnames_capacity = 8;
+ char **dirnames = palloc(sizeof(char *) * dirnames_capacity);
+
+ dir = OPENDIR(path);
+ if (dir == NULL)
+ {
+ pg_log_warning("could not open directory \"%s\": %m", path);
+ return false;
+ }
+
+ while (errno = 0, (de = readdir(dir)))
+ {
+ if (strcmp(de->d_name, ".") == 0 ||
+ strcmp(de->d_name, "..") == 0)
+ continue;
+ snprintf(pathbuf, sizeof(pathbuf), "%s/%s", path, de->d_name);
+ switch (get_dirent_type(pathbuf, de, false, LOG_LEVEL))
+ {
+ case PGFILETYPE_ERROR:
+ /* already logged, press on */
+ break;
+ case PGFILETYPE_DIR:
+
+ /*
+ * Defer recursion until after we've closed this directory, to
+ * avoid using more than one file descriptor at a time.
+ */
+ if (dirnames_size == dirnames_capacity)
+ {
+ dirnames = repalloc(dirnames,
+ sizeof(char *) * dirnames_capacity * 2);
+ dirnames_capacity *= 2;
+ }
+ dirnames[dirnames_size++] = pstrdup(pathbuf);
+ break;
+ default:
+ if (unlink(pathbuf) != 0 && errno != ENOENT)
+ {
+ pg_log_warning("could not remove file \"%s\": %m", pathbuf);
+ result = false;
+ }
+ break;
+ }
+ }
+
+ if (errno != 0)
+ {
+ pg_log_warning("could not read directory \"%s\": %m", path);
+ result = false;
+ }
+
+ CLOSEDIR(dir);
+
+ /* Now recurse into the subdirectories we found. */
+ for (size_t i = 0; i < dirnames_size; ++i)
+ {
+ if (!rmtree(dirnames[i], true))
+ result = false;
+ pfree(dirnames[i]);
+ }
+
+ if (rmtopdir)
+ {
+ if (rmdir(path) != 0)
+ {
+ pg_log_warning("could not remove directory \"%s\": %m", path);
+ result = false;
+ }
+ }
+
+ pfree(dirnames);
+
+ return result;
+}
diff --git a/contrib/libs/libpq/src/common/ryu_common.h b/contrib/libs/libpq/src/common/ryu_common.h
new file mode 100644
index 0000000000..ad850acf62
--- /dev/null
+++ b/contrib/libs/libpq/src/common/ryu_common.h
@@ -0,0 +1,133 @@
+/*---------------------------------------------------------------------------
+ *
+ * Common routines for Ryu floating-point output.
+ *
+ * Portions Copyright (c) 2018-2023, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/common/ryu_common.h
+ *
+ * This is a modification of code taken from github.com/ulfjack/ryu under the
+ * terms of the Boost license (not the Apache license). The original copyright
+ * notice follows:
+ *
+ * Copyright 2018 Ulf Adams
+ *
+ * The contents of this file may be used under the terms of the Apache
+ * License, Version 2.0.
+ *
+ * (See accompanying file LICENSE-Apache or copy at
+ * http://www.apache.org/licenses/LICENSE-2.0)
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * Boost Software License, Version 1.0.
+ *
+ * (See accompanying file LICENSE-Boost or copy at
+ * https://www.boost.org/LICENSE_1_0.txt)
+ *
+ * Unless required by applicable law or agreed to in writing, this software is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.
+ *
+ *---------------------------------------------------------------------------
+ */
+#ifndef RYU_COMMON_H
+#define RYU_COMMON_H
+
+/*
+ * Upstream Ryu's output is always the shortest possible. But we adjust that
+ * slightly to improve portability: we avoid outputting the exact midpoint
+ * value between two representable floats, since that relies on the reader
+ * getting the round-to-even rule correct, which seems to be the common
+ * failure mode.
+ *
+ * Defining this to 1 would restore the upstream behavior.
+ */
+#define STRICTLY_SHORTEST 0
+
+#if SIZEOF_SIZE_T < 8
+#define RYU_32_BIT_PLATFORM
+#endif
+
+/* Returns e == 0 ? 1 : ceil(log_2(5^e)). */
+static inline uint32
+pow5bits(const int32 e)
+{
+ /*
+ * This approximation works up to the point that the multiplication
+ * overflows at e = 3529.
+ *
+ * If the multiplication were done in 64 bits, it would fail at 5^4004
+ * which is just greater than 2^9297.
+ */
+ Assert(e >= 0);
+ Assert(e <= 3528);
+ return ((((uint32) e) * 1217359) >> 19) + 1;
+}
+
+/* Returns floor(log_10(2^e)). */
+static inline int32
+log10Pow2(const int32 e)
+{
+ /*
+ * The first value this approximation fails for is 2^1651 which is just
+ * greater than 10^297.
+ */
+ Assert(e >= 0);
+ Assert(e <= 1650);
+ return (int32) ((((uint32) e) * 78913) >> 18);
+}
+
+/* Returns floor(log_10(5^e)). */
+static inline int32
+log10Pow5(const int32 e)
+{
+ /*
+ * The first value this approximation fails for is 5^2621 which is just
+ * greater than 10^1832.
+ */
+ Assert(e >= 0);
+ Assert(e <= 2620);
+ return (int32) ((((uint32) e) * 732923) >> 20);
+}
+
+static inline int
+copy_special_str(char *const result, const bool sign, const bool exponent, const bool mantissa)
+{
+ if (mantissa)
+ {
+ memcpy(result, "NaN", 3);
+ return 3;
+ }
+ if (sign)
+ {
+ result[0] = '-';
+ }
+ if (exponent)
+ {
+ memcpy(result + sign, "Infinity", 8);
+ return sign + 8;
+ }
+ result[sign] = '0';
+ return sign + 1;
+}
+
+static inline uint32
+float_to_bits(const float f)
+{
+ uint32 bits = 0;
+
+ memcpy(&bits, &f, sizeof(float));
+ return bits;
+}
+
+static inline uint64
+double_to_bits(const double d)
+{
+ uint64 bits = 0;
+
+ memcpy(&bits, &d, sizeof(double));
+ return bits;
+}
+
+#endif /* RYU_COMMON_H */
diff --git a/contrib/libs/libpq/src/common/saslprep.c b/contrib/libs/libpq/src/common/saslprep.c
new file mode 100644
index 0000000000..3cf498866a
--- /dev/null
+++ b/contrib/libs/libpq/src/common/saslprep.c
@@ -0,0 +1,1245 @@
+/*-------------------------------------------------------------------------
+ * saslprep.c
+ * SASLprep normalization, for SCRAM authentication
+ *
+ * The SASLprep algorithm is used to process a user-supplied password into
+ * canonical form. For more details, see:
+ *
+ * [RFC3454] Preparation of Internationalized Strings ("stringprep"),
+ * http://www.ietf.org/rfc/rfc3454.txt
+ *
+ * [RFC4013] SASLprep: Stringprep Profile for User Names and Passwords
+ * http://www.ietf.org/rfc/rfc4013.txt
+ *
+ *
+ * Portions Copyright (c) 2017-2023, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/common/saslprep.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#include "common/saslprep.h"
+#include "common/string.h"
+#include "common/unicode_norm.h"
+#include "mb/pg_wchar.h"
+
+/*
+ * In backend, we will use palloc/pfree. In frontend, use malloc, and
+ * return SASLPREP_OOM on out-of-memory.
+ */
+#ifndef FRONTEND
+#define STRDUP(s) pstrdup(s)
+#define ALLOC(size) palloc(size)
+#define FREE(size) pfree(size)
+#else
+#define STRDUP(s) strdup(s)
+#define ALLOC(size) malloc(size)
+#define FREE(size) free(size)
+#endif
+
+/* Prototypes for local functions */
+static int codepoint_range_cmp(const void *a, const void *b);
+static bool is_code_in_table(pg_wchar code, const pg_wchar *map, int mapsize);
+static int pg_utf8_string_len(const char *source);
+
+/*
+ * Stringprep Mapping Tables.
+ *
+ * The stringprep specification includes a number of tables of Unicode
+ * codepoints, used in different parts of the algorithm. They are below,
+ * as arrays of codepoint ranges. Each range is a pair of codepoints,
+ * for the first and last codepoint included the range (inclusive!).
+ */
+
+/*
+ * C.1.2 Non-ASCII space characters
+ *
+ * These are all mapped to the ASCII space character (U+00A0).
+ */
+static const pg_wchar non_ascii_space_ranges[] =
+{
+ 0x00A0, 0x00A0,
+ 0x1680, 0x1680,
+ 0x2000, 0x200B,
+ 0x202F, 0x202F,
+ 0x205F, 0x205F,
+ 0x3000, 0x3000
+};
+
+/*
+ * B.1 Commonly mapped to nothing
+ *
+ * If any of these appear in the input, they are removed.
+ */
+static const pg_wchar commonly_mapped_to_nothing_ranges[] =
+{
+ 0x00AD, 0x00AD,
+ 0x034F, 0x034F,
+ 0x1806, 0x1806,
+ 0x180B, 0x180D,
+ 0x200B, 0x200D,
+ 0x2060, 0x2060,
+ 0xFE00, 0xFE0F,
+ 0xFEFF, 0xFEFF
+};
+
+/*
+ * prohibited_output_ranges is a union of all the characters from
+ * the following tables:
+ *
+ * C.1.2 Non-ASCII space characters
+ * C.2.1 ASCII control characters
+ * C.2.2 Non-ASCII control characters
+ * C.3 Private Use characters
+ * C.4 Non-character code points
+ * C.5 Surrogate code points
+ * C.6 Inappropriate for plain text characters
+ * C.7 Inappropriate for canonical representation characters
+ * C.7 Change display properties or deprecated characters
+ * C.8 Tagging characters
+ *
+ * These are the tables that are listed as "prohibited output"
+ * characters in the SASLprep profile.
+ *
+ * The comment after each code range indicates which source table
+ * the code came from. Note that there is some overlap in the source
+ * tables, so one code might originate from multiple source tables.
+ * Adjacent ranges have also been merged together, to save space.
+ */
+static const pg_wchar prohibited_output_ranges[] =
+{
+ 0x0000, 0x001F, /* C.2.1 */
+ 0x007F, 0x00A0, /* C.1.2, C.2.1, C.2.2 */
+ 0x0340, 0x0341, /* C.8 */
+ 0x06DD, 0x06DD, /* C.2.2 */
+ 0x070F, 0x070F, /* C.2.2 */
+ 0x1680, 0x1680, /* C.1.2 */
+ 0x180E, 0x180E, /* C.2.2 */
+ 0x2000, 0x200F, /* C.1.2, C.2.2, C.8 */
+ 0x2028, 0x202F, /* C.1.2, C.2.2, C.8 */
+ 0x205F, 0x2063, /* C.1.2, C.2.2 */
+ 0x206A, 0x206F, /* C.2.2, C.8 */
+ 0x2FF0, 0x2FFB, /* C.7 */
+ 0x3000, 0x3000, /* C.1.2 */
+ 0xD800, 0xF8FF, /* C.3, C.5 */
+ 0xFDD0, 0xFDEF, /* C.4 */
+ 0xFEFF, 0xFEFF, /* C.2.2 */
+ 0xFFF9, 0xFFFF, /* C.2.2, C.4, C.6 */
+ 0x1D173, 0x1D17A, /* C.2.2 */
+ 0x1FFFE, 0x1FFFF, /* C.4 */
+ 0x2FFFE, 0x2FFFF, /* C.4 */
+ 0x3FFFE, 0x3FFFF, /* C.4 */
+ 0x4FFFE, 0x4FFFF, /* C.4 */
+ 0x5FFFE, 0x5FFFF, /* C.4 */
+ 0x6FFFE, 0x6FFFF, /* C.4 */
+ 0x7FFFE, 0x7FFFF, /* C.4 */
+ 0x8FFFE, 0x8FFFF, /* C.4 */
+ 0x9FFFE, 0x9FFFF, /* C.4 */
+ 0xAFFFE, 0xAFFFF, /* C.4 */
+ 0xBFFFE, 0xBFFFF, /* C.4 */
+ 0xCFFFE, 0xCFFFF, /* C.4 */
+ 0xDFFFE, 0xDFFFF, /* C.4 */
+ 0xE0001, 0xE0001, /* C.9 */
+ 0xE0020, 0xE007F, /* C.9 */
+ 0xEFFFE, 0xEFFFF, /* C.4 */
+ 0xF0000, 0xFFFFF, /* C.3, C.4 */
+ 0x100000, 0x10FFFF /* C.3, C.4 */
+};
+
+/* A.1 Unassigned code points in Unicode 3.2 */
+static const pg_wchar unassigned_codepoint_ranges[] =
+{
+ 0x0221, 0x0221,
+ 0x0234, 0x024F,
+ 0x02AE, 0x02AF,
+ 0x02EF, 0x02FF,
+ 0x0350, 0x035F,
+ 0x0370, 0x0373,
+ 0x0376, 0x0379,
+ 0x037B, 0x037D,
+ 0x037F, 0x0383,
+ 0x038B, 0x038B,
+ 0x038D, 0x038D,
+ 0x03A2, 0x03A2,
+ 0x03CF, 0x03CF,
+ 0x03F7, 0x03FF,
+ 0x0487, 0x0487,
+ 0x04CF, 0x04CF,
+ 0x04F6, 0x04F7,
+ 0x04FA, 0x04FF,
+ 0x0510, 0x0530,
+ 0x0557, 0x0558,
+ 0x0560, 0x0560,
+ 0x0588, 0x0588,
+ 0x058B, 0x0590,
+ 0x05A2, 0x05A2,
+ 0x05BA, 0x05BA,
+ 0x05C5, 0x05CF,
+ 0x05EB, 0x05EF,
+ 0x05F5, 0x060B,
+ 0x060D, 0x061A,
+ 0x061C, 0x061E,
+ 0x0620, 0x0620,
+ 0x063B, 0x063F,
+ 0x0656, 0x065F,
+ 0x06EE, 0x06EF,
+ 0x06FF, 0x06FF,
+ 0x070E, 0x070E,
+ 0x072D, 0x072F,
+ 0x074B, 0x077F,
+ 0x07B2, 0x0900,
+ 0x0904, 0x0904,
+ 0x093A, 0x093B,
+ 0x094E, 0x094F,
+ 0x0955, 0x0957,
+ 0x0971, 0x0980,
+ 0x0984, 0x0984,
+ 0x098D, 0x098E,
+ 0x0991, 0x0992,
+ 0x09A9, 0x09A9,
+ 0x09B1, 0x09B1,
+ 0x09B3, 0x09B5,
+ 0x09BA, 0x09BB,
+ 0x09BD, 0x09BD,
+ 0x09C5, 0x09C6,
+ 0x09C9, 0x09CA,
+ 0x09CE, 0x09D6,
+ 0x09D8, 0x09DB,
+ 0x09DE, 0x09DE,
+ 0x09E4, 0x09E5,
+ 0x09FB, 0x0A01,
+ 0x0A03, 0x0A04,
+ 0x0A0B, 0x0A0E,
+ 0x0A11, 0x0A12,
+ 0x0A29, 0x0A29,
+ 0x0A31, 0x0A31,
+ 0x0A34, 0x0A34,
+ 0x0A37, 0x0A37,
+ 0x0A3A, 0x0A3B,
+ 0x0A3D, 0x0A3D,
+ 0x0A43, 0x0A46,
+ 0x0A49, 0x0A4A,
+ 0x0A4E, 0x0A58,
+ 0x0A5D, 0x0A5D,
+ 0x0A5F, 0x0A65,
+ 0x0A75, 0x0A80,
+ 0x0A84, 0x0A84,
+ 0x0A8C, 0x0A8C,
+ 0x0A8E, 0x0A8E,
+ 0x0A92, 0x0A92,
+ 0x0AA9, 0x0AA9,
+ 0x0AB1, 0x0AB1,
+ 0x0AB4, 0x0AB4,
+ 0x0ABA, 0x0ABB,
+ 0x0AC6, 0x0AC6,
+ 0x0ACA, 0x0ACA,
+ 0x0ACE, 0x0ACF,
+ 0x0AD1, 0x0ADF,
+ 0x0AE1, 0x0AE5,
+ 0x0AF0, 0x0B00,
+ 0x0B04, 0x0B04,
+ 0x0B0D, 0x0B0E,
+ 0x0B11, 0x0B12,
+ 0x0B29, 0x0B29,
+ 0x0B31, 0x0B31,
+ 0x0B34, 0x0B35,
+ 0x0B3A, 0x0B3B,
+ 0x0B44, 0x0B46,
+ 0x0B49, 0x0B4A,
+ 0x0B4E, 0x0B55,
+ 0x0B58, 0x0B5B,
+ 0x0B5E, 0x0B5E,
+ 0x0B62, 0x0B65,
+ 0x0B71, 0x0B81,
+ 0x0B84, 0x0B84,
+ 0x0B8B, 0x0B8D,
+ 0x0B91, 0x0B91,
+ 0x0B96, 0x0B98,
+ 0x0B9B, 0x0B9B,
+ 0x0B9D, 0x0B9D,
+ 0x0BA0, 0x0BA2,
+ 0x0BA5, 0x0BA7,
+ 0x0BAB, 0x0BAD,
+ 0x0BB6, 0x0BB6,
+ 0x0BBA, 0x0BBD,
+ 0x0BC3, 0x0BC5,
+ 0x0BC9, 0x0BC9,
+ 0x0BCE, 0x0BD6,
+ 0x0BD8, 0x0BE6,
+ 0x0BF3, 0x0C00,
+ 0x0C04, 0x0C04,
+ 0x0C0D, 0x0C0D,
+ 0x0C11, 0x0C11,
+ 0x0C29, 0x0C29,
+ 0x0C34, 0x0C34,
+ 0x0C3A, 0x0C3D,
+ 0x0C45, 0x0C45,
+ 0x0C49, 0x0C49,
+ 0x0C4E, 0x0C54,
+ 0x0C57, 0x0C5F,
+ 0x0C62, 0x0C65,
+ 0x0C70, 0x0C81,
+ 0x0C84, 0x0C84,
+ 0x0C8D, 0x0C8D,
+ 0x0C91, 0x0C91,
+ 0x0CA9, 0x0CA9,
+ 0x0CB4, 0x0CB4,
+ 0x0CBA, 0x0CBD,
+ 0x0CC5, 0x0CC5,
+ 0x0CC9, 0x0CC9,
+ 0x0CCE, 0x0CD4,
+ 0x0CD7, 0x0CDD,
+ 0x0CDF, 0x0CDF,
+ 0x0CE2, 0x0CE5,
+ 0x0CF0, 0x0D01,
+ 0x0D04, 0x0D04,
+ 0x0D0D, 0x0D0D,
+ 0x0D11, 0x0D11,
+ 0x0D29, 0x0D29,
+ 0x0D3A, 0x0D3D,
+ 0x0D44, 0x0D45,
+ 0x0D49, 0x0D49,
+ 0x0D4E, 0x0D56,
+ 0x0D58, 0x0D5F,
+ 0x0D62, 0x0D65,
+ 0x0D70, 0x0D81,
+ 0x0D84, 0x0D84,
+ 0x0D97, 0x0D99,
+ 0x0DB2, 0x0DB2,
+ 0x0DBC, 0x0DBC,
+ 0x0DBE, 0x0DBF,
+ 0x0DC7, 0x0DC9,
+ 0x0DCB, 0x0DCE,
+ 0x0DD5, 0x0DD5,
+ 0x0DD7, 0x0DD7,
+ 0x0DE0, 0x0DF1,
+ 0x0DF5, 0x0E00,
+ 0x0E3B, 0x0E3E,
+ 0x0E5C, 0x0E80,
+ 0x0E83, 0x0E83,
+ 0x0E85, 0x0E86,
+ 0x0E89, 0x0E89,
+ 0x0E8B, 0x0E8C,
+ 0x0E8E, 0x0E93,
+ 0x0E98, 0x0E98,
+ 0x0EA0, 0x0EA0,
+ 0x0EA4, 0x0EA4,
+ 0x0EA6, 0x0EA6,
+ 0x0EA8, 0x0EA9,
+ 0x0EAC, 0x0EAC,
+ 0x0EBA, 0x0EBA,
+ 0x0EBE, 0x0EBF,
+ 0x0EC5, 0x0EC5,
+ 0x0EC7, 0x0EC7,
+ 0x0ECE, 0x0ECF,
+ 0x0EDA, 0x0EDB,
+ 0x0EDE, 0x0EFF,
+ 0x0F48, 0x0F48,
+ 0x0F6B, 0x0F70,
+ 0x0F8C, 0x0F8F,
+ 0x0F98, 0x0F98,
+ 0x0FBD, 0x0FBD,
+ 0x0FCD, 0x0FCE,
+ 0x0FD0, 0x0FFF,
+ 0x1022, 0x1022,
+ 0x1028, 0x1028,
+ 0x102B, 0x102B,
+ 0x1033, 0x1035,
+ 0x103A, 0x103F,
+ 0x105A, 0x109F,
+ 0x10C6, 0x10CF,
+ 0x10F9, 0x10FA,
+ 0x10FC, 0x10FF,
+ 0x115A, 0x115E,
+ 0x11A3, 0x11A7,
+ 0x11FA, 0x11FF,
+ 0x1207, 0x1207,
+ 0x1247, 0x1247,
+ 0x1249, 0x1249,
+ 0x124E, 0x124F,
+ 0x1257, 0x1257,
+ 0x1259, 0x1259,
+ 0x125E, 0x125F,
+ 0x1287, 0x1287,
+ 0x1289, 0x1289,
+ 0x128E, 0x128F,
+ 0x12AF, 0x12AF,
+ 0x12B1, 0x12B1,
+ 0x12B6, 0x12B7,
+ 0x12BF, 0x12BF,
+ 0x12C1, 0x12C1,
+ 0x12C6, 0x12C7,
+ 0x12CF, 0x12CF,
+ 0x12D7, 0x12D7,
+ 0x12EF, 0x12EF,
+ 0x130F, 0x130F,
+ 0x1311, 0x1311,
+ 0x1316, 0x1317,
+ 0x131F, 0x131F,
+ 0x1347, 0x1347,
+ 0x135B, 0x1360,
+ 0x137D, 0x139F,
+ 0x13F5, 0x1400,
+ 0x1677, 0x167F,
+ 0x169D, 0x169F,
+ 0x16F1, 0x16FF,
+ 0x170D, 0x170D,
+ 0x1715, 0x171F,
+ 0x1737, 0x173F,
+ 0x1754, 0x175F,
+ 0x176D, 0x176D,
+ 0x1771, 0x1771,
+ 0x1774, 0x177F,
+ 0x17DD, 0x17DF,
+ 0x17EA, 0x17FF,
+ 0x180F, 0x180F,
+ 0x181A, 0x181F,
+ 0x1878, 0x187F,
+ 0x18AA, 0x1DFF,
+ 0x1E9C, 0x1E9F,
+ 0x1EFA, 0x1EFF,
+ 0x1F16, 0x1F17,
+ 0x1F1E, 0x1F1F,
+ 0x1F46, 0x1F47,
+ 0x1F4E, 0x1F4F,
+ 0x1F58, 0x1F58,
+ 0x1F5A, 0x1F5A,
+ 0x1F5C, 0x1F5C,
+ 0x1F5E, 0x1F5E,
+ 0x1F7E, 0x1F7F,
+ 0x1FB5, 0x1FB5,
+ 0x1FC5, 0x1FC5,
+ 0x1FD4, 0x1FD5,
+ 0x1FDC, 0x1FDC,
+ 0x1FF0, 0x1FF1,
+ 0x1FF5, 0x1FF5,
+ 0x1FFF, 0x1FFF,
+ 0x2053, 0x2056,
+ 0x2058, 0x205E,
+ 0x2064, 0x2069,
+ 0x2072, 0x2073,
+ 0x208F, 0x209F,
+ 0x20B2, 0x20CF,
+ 0x20EB, 0x20FF,
+ 0x213B, 0x213C,
+ 0x214C, 0x2152,
+ 0x2184, 0x218F,
+ 0x23CF, 0x23FF,
+ 0x2427, 0x243F,
+ 0x244B, 0x245F,
+ 0x24FF, 0x24FF,
+ 0x2614, 0x2615,
+ 0x2618, 0x2618,
+ 0x267E, 0x267F,
+ 0x268A, 0x2700,
+ 0x2705, 0x2705,
+ 0x270A, 0x270B,
+ 0x2728, 0x2728,
+ 0x274C, 0x274C,
+ 0x274E, 0x274E,
+ 0x2753, 0x2755,
+ 0x2757, 0x2757,
+ 0x275F, 0x2760,
+ 0x2795, 0x2797,
+ 0x27B0, 0x27B0,
+ 0x27BF, 0x27CF,
+ 0x27EC, 0x27EF,
+ 0x2B00, 0x2E7F,
+ 0x2E9A, 0x2E9A,
+ 0x2EF4, 0x2EFF,
+ 0x2FD6, 0x2FEF,
+ 0x2FFC, 0x2FFF,
+ 0x3040, 0x3040,
+ 0x3097, 0x3098,
+ 0x3100, 0x3104,
+ 0x312D, 0x3130,
+ 0x318F, 0x318F,
+ 0x31B8, 0x31EF,
+ 0x321D, 0x321F,
+ 0x3244, 0x3250,
+ 0x327C, 0x327E,
+ 0x32CC, 0x32CF,
+ 0x32FF, 0x32FF,
+ 0x3377, 0x337A,
+ 0x33DE, 0x33DF,
+ 0x33FF, 0x33FF,
+ 0x4DB6, 0x4DFF,
+ 0x9FA6, 0x9FFF,
+ 0xA48D, 0xA48F,
+ 0xA4C7, 0xABFF,
+ 0xD7A4, 0xD7FF,
+ 0xFA2E, 0xFA2F,
+ 0xFA6B, 0xFAFF,
+ 0xFB07, 0xFB12,
+ 0xFB18, 0xFB1C,
+ 0xFB37, 0xFB37,
+ 0xFB3D, 0xFB3D,
+ 0xFB3F, 0xFB3F,
+ 0xFB42, 0xFB42,
+ 0xFB45, 0xFB45,
+ 0xFBB2, 0xFBD2,
+ 0xFD40, 0xFD4F,
+ 0xFD90, 0xFD91,
+ 0xFDC8, 0xFDCF,
+ 0xFDFD, 0xFDFF,
+ 0xFE10, 0xFE1F,
+ 0xFE24, 0xFE2F,
+ 0xFE47, 0xFE48,
+ 0xFE53, 0xFE53,
+ 0xFE67, 0xFE67,
+ 0xFE6C, 0xFE6F,
+ 0xFE75, 0xFE75,
+ 0xFEFD, 0xFEFE,
+ 0xFF00, 0xFF00,
+ 0xFFBF, 0xFFC1,
+ 0xFFC8, 0xFFC9,
+ 0xFFD0, 0xFFD1,
+ 0xFFD8, 0xFFD9,
+ 0xFFDD, 0xFFDF,
+ 0xFFE7, 0xFFE7,
+ 0xFFEF, 0xFFF8,
+ 0x10000, 0x102FF,
+ 0x1031F, 0x1031F,
+ 0x10324, 0x1032F,
+ 0x1034B, 0x103FF,
+ 0x10426, 0x10427,
+ 0x1044E, 0x1CFFF,
+ 0x1D0F6, 0x1D0FF,
+ 0x1D127, 0x1D129,
+ 0x1D1DE, 0x1D3FF,
+ 0x1D455, 0x1D455,
+ 0x1D49D, 0x1D49D,
+ 0x1D4A0, 0x1D4A1,
+ 0x1D4A3, 0x1D4A4,
+ 0x1D4A7, 0x1D4A8,
+ 0x1D4AD, 0x1D4AD,
+ 0x1D4BA, 0x1D4BA,
+ 0x1D4BC, 0x1D4BC,
+ 0x1D4C1, 0x1D4C1,
+ 0x1D4C4, 0x1D4C4,
+ 0x1D506, 0x1D506,
+ 0x1D50B, 0x1D50C,
+ 0x1D515, 0x1D515,
+ 0x1D51D, 0x1D51D,
+ 0x1D53A, 0x1D53A,
+ 0x1D53F, 0x1D53F,
+ 0x1D545, 0x1D545,
+ 0x1D547, 0x1D549,
+ 0x1D551, 0x1D551,
+ 0x1D6A4, 0x1D6A7,
+ 0x1D7CA, 0x1D7CD,
+ 0x1D800, 0x1FFFD,
+ 0x2A6D7, 0x2F7FF,
+ 0x2FA1E, 0x2FFFD,
+ 0x30000, 0x3FFFD,
+ 0x40000, 0x4FFFD,
+ 0x50000, 0x5FFFD,
+ 0x60000, 0x6FFFD,
+ 0x70000, 0x7FFFD,
+ 0x80000, 0x8FFFD,
+ 0x90000, 0x9FFFD,
+ 0xA0000, 0xAFFFD,
+ 0xB0000, 0xBFFFD,
+ 0xC0000, 0xCFFFD,
+ 0xD0000, 0xDFFFD,
+ 0xE0000, 0xE0000,
+ 0xE0002, 0xE001F,
+ 0xE0080, 0xEFFFD
+};
+
+/* D.1 Characters with bidirectional property "R" or "AL" */
+static const pg_wchar RandALCat_codepoint_ranges[] =
+{
+ 0x05BE, 0x05BE,
+ 0x05C0, 0x05C0,
+ 0x05C3, 0x05C3,
+ 0x05D0, 0x05EA,
+ 0x05F0, 0x05F4,
+ 0x061B, 0x061B,
+ 0x061F, 0x061F,
+ 0x0621, 0x063A,
+ 0x0640, 0x064A,
+ 0x066D, 0x066F,
+ 0x0671, 0x06D5,
+ 0x06DD, 0x06DD,
+ 0x06E5, 0x06E6,
+ 0x06FA, 0x06FE,
+ 0x0700, 0x070D,
+ 0x0710, 0x0710,
+ 0x0712, 0x072C,
+ 0x0780, 0x07A5,
+ 0x07B1, 0x07B1,
+ 0x200F, 0x200F,
+ 0xFB1D, 0xFB1D,
+ 0xFB1F, 0xFB28,
+ 0xFB2A, 0xFB36,
+ 0xFB38, 0xFB3C,
+ 0xFB3E, 0xFB3E,
+ 0xFB40, 0xFB41,
+ 0xFB43, 0xFB44,
+ 0xFB46, 0xFBB1,
+ 0xFBD3, 0xFD3D,
+ 0xFD50, 0xFD8F,
+ 0xFD92, 0xFDC7,
+ 0xFDF0, 0xFDFC,
+ 0xFE70, 0xFE74,
+ 0xFE76, 0xFEFC
+};
+
+/* D.2 Characters with bidirectional property "L" */
+static const pg_wchar LCat_codepoint_ranges[] =
+{
+ 0x0041, 0x005A,
+ 0x0061, 0x007A,
+ 0x00AA, 0x00AA,
+ 0x00B5, 0x00B5,
+ 0x00BA, 0x00BA,
+ 0x00C0, 0x00D6,
+ 0x00D8, 0x00F6,
+ 0x00F8, 0x0220,
+ 0x0222, 0x0233,
+ 0x0250, 0x02AD,
+ 0x02B0, 0x02B8,
+ 0x02BB, 0x02C1,
+ 0x02D0, 0x02D1,
+ 0x02E0, 0x02E4,
+ 0x02EE, 0x02EE,
+ 0x037A, 0x037A,
+ 0x0386, 0x0386,
+ 0x0388, 0x038A,
+ 0x038C, 0x038C,
+ 0x038E, 0x03A1,
+ 0x03A3, 0x03CE,
+ 0x03D0, 0x03F5,
+ 0x0400, 0x0482,
+ 0x048A, 0x04CE,
+ 0x04D0, 0x04F5,
+ 0x04F8, 0x04F9,
+ 0x0500, 0x050F,
+ 0x0531, 0x0556,
+ 0x0559, 0x055F,
+ 0x0561, 0x0587,
+ 0x0589, 0x0589,
+ 0x0903, 0x0903,
+ 0x0905, 0x0939,
+ 0x093D, 0x0940,
+ 0x0949, 0x094C,
+ 0x0950, 0x0950,
+ 0x0958, 0x0961,
+ 0x0964, 0x0970,
+ 0x0982, 0x0983,
+ 0x0985, 0x098C,
+ 0x098F, 0x0990,
+ 0x0993, 0x09A8,
+ 0x09AA, 0x09B0,
+ 0x09B2, 0x09B2,
+ 0x09B6, 0x09B9,
+ 0x09BE, 0x09C0,
+ 0x09C7, 0x09C8,
+ 0x09CB, 0x09CC,
+ 0x09D7, 0x09D7,
+ 0x09DC, 0x09DD,
+ 0x09DF, 0x09E1,
+ 0x09E6, 0x09F1,
+ 0x09F4, 0x09FA,
+ 0x0A05, 0x0A0A,
+ 0x0A0F, 0x0A10,
+ 0x0A13, 0x0A28,
+ 0x0A2A, 0x0A30,
+ 0x0A32, 0x0A33,
+ 0x0A35, 0x0A36,
+ 0x0A38, 0x0A39,
+ 0x0A3E, 0x0A40,
+ 0x0A59, 0x0A5C,
+ 0x0A5E, 0x0A5E,
+ 0x0A66, 0x0A6F,
+ 0x0A72, 0x0A74,
+ 0x0A83, 0x0A83,
+ 0x0A85, 0x0A8B,
+ 0x0A8D, 0x0A8D,
+ 0x0A8F, 0x0A91,
+ 0x0A93, 0x0AA8,
+ 0x0AAA, 0x0AB0,
+ 0x0AB2, 0x0AB3,
+ 0x0AB5, 0x0AB9,
+ 0x0ABD, 0x0AC0,
+ 0x0AC9, 0x0AC9,
+ 0x0ACB, 0x0ACC,
+ 0x0AD0, 0x0AD0,
+ 0x0AE0, 0x0AE0,
+ 0x0AE6, 0x0AEF,
+ 0x0B02, 0x0B03,
+ 0x0B05, 0x0B0C,
+ 0x0B0F, 0x0B10,
+ 0x0B13, 0x0B28,
+ 0x0B2A, 0x0B30,
+ 0x0B32, 0x0B33,
+ 0x0B36, 0x0B39,
+ 0x0B3D, 0x0B3E,
+ 0x0B40, 0x0B40,
+ 0x0B47, 0x0B48,
+ 0x0B4B, 0x0B4C,
+ 0x0B57, 0x0B57,
+ 0x0B5C, 0x0B5D,
+ 0x0B5F, 0x0B61,
+ 0x0B66, 0x0B70,
+ 0x0B83, 0x0B83,
+ 0x0B85, 0x0B8A,
+ 0x0B8E, 0x0B90,
+ 0x0B92, 0x0B95,
+ 0x0B99, 0x0B9A,
+ 0x0B9C, 0x0B9C,
+ 0x0B9E, 0x0B9F,
+ 0x0BA3, 0x0BA4,
+ 0x0BA8, 0x0BAA,
+ 0x0BAE, 0x0BB5,
+ 0x0BB7, 0x0BB9,
+ 0x0BBE, 0x0BBF,
+ 0x0BC1, 0x0BC2,
+ 0x0BC6, 0x0BC8,
+ 0x0BCA, 0x0BCC,
+ 0x0BD7, 0x0BD7,
+ 0x0BE7, 0x0BF2,
+ 0x0C01, 0x0C03,
+ 0x0C05, 0x0C0C,
+ 0x0C0E, 0x0C10,
+ 0x0C12, 0x0C28,
+ 0x0C2A, 0x0C33,
+ 0x0C35, 0x0C39,
+ 0x0C41, 0x0C44,
+ 0x0C60, 0x0C61,
+ 0x0C66, 0x0C6F,
+ 0x0C82, 0x0C83,
+ 0x0C85, 0x0C8C,
+ 0x0C8E, 0x0C90,
+ 0x0C92, 0x0CA8,
+ 0x0CAA, 0x0CB3,
+ 0x0CB5, 0x0CB9,
+ 0x0CBE, 0x0CBE,
+ 0x0CC0, 0x0CC4,
+ 0x0CC7, 0x0CC8,
+ 0x0CCA, 0x0CCB,
+ 0x0CD5, 0x0CD6,
+ 0x0CDE, 0x0CDE,
+ 0x0CE0, 0x0CE1,
+ 0x0CE6, 0x0CEF,
+ 0x0D02, 0x0D03,
+ 0x0D05, 0x0D0C,
+ 0x0D0E, 0x0D10,
+ 0x0D12, 0x0D28,
+ 0x0D2A, 0x0D39,
+ 0x0D3E, 0x0D40,
+ 0x0D46, 0x0D48,
+ 0x0D4A, 0x0D4C,
+ 0x0D57, 0x0D57,
+ 0x0D60, 0x0D61,
+ 0x0D66, 0x0D6F,
+ 0x0D82, 0x0D83,
+ 0x0D85, 0x0D96,
+ 0x0D9A, 0x0DB1,
+ 0x0DB3, 0x0DBB,
+ 0x0DBD, 0x0DBD,
+ 0x0DC0, 0x0DC6,
+ 0x0DCF, 0x0DD1,
+ 0x0DD8, 0x0DDF,
+ 0x0DF2, 0x0DF4,
+ 0x0E01, 0x0E30,
+ 0x0E32, 0x0E33,
+ 0x0E40, 0x0E46,
+ 0x0E4F, 0x0E5B,
+ 0x0E81, 0x0E82,
+ 0x0E84, 0x0E84,
+ 0x0E87, 0x0E88,
+ 0x0E8A, 0x0E8A,
+ 0x0E8D, 0x0E8D,
+ 0x0E94, 0x0E97,
+ 0x0E99, 0x0E9F,
+ 0x0EA1, 0x0EA3,
+ 0x0EA5, 0x0EA5,
+ 0x0EA7, 0x0EA7,
+ 0x0EAA, 0x0EAB,
+ 0x0EAD, 0x0EB0,
+ 0x0EB2, 0x0EB3,
+ 0x0EBD, 0x0EBD,
+ 0x0EC0, 0x0EC4,
+ 0x0EC6, 0x0EC6,
+ 0x0ED0, 0x0ED9,
+ 0x0EDC, 0x0EDD,
+ 0x0F00, 0x0F17,
+ 0x0F1A, 0x0F34,
+ 0x0F36, 0x0F36,
+ 0x0F38, 0x0F38,
+ 0x0F3E, 0x0F47,
+ 0x0F49, 0x0F6A,
+ 0x0F7F, 0x0F7F,
+ 0x0F85, 0x0F85,
+ 0x0F88, 0x0F8B,
+ 0x0FBE, 0x0FC5,
+ 0x0FC7, 0x0FCC,
+ 0x0FCF, 0x0FCF,
+ 0x1000, 0x1021,
+ 0x1023, 0x1027,
+ 0x1029, 0x102A,
+ 0x102C, 0x102C,
+ 0x1031, 0x1031,
+ 0x1038, 0x1038,
+ 0x1040, 0x1057,
+ 0x10A0, 0x10C5,
+ 0x10D0, 0x10F8,
+ 0x10FB, 0x10FB,
+ 0x1100, 0x1159,
+ 0x115F, 0x11A2,
+ 0x11A8, 0x11F9,
+ 0x1200, 0x1206,
+ 0x1208, 0x1246,
+ 0x1248, 0x1248,
+ 0x124A, 0x124D,
+ 0x1250, 0x1256,
+ 0x1258, 0x1258,
+ 0x125A, 0x125D,
+ 0x1260, 0x1286,
+ 0x1288, 0x1288,
+ 0x128A, 0x128D,
+ 0x1290, 0x12AE,
+ 0x12B0, 0x12B0,
+ 0x12B2, 0x12B5,
+ 0x12B8, 0x12BE,
+ 0x12C0, 0x12C0,
+ 0x12C2, 0x12C5,
+ 0x12C8, 0x12CE,
+ 0x12D0, 0x12D6,
+ 0x12D8, 0x12EE,
+ 0x12F0, 0x130E,
+ 0x1310, 0x1310,
+ 0x1312, 0x1315,
+ 0x1318, 0x131E,
+ 0x1320, 0x1346,
+ 0x1348, 0x135A,
+ 0x1361, 0x137C,
+ 0x13A0, 0x13F4,
+ 0x1401, 0x1676,
+ 0x1681, 0x169A,
+ 0x16A0, 0x16F0,
+ 0x1700, 0x170C,
+ 0x170E, 0x1711,
+ 0x1720, 0x1731,
+ 0x1735, 0x1736,
+ 0x1740, 0x1751,
+ 0x1760, 0x176C,
+ 0x176E, 0x1770,
+ 0x1780, 0x17B6,
+ 0x17BE, 0x17C5,
+ 0x17C7, 0x17C8,
+ 0x17D4, 0x17DA,
+ 0x17DC, 0x17DC,
+ 0x17E0, 0x17E9,
+ 0x1810, 0x1819,
+ 0x1820, 0x1877,
+ 0x1880, 0x18A8,
+ 0x1E00, 0x1E9B,
+ 0x1EA0, 0x1EF9,
+ 0x1F00, 0x1F15,
+ 0x1F18, 0x1F1D,
+ 0x1F20, 0x1F45,
+ 0x1F48, 0x1F4D,
+ 0x1F50, 0x1F57,
+ 0x1F59, 0x1F59,
+ 0x1F5B, 0x1F5B,
+ 0x1F5D, 0x1F5D,
+ 0x1F5F, 0x1F7D,
+ 0x1F80, 0x1FB4,
+ 0x1FB6, 0x1FBC,
+ 0x1FBE, 0x1FBE,
+ 0x1FC2, 0x1FC4,
+ 0x1FC6, 0x1FCC,
+ 0x1FD0, 0x1FD3,
+ 0x1FD6, 0x1FDB,
+ 0x1FE0, 0x1FEC,
+ 0x1FF2, 0x1FF4,
+ 0x1FF6, 0x1FFC,
+ 0x200E, 0x200E,
+ 0x2071, 0x2071,
+ 0x207F, 0x207F,
+ 0x2102, 0x2102,
+ 0x2107, 0x2107,
+ 0x210A, 0x2113,
+ 0x2115, 0x2115,
+ 0x2119, 0x211D,
+ 0x2124, 0x2124,
+ 0x2126, 0x2126,
+ 0x2128, 0x2128,
+ 0x212A, 0x212D,
+ 0x212F, 0x2131,
+ 0x2133, 0x2139,
+ 0x213D, 0x213F,
+ 0x2145, 0x2149,
+ 0x2160, 0x2183,
+ 0x2336, 0x237A,
+ 0x2395, 0x2395,
+ 0x249C, 0x24E9,
+ 0x3005, 0x3007,
+ 0x3021, 0x3029,
+ 0x3031, 0x3035,
+ 0x3038, 0x303C,
+ 0x3041, 0x3096,
+ 0x309D, 0x309F,
+ 0x30A1, 0x30FA,
+ 0x30FC, 0x30FF,
+ 0x3105, 0x312C,
+ 0x3131, 0x318E,
+ 0x3190, 0x31B7,
+ 0x31F0, 0x321C,
+ 0x3220, 0x3243,
+ 0x3260, 0x327B,
+ 0x327F, 0x32B0,
+ 0x32C0, 0x32CB,
+ 0x32D0, 0x32FE,
+ 0x3300, 0x3376,
+ 0x337B, 0x33DD,
+ 0x33E0, 0x33FE,
+ 0x3400, 0x4DB5,
+ 0x4E00, 0x9FA5,
+ 0xA000, 0xA48C,
+ 0xAC00, 0xD7A3,
+ 0xD800, 0xFA2D,
+ 0xFA30, 0xFA6A,
+ 0xFB00, 0xFB06,
+ 0xFB13, 0xFB17,
+ 0xFF21, 0xFF3A,
+ 0xFF41, 0xFF5A,
+ 0xFF66, 0xFFBE,
+ 0xFFC2, 0xFFC7,
+ 0xFFCA, 0xFFCF,
+ 0xFFD2, 0xFFD7,
+ 0xFFDA, 0xFFDC,
+ 0x10300, 0x1031E,
+ 0x10320, 0x10323,
+ 0x10330, 0x1034A,
+ 0x10400, 0x10425,
+ 0x10428, 0x1044D,
+ 0x1D000, 0x1D0F5,
+ 0x1D100, 0x1D126,
+ 0x1D12A, 0x1D166,
+ 0x1D16A, 0x1D172,
+ 0x1D183, 0x1D184,
+ 0x1D18C, 0x1D1A9,
+ 0x1D1AE, 0x1D1DD,
+ 0x1D400, 0x1D454,
+ 0x1D456, 0x1D49C,
+ 0x1D49E, 0x1D49F,
+ 0x1D4A2, 0x1D4A2,
+ 0x1D4A5, 0x1D4A6,
+ 0x1D4A9, 0x1D4AC,
+ 0x1D4AE, 0x1D4B9,
+ 0x1D4BB, 0x1D4BB,
+ 0x1D4BD, 0x1D4C0,
+ 0x1D4C2, 0x1D4C3,
+ 0x1D4C5, 0x1D505,
+ 0x1D507, 0x1D50A,
+ 0x1D50D, 0x1D514,
+ 0x1D516, 0x1D51C,
+ 0x1D51E, 0x1D539,
+ 0x1D53B, 0x1D53E,
+ 0x1D540, 0x1D544,
+ 0x1D546, 0x1D546,
+ 0x1D54A, 0x1D550,
+ 0x1D552, 0x1D6A3,
+ 0x1D6A8, 0x1D7C9,
+ 0x20000, 0x2A6D6,
+ 0x2F800, 0x2FA1D,
+ 0xF0000, 0xFFFFD,
+ 0x100000, 0x10FFFD
+};
+
+/* End of stringprep tables */
+
+
+/* Is the given Unicode codepoint in the given table of ranges? */
+#define IS_CODE_IN_TABLE(code, map) is_code_in_table(code, map, lengthof(map))
+
+static int
+codepoint_range_cmp(const void *a, const void *b)
+{
+ const pg_wchar *key = (const pg_wchar *) a;
+ const pg_wchar *range = (const pg_wchar *) b;
+
+ if (*key < range[0])
+ return -1; /* less than lower bound */
+ if (*key > range[1])
+ return 1; /* greater than upper bound */
+
+ return 0; /* within range */
+}
+
+static bool
+is_code_in_table(pg_wchar code, const pg_wchar *map, int mapsize)
+{
+ Assert(mapsize % 2 == 0);
+
+ if (code < map[0] || code > map[mapsize - 1])
+ return false;
+
+ if (bsearch(&code, map, mapsize / 2, sizeof(pg_wchar) * 2,
+ codepoint_range_cmp))
+ return true;
+ else
+ return false;
+}
+
+/*
+ * Calculate the length in characters of a null-terminated UTF-8 string.
+ *
+ * Returns -1 if the input is not valid UTF-8.
+ */
+static int
+pg_utf8_string_len(const char *source)
+{
+ const unsigned char *p = (const unsigned char *) source;
+ int l;
+ int num_chars = 0;
+
+ while (*p)
+ {
+ l = pg_utf_mblen(p);
+
+ if (!pg_utf8_islegal(p, l))
+ return -1;
+
+ p += l;
+ num_chars++;
+ }
+
+ return num_chars;
+}
+
+
+/*
+ * pg_saslprep - Normalize a password with SASLprep.
+ *
+ * SASLprep requires the input to be in UTF-8 encoding, but PostgreSQL
+ * supports many encodings, so we don't blindly assume that. pg_saslprep
+ * will check if the input looks like valid UTF-8, and returns
+ * SASLPREP_INVALID_UTF8 if not.
+ *
+ * If the string contains prohibited characters (or more precisely, if the
+ * output string would contain prohibited characters after normalization),
+ * returns SASLPREP_PROHIBITED.
+ *
+ * On success, returns SASLPREP_SUCCESS, and the normalized string in
+ * *output.
+ *
+ * In frontend, the normalized string is malloc'd, and the caller is
+ * responsible for freeing it. If an allocation fails, returns
+ * SASLPREP_OOM. In backend, the normalized string is palloc'd instead,
+ * and a failed allocation leads to ereport(ERROR).
+ */
+pg_saslprep_rc
+pg_saslprep(const char *input, char **output)
+{
+ pg_wchar *input_chars = NULL;
+ pg_wchar *output_chars = NULL;
+ int input_size;
+ char *result;
+ int result_size;
+ int count;
+ int i;
+ bool contains_RandALCat;
+ unsigned char *p;
+ pg_wchar *wp;
+
+ /* Ensure we return *output as NULL on failure */
+ *output = NULL;
+
+ /*
+ * Quick check if the input is pure ASCII. An ASCII string requires no
+ * further processing.
+ */
+ if (pg_is_ascii(input))
+ {
+ *output = STRDUP(input);
+ if (!(*output))
+ goto oom;
+ return SASLPREP_SUCCESS;
+ }
+
+ /*
+ * Convert the input from UTF-8 to an array of Unicode codepoints.
+ *
+ * This also checks that the input is a legal UTF-8 string.
+ */
+ input_size = pg_utf8_string_len(input);
+ if (input_size < 0)
+ return SASLPREP_INVALID_UTF8;
+
+ input_chars = ALLOC((input_size + 1) * sizeof(pg_wchar));
+ if (!input_chars)
+ goto oom;
+
+ p = (unsigned char *) input;
+ for (i = 0; i < input_size; i++)
+ {
+ input_chars[i] = utf8_to_unicode(p);
+ p += pg_utf_mblen(p);
+ }
+ input_chars[i] = (pg_wchar) '\0';
+
+ /*
+ * The steps below correspond to the steps listed in [RFC3454], Section
+ * "2. Preparation Overview"
+ */
+
+ /*
+ * 1) Map -- For each character in the input, check if it has a mapping
+ * and, if so, replace it with its mapping.
+ */
+ count = 0;
+ for (i = 0; i < input_size; i++)
+ {
+ pg_wchar code = input_chars[i];
+
+ if (IS_CODE_IN_TABLE(code, non_ascii_space_ranges))
+ input_chars[count++] = 0x0020;
+ else if (IS_CODE_IN_TABLE(code, commonly_mapped_to_nothing_ranges))
+ {
+ /* map to nothing */
+ }
+ else
+ input_chars[count++] = code;
+ }
+ input_chars[count] = (pg_wchar) '\0';
+ input_size = count;
+
+ if (input_size == 0)
+ goto prohibited; /* don't allow empty password */
+
+ /*
+ * 2) Normalize -- Normalize the result of step 1 using Unicode
+ * normalization.
+ */
+ output_chars = unicode_normalize(UNICODE_NFKC, input_chars);
+ if (!output_chars)
+ goto oom;
+
+ /*
+ * 3) Prohibit -- Check for any characters that are not allowed in the
+ * output. If any are found, return an error.
+ */
+ for (i = 0; i < input_size; i++)
+ {
+ pg_wchar code = input_chars[i];
+
+ if (IS_CODE_IN_TABLE(code, prohibited_output_ranges))
+ goto prohibited;
+ if (IS_CODE_IN_TABLE(code, unassigned_codepoint_ranges))
+ goto prohibited;
+ }
+
+ /*
+ * 4) Check bidi -- Possibly check for right-to-left characters, and if
+ * any are found, make sure that the whole string satisfies the
+ * requirements for bidirectional strings. If the string does not satisfy
+ * the requirements for bidirectional strings, return an error.
+ *
+ * [RFC3454], Section "6. Bidirectional Characters" explains in more
+ * detail what that means:
+ *
+ * "In any profile that specifies bidirectional character handling, all
+ * three of the following requirements MUST be met:
+ *
+ * 1) The characters in section 5.8 MUST be prohibited.
+ *
+ * 2) If a string contains any RandALCat character, the string MUST NOT
+ * contain any LCat character.
+ *
+ * 3) If a string contains any RandALCat character, a RandALCat character
+ * MUST be the first character of the string, and a RandALCat character
+ * MUST be the last character of the string."
+ */
+ contains_RandALCat = false;
+ for (i = 0; i < input_size; i++)
+ {
+ pg_wchar code = input_chars[i];
+
+ if (IS_CODE_IN_TABLE(code, RandALCat_codepoint_ranges))
+ {
+ contains_RandALCat = true;
+ break;
+ }
+ }
+
+ if (contains_RandALCat)
+ {
+ pg_wchar first = input_chars[0];
+ pg_wchar last = input_chars[input_size - 1];
+
+ for (i = 0; i < input_size; i++)
+ {
+ pg_wchar code = input_chars[i];
+
+ if (IS_CODE_IN_TABLE(code, LCat_codepoint_ranges))
+ goto prohibited;
+ }
+
+ if (!IS_CODE_IN_TABLE(first, RandALCat_codepoint_ranges) ||
+ !IS_CODE_IN_TABLE(last, RandALCat_codepoint_ranges))
+ goto prohibited;
+ }
+
+ /*
+ * Finally, convert the result back to UTF-8.
+ */
+ result_size = 0;
+ for (wp = output_chars; *wp; wp++)
+ {
+ unsigned char buf[4];
+
+ unicode_to_utf8(*wp, buf);
+ result_size += pg_utf_mblen(buf);
+ }
+
+ result = ALLOC(result_size + 1);
+ if (!result)
+ goto oom;
+
+ /*
+ * There are no error exits below here, so the error exit paths don't need
+ * to worry about possibly freeing "result".
+ */
+ p = (unsigned char *) result;
+ for (wp = output_chars; *wp; wp++)
+ {
+ unicode_to_utf8(*wp, p);
+ p += pg_utf_mblen(p);
+ }
+ Assert((char *) p == result + result_size);
+ *p = '\0';
+
+ FREE(input_chars);
+ FREE(output_chars);
+
+ *output = result;
+ return SASLPREP_SUCCESS;
+
+prohibited:
+ if (input_chars)
+ FREE(input_chars);
+ if (output_chars)
+ FREE(output_chars);
+
+ return SASLPREP_PROHIBITED;
+
+oom:
+ if (input_chars)
+ FREE(input_chars);
+ if (output_chars)
+ FREE(output_chars);
+
+ return SASLPREP_OOM;
+}
diff --git a/contrib/libs/libpq/src/common/scram-common.c b/contrib/libs/libpq/src/common/scram-common.c
new file mode 100644
index 0000000000..ef997ef684
--- /dev/null
+++ b/contrib/libs/libpq/src/common/scram-common.c
@@ -0,0 +1,319 @@
+/*-------------------------------------------------------------------------
+ * scram-common.c
+ * Shared frontend/backend code for SCRAM authentication
+ *
+ * This contains the common low-level functions needed in both frontend and
+ * backend, for implement the Salted Challenge Response Authentication
+ * Mechanism (SCRAM), per IETF's RFC 5802.
+ *
+ * Portions Copyright (c) 2017-2023, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/common/scram-common.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#include "common/base64.h"
+#include "common/hmac.h"
+#include "common/scram-common.h"
+#include "port/pg_bswap.h"
+
+/*
+ * Calculate SaltedPassword.
+ *
+ * The password should already be normalized by SASLprep. Returns 0 on
+ * success, -1 on failure with *errstr pointing to a message about the
+ * error details.
+ */
+int
+scram_SaltedPassword(const char *password,
+ pg_cryptohash_type hash_type, int key_length,
+ const char *salt, int saltlen, int iterations,
+ uint8 *result, const char **errstr)
+{
+ int password_len = strlen(password);
+ uint32 one = pg_hton32(1);
+ int i,
+ j;
+ uint8 Ui[SCRAM_MAX_KEY_LEN];
+ uint8 Ui_prev[SCRAM_MAX_KEY_LEN];
+ pg_hmac_ctx *hmac_ctx = pg_hmac_create(hash_type);
+
+ if (hmac_ctx == NULL)
+ {
+ *errstr = pg_hmac_error(NULL); /* returns OOM */
+ return -1;
+ }
+
+ /*
+ * Iterate hash calculation of HMAC entry using given salt. This is
+ * essentially PBKDF2 (see RFC2898) with HMAC() as the pseudorandom
+ * function.
+ */
+
+ /* First iteration */
+ if (pg_hmac_init(hmac_ctx, (uint8 *) password, password_len) < 0 ||
+ pg_hmac_update(hmac_ctx, (uint8 *) salt, saltlen) < 0 ||
+ pg_hmac_update(hmac_ctx, (uint8 *) &one, sizeof(uint32)) < 0 ||
+ pg_hmac_final(hmac_ctx, Ui_prev, key_length) < 0)
+ {
+ *errstr = pg_hmac_error(hmac_ctx);
+ pg_hmac_free(hmac_ctx);
+ return -1;
+ }
+
+ memcpy(result, Ui_prev, key_length);
+
+ /* Subsequent iterations */
+ for (i = 2; i <= iterations; i++)
+ {
+ if (pg_hmac_init(hmac_ctx, (uint8 *) password, password_len) < 0 ||
+ pg_hmac_update(hmac_ctx, (uint8 *) Ui_prev, key_length) < 0 ||
+ pg_hmac_final(hmac_ctx, Ui, key_length) < 0)
+ {
+ *errstr = pg_hmac_error(hmac_ctx);
+ pg_hmac_free(hmac_ctx);
+ return -1;
+ }
+
+ for (j = 0; j < key_length; j++)
+ result[j] ^= Ui[j];
+ memcpy(Ui_prev, Ui, key_length);
+ }
+
+ pg_hmac_free(hmac_ctx);
+ return 0;
+}
+
+
+/*
+ * Calculate hash for a NULL-terminated string. (The NULL terminator is
+ * not included in the hash). Returns 0 on success, -1 on failure with *errstr
+ * pointing to a message about the error details.
+ */
+int
+scram_H(const uint8 *input, pg_cryptohash_type hash_type, int key_length,
+ uint8 *result, const char **errstr)
+{
+ pg_cryptohash_ctx *ctx;
+
+ ctx = pg_cryptohash_create(hash_type);
+ if (ctx == NULL)
+ {
+ *errstr = pg_cryptohash_error(NULL); /* returns OOM */
+ return -1;
+ }
+
+ if (pg_cryptohash_init(ctx) < 0 ||
+ pg_cryptohash_update(ctx, input, key_length) < 0 ||
+ pg_cryptohash_final(ctx, result, key_length) < 0)
+ {
+ *errstr = pg_cryptohash_error(ctx);
+ pg_cryptohash_free(ctx);
+ return -1;
+ }
+
+ pg_cryptohash_free(ctx);
+ return 0;
+}
+
+/*
+ * Calculate ClientKey. Returns 0 on success, -1 on failure with *errstr
+ * pointing to a message about the error details.
+ */
+int
+scram_ClientKey(const uint8 *salted_password,
+ pg_cryptohash_type hash_type, int key_length,
+ uint8 *result, const char **errstr)
+{
+ pg_hmac_ctx *ctx = pg_hmac_create(hash_type);
+
+ if (ctx == NULL)
+ {
+ *errstr = pg_hmac_error(NULL); /* returns OOM */
+ return -1;
+ }
+
+ if (pg_hmac_init(ctx, salted_password, key_length) < 0 ||
+ pg_hmac_update(ctx, (uint8 *) "Client Key", strlen("Client Key")) < 0 ||
+ pg_hmac_final(ctx, result, key_length) < 0)
+ {
+ *errstr = pg_hmac_error(ctx);
+ pg_hmac_free(ctx);
+ return -1;
+ }
+
+ pg_hmac_free(ctx);
+ return 0;
+}
+
+/*
+ * Calculate ServerKey. Returns 0 on success, -1 on failure with *errstr
+ * pointing to a message about the error details.
+ */
+int
+scram_ServerKey(const uint8 *salted_password,
+ pg_cryptohash_type hash_type, int key_length,
+ uint8 *result, const char **errstr)
+{
+ pg_hmac_ctx *ctx = pg_hmac_create(hash_type);
+
+ if (ctx == NULL)
+ {
+ *errstr = pg_hmac_error(NULL); /* returns OOM */
+ return -1;
+ }
+
+ if (pg_hmac_init(ctx, salted_password, key_length) < 0 ||
+ pg_hmac_update(ctx, (uint8 *) "Server Key", strlen("Server Key")) < 0 ||
+ pg_hmac_final(ctx, result, key_length) < 0)
+ {
+ *errstr = pg_hmac_error(ctx);
+ pg_hmac_free(ctx);
+ return -1;
+ }
+
+ pg_hmac_free(ctx);
+ return 0;
+}
+
+
+/*
+ * Construct a SCRAM secret, for storing in pg_authid.rolpassword.
+ *
+ * The password should already have been processed with SASLprep, if necessary!
+ *
+ * If iterations is 0, default number of iterations is used. The result is
+ * palloc'd or malloc'd, so caller is responsible for freeing it.
+ *
+ * On error, returns NULL and sets *errstr to point to a message about the
+ * error details.
+ */
+char *
+scram_build_secret(pg_cryptohash_type hash_type, int key_length,
+ const char *salt, int saltlen, int iterations,
+ const char *password, const char **errstr)
+{
+ uint8 salted_password[SCRAM_MAX_KEY_LEN];
+ uint8 stored_key[SCRAM_MAX_KEY_LEN];
+ uint8 server_key[SCRAM_MAX_KEY_LEN];
+ char *result;
+ char *p;
+ int maxlen;
+ int encoded_salt_len;
+ int encoded_stored_len;
+ int encoded_server_len;
+ int encoded_result;
+
+ /* Only this hash method is supported currently */
+ Assert(hash_type == PG_SHA256);
+
+ Assert(iterations > 0);
+
+ /* Calculate StoredKey and ServerKey */
+ if (scram_SaltedPassword(password, hash_type, key_length,
+ salt, saltlen, iterations,
+ salted_password, errstr) < 0 ||
+ scram_ClientKey(salted_password, hash_type, key_length,
+ stored_key, errstr) < 0 ||
+ scram_H(stored_key, hash_type, key_length,
+ stored_key, errstr) < 0 ||
+ scram_ServerKey(salted_password, hash_type, key_length,
+ server_key, errstr) < 0)
+ {
+ /* errstr is filled already here */
+#ifdef FRONTEND
+ return NULL;
+#else
+ elog(ERROR, "could not calculate stored key and server key: %s",
+ *errstr);
+#endif
+ }
+
+ /*----------
+ * The format is:
+ * SCRAM-SHA-256$<iteration count>:<salt>$<StoredKey>:<ServerKey>
+ *----------
+ */
+ encoded_salt_len = pg_b64_enc_len(saltlen);
+ encoded_stored_len = pg_b64_enc_len(key_length);
+ encoded_server_len = pg_b64_enc_len(key_length);
+
+ maxlen = strlen("SCRAM-SHA-256") + 1
+ + 10 + 1 /* iteration count */
+ + encoded_salt_len + 1 /* Base64-encoded salt */
+ + encoded_stored_len + 1 /* Base64-encoded StoredKey */
+ + encoded_server_len + 1; /* Base64-encoded ServerKey */
+
+#ifdef FRONTEND
+ result = malloc(maxlen);
+ if (!result)
+ {
+ *errstr = _("out of memory");
+ return NULL;
+ }
+#else
+ result = palloc(maxlen);
+#endif
+
+ p = result + sprintf(result, "SCRAM-SHA-256$%d:", iterations);
+
+ /* salt */
+ encoded_result = pg_b64_encode(salt, saltlen, p, encoded_salt_len);
+ if (encoded_result < 0)
+ {
+ *errstr = _("could not encode salt");
+#ifdef FRONTEND
+ free(result);
+ return NULL;
+#else
+ elog(ERROR, "%s", *errstr);
+#endif
+ }
+ p += encoded_result;
+ *(p++) = '$';
+
+ /* stored key */
+ encoded_result = pg_b64_encode((char *) stored_key, key_length, p,
+ encoded_stored_len);
+ if (encoded_result < 0)
+ {
+ *errstr = _("could not encode stored key");
+#ifdef FRONTEND
+ free(result);
+ return NULL;
+#else
+ elog(ERROR, "%s", *errstr);
+#endif
+ }
+
+ p += encoded_result;
+ *(p++) = ':';
+
+ /* server key */
+ encoded_result = pg_b64_encode((char *) server_key, key_length, p,
+ encoded_server_len);
+ if (encoded_result < 0)
+ {
+ *errstr = _("could not encode server key");
+#ifdef FRONTEND
+ free(result);
+ return NULL;
+#else
+ elog(ERROR, "%s", *errstr);
+#endif
+ }
+
+ p += encoded_result;
+ *(p++) = '\0';
+
+ Assert(p - result <= maxlen);
+
+ return result;
+}
diff --git a/contrib/libs/libpq/src/common/sprompt.c b/contrib/libs/libpq/src/common/sprompt.c
new file mode 100644
index 0000000000..201c831746
--- /dev/null
+++ b/contrib/libs/libpq/src/common/sprompt.c
@@ -0,0 +1,181 @@
+/*-------------------------------------------------------------------------
+ *
+ * sprompt.c
+ * simple_prompt() routine
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/common/sprompt.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "c.h"
+
+#include "common/fe_memutils.h"
+#include "common/string.h"
+
+#ifdef HAVE_TERMIOS_H
+#include <termios.h>
+#endif
+
+
+/*
+ * simple_prompt
+ *
+ * Generalized function especially intended for reading in usernames and
+ * passwords interactively. Reads from /dev/tty or stdin/stderr.
+ *
+ * prompt: The prompt to print, or NULL if none (automatically localized)
+ * echo: Set to false if you want to hide what is entered (for passwords)
+ *
+ * The input (without trailing newline) is returned as a malloc'd string.
+ * Caller is responsible for freeing it when done.
+ */
+char *
+simple_prompt(const char *prompt, bool echo)
+{
+ return simple_prompt_extended(prompt, echo, NULL);
+}
+
+/*
+ * simple_prompt_extended
+ *
+ * This is the same as simple_prompt(), except that prompt_ctx can
+ * optionally be provided to allow this function to be canceled via an
+ * existing SIGINT signal handler that will longjmp to the specified place
+ * only when *(prompt_ctx->enabled) is true. If canceled, this function
+ * returns an empty string, and prompt_ctx->canceled is set to true.
+ */
+char *
+simple_prompt_extended(const char *prompt, bool echo,
+ PromptInterruptContext *prompt_ctx)
+{
+ char *result;
+ FILE *termin,
+ *termout;
+#if defined(HAVE_TERMIOS_H)
+ struct termios t_orig,
+ t;
+#elif defined(WIN32)
+ HANDLE t = NULL;
+ DWORD t_orig = 0;
+#endif
+
+#ifdef WIN32
+
+ /*
+ * A Windows console has an "input code page" and an "output code page";
+ * these usually match each other, but they rarely match the "Windows ANSI
+ * code page" defined at system boot and expected of "char *" arguments to
+ * Windows API functions. The Microsoft CRT write() implementation
+ * automatically converts text between these code pages when writing to a
+ * console. To identify such file descriptors, it calls GetConsoleMode()
+ * on the underlying HANDLE, which in turn requires GENERIC_READ access on
+ * the HANDLE. Opening termout in mode "w+" allows that detection to
+ * succeed. Otherwise, write() would not recognize the descriptor as a
+ * console, and non-ASCII characters would display incorrectly.
+ *
+ * XXX fgets() still receives text in the console's input code page. This
+ * makes non-ASCII credentials unportable.
+ *
+ * Unintuitively, we also open termin in mode "w+", even though we only
+ * read it; that's needed for SetConsoleMode() to succeed.
+ */
+ termin = fopen("CONIN$", "w+");
+ termout = fopen("CONOUT$", "w+");
+#else
+
+ /*
+ * Do not try to collapse these into one "w+" mode file. Doesn't work on
+ * some platforms (eg, HPUX 10.20).
+ */
+ termin = fopen("/dev/tty", "r");
+ termout = fopen("/dev/tty", "w");
+#endif
+ if (!termin || !termout
+#ifdef WIN32
+
+ /*
+ * Direct console I/O does not work from the MSYS 1.0.10 console. Writes
+ * reach nowhere user-visible; reads block indefinitely. XXX This affects
+ * most Windows terminal environments, including rxvt, mintty, Cygwin
+ * xterm, Cygwin sshd, and PowerShell ISE. Switch to a more-generic test.
+ */
+ || (getenv("OSTYPE") && strcmp(getenv("OSTYPE"), "msys") == 0)
+#endif
+ )
+ {
+ if (termin)
+ fclose(termin);
+ if (termout)
+ fclose(termout);
+ termin = stdin;
+ termout = stderr;
+ }
+
+ if (!echo)
+ {
+#if defined(HAVE_TERMIOS_H)
+ /* disable echo via tcgetattr/tcsetattr */
+ tcgetattr(fileno(termin), &t);
+ t_orig = t;
+ t.c_lflag &= ~ECHO;
+ tcsetattr(fileno(termin), TCSAFLUSH, &t);
+#elif defined(WIN32)
+ /* need the file's HANDLE to turn echo off */
+ t = (HANDLE) _get_osfhandle(_fileno(termin));
+
+ /* save the old configuration first */
+ GetConsoleMode(t, &t_orig);
+
+ /* set to the new mode */
+ SetConsoleMode(t, ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT);
+#endif
+ }
+
+ if (prompt)
+ {
+ fputs(_(prompt), termout);
+ fflush(termout);
+ }
+
+ result = pg_get_line(termin, prompt_ctx);
+
+ /* If we failed to read anything, just return an empty string */
+ if (result == NULL)
+ result = pg_strdup("");
+
+ /* strip trailing newline, including \r in case we're on Windows */
+ (void) pg_strip_crlf(result);
+
+ if (!echo)
+ {
+ /* restore previous echo behavior, then echo \n */
+#if defined(HAVE_TERMIOS_H)
+ tcsetattr(fileno(termin), TCSAFLUSH, &t_orig);
+ fputs("\n", termout);
+ fflush(termout);
+#elif defined(WIN32)
+ SetConsoleMode(t, t_orig);
+ fputs("\n", termout);
+ fflush(termout);
+#endif
+ }
+ else if (prompt_ctx && prompt_ctx->canceled)
+ {
+ /* also echo \n if prompt was canceled */
+ fputs("\n", termout);
+ fflush(termout);
+ }
+
+ if (termin != stdin)
+ {
+ fclose(termin);
+ fclose(termout);
+ }
+
+ return result;
+}
diff --git a/contrib/libs/libpq/src/common/string.c b/contrib/libs/libpq/src/common/string.c
new file mode 100644
index 0000000000..de97413635
--- /dev/null
+++ b/contrib/libs/libpq/src/common/string.c
@@ -0,0 +1,164 @@
+/*-------------------------------------------------------------------------
+ *
+ * string.c
+ * string handling helpers
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/common/string.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#include "common/string.h"
+#include "lib/stringinfo.h"
+
+
+/*
+ * Returns whether the string `str' has the postfix `end'.
+ */
+bool
+pg_str_endswith(const char *str, const char *end)
+{
+ size_t slen = strlen(str);
+ size_t elen = strlen(end);
+
+ /* can't be a postfix if longer */
+ if (elen > slen)
+ return false;
+
+ /* compare the end of the strings */
+ str += slen - elen;
+ return strcmp(str, end) == 0;
+}
+
+
+/*
+ * strtoint --- just like strtol, but returns int not long
+ */
+int
+strtoint(const char *pg_restrict str, char **pg_restrict endptr, int base)
+{
+ long val;
+
+ val = strtol(str, endptr, base);
+ if (val != (int) val)
+ errno = ERANGE;
+ return (int) val;
+}
+
+
+/*
+ * pg_clean_ascii -- Replace any non-ASCII chars with a "\xXX" string
+ *
+ * Makes a newly allocated copy of the string passed in, which must be
+ * '\0'-terminated. In the backend, additional alloc_flags may be provided and
+ * will be passed as-is to palloc_extended(); in the frontend, alloc_flags is
+ * ignored and the copy is malloc'd.
+ *
+ * This function exists specifically to deal with filtering out
+ * non-ASCII characters in a few places where the client can provide an almost
+ * arbitrary string (and it isn't checked to ensure it's a valid username or
+ * database name or similar) and we don't want to have control characters or other
+ * things ending up in the log file where server admins might end up with a
+ * messed up terminal when looking at them.
+ *
+ * In general, this function should NOT be used- instead, consider how to handle
+ * the string without needing to filter out the non-ASCII characters.
+ *
+ * Ultimately, we'd like to improve the situation to not require replacing all
+ * non-ASCII but perform more intelligent filtering which would allow UTF or
+ * similar, but it's unclear exactly what we should allow, so stick to ASCII only
+ * for now.
+ */
+char *
+pg_clean_ascii(const char *str, int alloc_flags)
+{
+ size_t dstlen;
+ char *dst;
+ const char *p;
+ size_t i = 0;
+
+ /* Worst case, each byte can become four bytes, plus a null terminator. */
+ dstlen = strlen(str) * 4 + 1;
+
+#ifdef FRONTEND
+ dst = malloc(dstlen);
+#else
+ dst = palloc_extended(dstlen, alloc_flags);
+#endif
+
+ if (!dst)
+ return NULL;
+
+ for (p = str; *p != '\0'; p++)
+ {
+
+ /* Only allow clean ASCII chars in the string */
+ if (*p < 32 || *p > 126)
+ {
+ Assert(i < (dstlen - 3));
+ snprintf(&dst[i], dstlen - i, "\\x%02x", (unsigned char) *p);
+ i += 4;
+ }
+ else
+ {
+ Assert(i < dstlen);
+ dst[i] = *p;
+ i++;
+ }
+ }
+
+ Assert(i < dstlen);
+ dst[i] = '\0';
+ return dst;
+}
+
+
+/*
+ * pg_is_ascii -- Check if string is made only of ASCII characters
+ */
+bool
+pg_is_ascii(const char *str)
+{
+ while (*str)
+ {
+ if (IS_HIGHBIT_SET(*str))
+ return false;
+ str++;
+ }
+ return true;
+}
+
+
+/*
+ * pg_strip_crlf -- Remove any trailing newline and carriage return
+ *
+ * Removes any trailing newline and carriage return characters (\r on
+ * Windows) in the input string, zero-terminating it.
+ *
+ * The passed in string must be zero-terminated. This function returns
+ * the new length of the string.
+ */
+int
+pg_strip_crlf(char *str)
+{
+ int len = strlen(str);
+
+ while (len > 0 && (str[len - 1] == '\n' ||
+ str[len - 1] == '\r'))
+ str[--len] = '\0';
+
+ return len;
+}
diff --git a/contrib/libs/libpq/src/common/stringinfo.c b/contrib/libs/libpq/src/common/stringinfo.c
new file mode 100644
index 0000000000..230dafd6c8
--- /dev/null
+++ b/contrib/libs/libpq/src/common/stringinfo.c
@@ -0,0 +1,343 @@
+/*-------------------------------------------------------------------------
+ *
+ * stringinfo.c
+ *
+ * StringInfo provides an extensible string data type (currently limited to a
+ * length of 1GB). It can be used to buffer either ordinary C strings
+ * (null-terminated text) or arbitrary binary data. All storage is allocated
+ * with palloc() (falling back to malloc in frontend code).
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/common/stringinfo.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+
+#include "postgres.h"
+#error #include "utils/memutils.h"
+
+#else
+
+#include "postgres_fe.h"
+
+/* It's possible we could use a different value for this in frontend code */
+#define MaxAllocSize ((Size) 0x3fffffff) /* 1 gigabyte - 1 */
+
+#endif
+
+#include "lib/stringinfo.h"
+
+
+/*
+ * makeStringInfo
+ *
+ * Create an empty 'StringInfoData' & return a pointer to it.
+ */
+StringInfo
+makeStringInfo(void)
+{
+ StringInfo res;
+
+ res = (StringInfo) palloc(sizeof(StringInfoData));
+
+ initStringInfo(res);
+
+ return res;
+}
+
+/*
+ * initStringInfo
+ *
+ * Initialize a StringInfoData struct (with previously undefined contents)
+ * to describe an empty string.
+ */
+void
+initStringInfo(StringInfo str)
+{
+ int size = 1024; /* initial default buffer size */
+
+ str->data = (char *) palloc(size);
+ str->maxlen = size;
+ resetStringInfo(str);
+}
+
+/*
+ * resetStringInfo
+ *
+ * Reset the StringInfo: the data buffer remains valid, but its
+ * previous content, if any, is cleared.
+ */
+void
+resetStringInfo(StringInfo str)
+{
+ str->data[0] = '\0';
+ str->len = 0;
+ str->cursor = 0;
+}
+
+/*
+ * appendStringInfo
+ *
+ * Format text data under the control of fmt (an sprintf-style format string)
+ * and append it to whatever is already in str. More space is allocated
+ * to str if necessary. This is sort of like a combination of sprintf and
+ * strcat.
+ */
+void
+appendStringInfo(StringInfo str, const char *fmt,...)
+{
+ int save_errno = errno;
+
+ for (;;)
+ {
+ va_list args;
+ int needed;
+
+ /* Try to format the data. */
+ errno = save_errno;
+ va_start(args, fmt);
+ needed = appendStringInfoVA(str, fmt, args);
+ va_end(args);
+
+ if (needed == 0)
+ break; /* success */
+
+ /* Increase the buffer size and try again. */
+ enlargeStringInfo(str, needed);
+ }
+}
+
+/*
+ * appendStringInfoVA
+ *
+ * Attempt to format text data under the control of fmt (an sprintf-style
+ * format string) and append it to whatever is already in str. If successful
+ * return zero; if not (because there's not enough space), return an estimate
+ * of the space needed, without modifying str. Typically the caller should
+ * pass the return value to enlargeStringInfo() before trying again; see
+ * appendStringInfo for standard usage pattern.
+ *
+ * Caution: callers must be sure to preserve their entry-time errno
+ * when looping, in case the fmt contains "%m".
+ *
+ * XXX This API is ugly, but there seems no alternative given the C spec's
+ * restrictions on what can portably be done with va_list arguments: you have
+ * to redo va_start before you can rescan the argument list, and we can't do
+ * that from here.
+ */
+int
+appendStringInfoVA(StringInfo str, const char *fmt, va_list args)
+{
+ int avail;
+ size_t nprinted;
+
+ Assert(str != NULL);
+
+ /*
+ * If there's hardly any space, don't bother trying, just fail to make the
+ * caller enlarge the buffer first. We have to guess at how much to
+ * enlarge, since we're skipping the formatting work.
+ */
+ avail = str->maxlen - str->len;
+ if (avail < 16)
+ return 32;
+
+ nprinted = pvsnprintf(str->data + str->len, (size_t) avail, fmt, args);
+
+ if (nprinted < (size_t) avail)
+ {
+ /* Success. Note nprinted does not include trailing null. */
+ str->len += (int) nprinted;
+ return 0;
+ }
+
+ /* Restore the trailing null so that str is unmodified. */
+ str->data[str->len] = '\0';
+
+ /*
+ * Return pvsnprintf's estimate of the space needed. (Although this is
+ * given as a size_t, we know it will fit in int because it's not more
+ * than MaxAllocSize.)
+ */
+ return (int) nprinted;
+}
+
+/*
+ * appendStringInfoString
+ *
+ * Append a null-terminated string to str.
+ * Like appendStringInfo(str, "%s", s) but faster.
+ */
+void
+appendStringInfoString(StringInfo str, const char *s)
+{
+ appendBinaryStringInfo(str, s, strlen(s));
+}
+
+/*
+ * appendStringInfoChar
+ *
+ * Append a single byte to str.
+ * Like appendStringInfo(str, "%c", ch) but much faster.
+ */
+void
+appendStringInfoChar(StringInfo str, char ch)
+{
+ /* Make more room if needed */
+ if (str->len + 1 >= str->maxlen)
+ enlargeStringInfo(str, 1);
+
+ /* OK, append the character */
+ str->data[str->len] = ch;
+ str->len++;
+ str->data[str->len] = '\0';
+}
+
+/*
+ * appendStringInfoSpaces
+ *
+ * Append the specified number of spaces to a buffer.
+ */
+void
+appendStringInfoSpaces(StringInfo str, int count)
+{
+ if (count > 0)
+ {
+ /* Make more room if needed */
+ enlargeStringInfo(str, count);
+
+ /* OK, append the spaces */
+ memset(&str->data[str->len], ' ', count);
+ str->len += count;
+ str->data[str->len] = '\0';
+ }
+}
+
+/*
+ * appendBinaryStringInfo
+ *
+ * Append arbitrary binary data to a StringInfo, allocating more space
+ * if necessary. Ensures that a trailing null byte is present.
+ */
+void
+appendBinaryStringInfo(StringInfo str, const void *data, int datalen)
+{
+ Assert(str != NULL);
+
+ /* Make more room if needed */
+ enlargeStringInfo(str, datalen);
+
+ /* OK, append the data */
+ memcpy(str->data + str->len, data, datalen);
+ str->len += datalen;
+
+ /*
+ * Keep a trailing null in place, even though it's probably useless for
+ * binary data. (Some callers are dealing with text but call this because
+ * their input isn't null-terminated.)
+ */
+ str->data[str->len] = '\0';
+}
+
+/*
+ * appendBinaryStringInfoNT
+ *
+ * Append arbitrary binary data to a StringInfo, allocating more space
+ * if necessary. Does not ensure a trailing null-byte exists.
+ */
+void
+appendBinaryStringInfoNT(StringInfo str, const void *data, int datalen)
+{
+ Assert(str != NULL);
+
+ /* Make more room if needed */
+ enlargeStringInfo(str, datalen);
+
+ /* OK, append the data */
+ memcpy(str->data + str->len, data, datalen);
+ str->len += datalen;
+}
+
+/*
+ * enlargeStringInfo
+ *
+ * Make sure there is enough space for 'needed' more bytes
+ * ('needed' does not include the terminating null).
+ *
+ * External callers usually need not concern themselves with this, since
+ * all stringinfo.c routines do it automatically. However, if a caller
+ * knows that a StringInfo will eventually become X bytes large, it
+ * can save some palloc overhead by enlarging the buffer before starting
+ * to store data in it.
+ *
+ * NB: In the backend, because we use repalloc() to enlarge the buffer, the
+ * string buffer will remain allocated in the same memory context that was
+ * current when initStringInfo was called, even if another context is now
+ * current. This is the desired and indeed critical behavior!
+ */
+void
+enlargeStringInfo(StringInfo str, int needed)
+{
+ int newlen;
+
+ /*
+ * Guard against out-of-range "needed" values. Without this, we can get
+ * an overflow or infinite loop in the following.
+ */
+ if (needed < 0) /* should not happen */
+ {
+#ifndef FRONTEND
+ elog(ERROR, "invalid string enlargement request size: %d", needed);
+#else
+ fprintf(stderr, "invalid string enlargement request size: %d\n", needed);
+ exit(EXIT_FAILURE);
+#endif
+ }
+ if (((Size) needed) >= (MaxAllocSize - (Size) str->len))
+ {
+#ifndef FRONTEND
+ ereport(ERROR,
+ (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+ errmsg("out of memory"),
+ errdetail("Cannot enlarge string buffer containing %d bytes by %d more bytes.",
+ str->len, needed)));
+#else
+ fprintf(stderr,
+ _("out of memory\n\nCannot enlarge string buffer containing %d bytes by %d more bytes.\n"),
+ str->len, needed);
+ exit(EXIT_FAILURE);
+#endif
+ }
+
+ needed += str->len + 1; /* total space required now */
+
+ /* Because of the above test, we now have needed <= MaxAllocSize */
+
+ if (needed <= str->maxlen)
+ return; /* got enough space already */
+
+ /*
+ * We don't want to allocate just a little more space with each append;
+ * for efficiency, double the buffer size each time it overflows.
+ * Actually, we might need to more than double it if 'needed' is big...
+ */
+ newlen = 2 * str->maxlen;
+ while (needed > newlen)
+ newlen = 2 * newlen;
+
+ /*
+ * Clamp to MaxAllocSize in case we went past it. Note we are assuming
+ * here that MaxAllocSize <= INT_MAX/2, else the above loop could
+ * overflow. We will still have newlen >= needed.
+ */
+ if (newlen > (int) MaxAllocSize)
+ newlen = (int) MaxAllocSize;
+
+ str->data = (char *) repalloc(str->data, newlen);
+
+ str->maxlen = newlen;
+}
diff --git a/contrib/libs/libpq/src/common/unicode_norm.c b/contrib/libs/libpq/src/common/unicode_norm.c
new file mode 100644
index 0000000000..6b40bdfeb4
--- /dev/null
+++ b/contrib/libs/libpq/src/common/unicode_norm.c
@@ -0,0 +1,634 @@
+/*-------------------------------------------------------------------------
+ * unicode_norm.c
+ * Normalize a Unicode string
+ *
+ * This implements Unicode normalization, per the documentation at
+ * https://www.unicode.org/reports/tr15/.
+ *
+ * Portions Copyright (c) 2017-2023, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/common/unicode_norm.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#include "common/unicode_norm.h"
+#ifndef FRONTEND
+#error #include "common/unicode_norm_hashfunc.h"
+#error #include "common/unicode_normprops_table.h"
+#include "port/pg_bswap.h"
+#else
+#include "common/unicode_norm_table.h"
+#endif
+
+#ifndef FRONTEND
+#define ALLOC(size) palloc(size)
+#define FREE(size) pfree(size)
+#else
+#define ALLOC(size) malloc(size)
+#define FREE(size) free(size)
+#endif
+
+/* Constants for calculations with Hangul characters */
+#define SBASE 0xAC00 /* U+AC00 */
+#define LBASE 0x1100 /* U+1100 */
+#define VBASE 0x1161 /* U+1161 */
+#define TBASE 0x11A7 /* U+11A7 */
+#define LCOUNT 19
+#define VCOUNT 21
+#define TCOUNT 28
+#define NCOUNT VCOUNT * TCOUNT
+#define SCOUNT LCOUNT * NCOUNT
+
+#ifdef FRONTEND
+/* comparison routine for bsearch() of decomposition lookup table. */
+static int
+conv_compare(const void *p1, const void *p2)
+{
+ uint32 v1,
+ v2;
+
+ v1 = *(const uint32 *) p1;
+ v2 = ((const pg_unicode_decomposition *) p2)->codepoint;
+ return (v1 > v2) ? 1 : ((v1 == v2) ? 0 : -1);
+}
+
+#endif
+
+/*
+ * get_code_entry
+ *
+ * Get the entry corresponding to code in the decomposition lookup table.
+ * The backend version of this code uses a perfect hash function for the
+ * lookup, while the frontend version uses a binary search.
+ */
+static const pg_unicode_decomposition *
+get_code_entry(pg_wchar code)
+{
+#ifndef FRONTEND
+ int h;
+ uint32 hashkey;
+ pg_unicode_decompinfo decompinfo = UnicodeDecompInfo;
+
+ /*
+ * Compute the hash function. The hash key is the codepoint with the bytes
+ * in network order.
+ */
+ hashkey = pg_hton32(code);
+ h = decompinfo.hash(&hashkey);
+
+ /* An out-of-range result implies no match */
+ if (h < 0 || h >= decompinfo.num_decomps)
+ return NULL;
+
+ /*
+ * Since it's a perfect hash, we need only match to the specific codepoint
+ * it identifies.
+ */
+ if (code != decompinfo.decomps[h].codepoint)
+ return NULL;
+
+ /* Success! */
+ return &decompinfo.decomps[h];
+#else
+ return bsearch(&(code),
+ UnicodeDecompMain,
+ lengthof(UnicodeDecompMain),
+ sizeof(pg_unicode_decomposition),
+ conv_compare);
+#endif
+}
+
+/*
+ * Get the combining class of the given codepoint.
+ */
+static uint8
+get_canonical_class(pg_wchar code)
+{
+ const pg_unicode_decomposition *entry = get_code_entry(code);
+
+ /*
+ * If no entries are found, the character used is either an Hangul
+ * character or a character with a class of 0 and no decompositions.
+ */
+ if (!entry)
+ return 0;
+ else
+ return entry->comb_class;
+}
+
+/*
+ * Given a decomposition entry looked up earlier, get the decomposed
+ * characters.
+ *
+ * Note: the returned pointer can point to statically allocated buffer, and
+ * is only valid until next call to this function!
+ */
+static const pg_wchar *
+get_code_decomposition(const pg_unicode_decomposition *entry, int *dec_size)
+{
+ static pg_wchar x;
+
+ if (DECOMPOSITION_IS_INLINE(entry))
+ {
+ Assert(DECOMPOSITION_SIZE(entry) == 1);
+ x = (pg_wchar) entry->dec_index;
+ *dec_size = 1;
+ return &x;
+ }
+ else
+ {
+ *dec_size = DECOMPOSITION_SIZE(entry);
+ return &UnicodeDecomp_codepoints[entry->dec_index];
+ }
+}
+
+/*
+ * Calculate how many characters a given character will decompose to.
+ *
+ * This needs to recurse, if the character decomposes into characters that
+ * are, in turn, decomposable.
+ */
+static int
+get_decomposed_size(pg_wchar code, bool compat)
+{
+ const pg_unicode_decomposition *entry;
+ int size = 0;
+ int i;
+ const uint32 *decomp;
+ int dec_size;
+
+ /*
+ * Fast path for Hangul characters not stored in tables to save memory as
+ * decomposition is algorithmic. See
+ * https://www.unicode.org/reports/tr15/tr15-18.html, annex 10 for details
+ * on the matter.
+ */
+ if (code >= SBASE && code < SBASE + SCOUNT)
+ {
+ uint32 tindex,
+ sindex;
+
+ sindex = code - SBASE;
+ tindex = sindex % TCOUNT;
+
+ if (tindex != 0)
+ return 3;
+ return 2;
+ }
+
+ entry = get_code_entry(code);
+
+ /*
+ * Just count current code if no other decompositions. A NULL entry is
+ * equivalent to a character with class 0 and no decompositions.
+ */
+ if (entry == NULL || DECOMPOSITION_SIZE(entry) == 0 ||
+ (!compat && DECOMPOSITION_IS_COMPAT(entry)))
+ return 1;
+
+ /*
+ * If this entry has other decomposition codes look at them as well. First
+ * get its decomposition in the list of tables available.
+ */
+ decomp = get_code_decomposition(entry, &dec_size);
+ for (i = 0; i < dec_size; i++)
+ {
+ uint32 lcode = decomp[i];
+
+ size += get_decomposed_size(lcode, compat);
+ }
+
+ return size;
+}
+
+/*
+ * Recompose a set of characters. For hangul characters, the calculation
+ * is algorithmic. For others, an inverse lookup at the decomposition
+ * table is necessary. Returns true if a recomposition can be done, and
+ * false otherwise.
+ */
+static bool
+recompose_code(uint32 start, uint32 code, uint32 *result)
+{
+ /*
+ * Handle Hangul characters algorithmically, per the Unicode spec.
+ *
+ * Check if two current characters are L and V.
+ */
+ if (start >= LBASE && start < LBASE + LCOUNT &&
+ code >= VBASE && code < VBASE + VCOUNT)
+ {
+ /* make syllable of form LV */
+ uint32 lindex = start - LBASE;
+ uint32 vindex = code - VBASE;
+
+ *result = SBASE + (lindex * VCOUNT + vindex) * TCOUNT;
+ return true;
+ }
+ /* Check if two current characters are LV and T */
+ else if (start >= SBASE && start < (SBASE + SCOUNT) &&
+ ((start - SBASE) % TCOUNT) == 0 &&
+ code >= TBASE && code < (TBASE + TCOUNT))
+ {
+ /* make syllable of form LVT */
+ uint32 tindex = code - TBASE;
+
+ *result = start + tindex;
+ return true;
+ }
+ else
+ {
+ const pg_unicode_decomposition *entry;
+
+ /*
+ * Do an inverse lookup of the decomposition tables to see if anything
+ * matches. The comparison just needs to be a perfect match on the
+ * sub-table of size two, because the start character has already been
+ * recomposed partially. This lookup uses a perfect hash function for
+ * the backend code.
+ */
+#ifndef FRONTEND
+
+ int h,
+ inv_lookup_index;
+ uint64 hashkey;
+ pg_unicode_recompinfo recompinfo = UnicodeRecompInfo;
+
+ /*
+ * Compute the hash function. The hash key is formed by concatenating
+ * bytes of the two codepoints in network order. See also
+ * src/common/unicode/generate-unicode_norm_table.pl.
+ */
+ hashkey = pg_hton64(((uint64) start << 32) | (uint64) code);
+ h = recompinfo.hash(&hashkey);
+
+ /* An out-of-range result implies no match */
+ if (h < 0 || h >= recompinfo.num_recomps)
+ return false;
+
+ inv_lookup_index = recompinfo.inverse_lookup[h];
+ entry = &UnicodeDecompMain[inv_lookup_index];
+
+ if (start == UnicodeDecomp_codepoints[entry->dec_index] &&
+ code == UnicodeDecomp_codepoints[entry->dec_index + 1])
+ {
+ *result = entry->codepoint;
+ return true;
+ }
+
+#else
+
+ int i;
+
+ for (i = 0; i < lengthof(UnicodeDecompMain); i++)
+ {
+ entry = &UnicodeDecompMain[i];
+
+ if (DECOMPOSITION_SIZE(entry) != 2)
+ continue;
+
+ if (DECOMPOSITION_NO_COMPOSE(entry))
+ continue;
+
+ if (start == UnicodeDecomp_codepoints[entry->dec_index] &&
+ code == UnicodeDecomp_codepoints[entry->dec_index + 1])
+ {
+ *result = entry->codepoint;
+ return true;
+ }
+ }
+#endif /* !FRONTEND */
+ }
+
+ return false;
+}
+
+/*
+ * Decompose the given code into the array given by caller. The
+ * decomposition begins at the position given by caller, saving one
+ * lookup on the decomposition table. The current position needs to be
+ * updated here to let the caller know from where to continue filling
+ * in the array result.
+ */
+static void
+decompose_code(pg_wchar code, bool compat, pg_wchar **result, int *current)
+{
+ const pg_unicode_decomposition *entry;
+ int i;
+ const uint32 *decomp;
+ int dec_size;
+
+ /*
+ * Fast path for Hangul characters not stored in tables to save memory as
+ * decomposition is algorithmic. See
+ * https://www.unicode.org/reports/tr15/tr15-18.html, annex 10 for details
+ * on the matter.
+ */
+ if (code >= SBASE && code < SBASE + SCOUNT)
+ {
+ uint32 l,
+ v,
+ tindex,
+ sindex;
+ pg_wchar *res = *result;
+
+ sindex = code - SBASE;
+ l = LBASE + sindex / (VCOUNT * TCOUNT);
+ v = VBASE + (sindex % (VCOUNT * TCOUNT)) / TCOUNT;
+ tindex = sindex % TCOUNT;
+
+ res[*current] = l;
+ (*current)++;
+ res[*current] = v;
+ (*current)++;
+
+ if (tindex != 0)
+ {
+ res[*current] = TBASE + tindex;
+ (*current)++;
+ }
+
+ return;
+ }
+
+ entry = get_code_entry(code);
+
+ /*
+ * Just fill in with the current decomposition if there are no
+ * decomposition codes to recurse to. A NULL entry is equivalent to a
+ * character with class 0 and no decompositions, so just leave also in
+ * this case.
+ */
+ if (entry == NULL || DECOMPOSITION_SIZE(entry) == 0 ||
+ (!compat && DECOMPOSITION_IS_COMPAT(entry)))
+ {
+ pg_wchar *res = *result;
+
+ res[*current] = code;
+ (*current)++;
+ return;
+ }
+
+ /*
+ * If this entry has other decomposition codes look at them as well.
+ */
+ decomp = get_code_decomposition(entry, &dec_size);
+ for (i = 0; i < dec_size; i++)
+ {
+ pg_wchar lcode = (pg_wchar) decomp[i];
+
+ /* Leave if no more decompositions */
+ decompose_code(lcode, compat, result, current);
+ }
+}
+
+/*
+ * unicode_normalize - Normalize a Unicode string to the specified form.
+ *
+ * The input is a 0-terminated array of codepoints.
+ *
+ * In frontend, returns a 0-terminated array of codepoints, allocated with
+ * malloc. Or NULL if we run out of memory. In backend, the returned
+ * string is palloc'd instead, and OOM is reported with ereport().
+ */
+pg_wchar *
+unicode_normalize(UnicodeNormalizationForm form, const pg_wchar *input)
+{
+ bool compat = (form == UNICODE_NFKC || form == UNICODE_NFKD);
+ bool recompose = (form == UNICODE_NFC || form == UNICODE_NFKC);
+ pg_wchar *decomp_chars;
+ pg_wchar *recomp_chars;
+ int decomp_size,
+ current_size;
+ int count;
+ const pg_wchar *p;
+
+ /* variables for recomposition */
+ int last_class;
+ int starter_pos;
+ int target_pos;
+ uint32 starter_ch;
+
+ /* First, do character decomposition */
+
+ /*
+ * Calculate how many characters long the decomposed version will be.
+ */
+ decomp_size = 0;
+ for (p = input; *p; p++)
+ decomp_size += get_decomposed_size(*p, compat);
+
+ decomp_chars = (pg_wchar *) ALLOC((decomp_size + 1) * sizeof(pg_wchar));
+ if (decomp_chars == NULL)
+ return NULL;
+
+ /*
+ * Now fill in each entry recursively. This needs a second pass on the
+ * decomposition table.
+ */
+ current_size = 0;
+ for (p = input; *p; p++)
+ decompose_code(*p, compat, &decomp_chars, &current_size);
+ decomp_chars[decomp_size] = '\0';
+ Assert(decomp_size == current_size);
+
+ /* Leave if there is nothing to decompose */
+ if (decomp_size == 0)
+ return decomp_chars;
+
+ /*
+ * Now apply canonical ordering.
+ */
+ for (count = 1; count < decomp_size; count++)
+ {
+ pg_wchar prev = decomp_chars[count - 1];
+ pg_wchar next = decomp_chars[count];
+ pg_wchar tmp;
+ const uint8 prevClass = get_canonical_class(prev);
+ const uint8 nextClass = get_canonical_class(next);
+
+ /*
+ * Per Unicode (https://www.unicode.org/reports/tr15/tr15-18.html)
+ * annex 4, a sequence of two adjacent characters in a string is an
+ * exchangeable pair if the combining class (from the Unicode
+ * Character Database) for the first character is greater than the
+ * combining class for the second, and the second is not a starter. A
+ * character is a starter if its combining class is 0.
+ */
+ if (prevClass == 0 || nextClass == 0)
+ continue;
+
+ if (prevClass <= nextClass)
+ continue;
+
+ /* exchange can happen */
+ tmp = decomp_chars[count - 1];
+ decomp_chars[count - 1] = decomp_chars[count];
+ decomp_chars[count] = tmp;
+
+ /* backtrack to check again */
+ if (count > 1)
+ count -= 2;
+ }
+
+ if (!recompose)
+ return decomp_chars;
+
+ /*
+ * The last phase of NFC and NFKC is the recomposition of the reordered
+ * Unicode string using combining classes. The recomposed string cannot be
+ * longer than the decomposed one, so make the allocation of the output
+ * string based on that assumption.
+ */
+ recomp_chars = (pg_wchar *) ALLOC((decomp_size + 1) * sizeof(pg_wchar));
+ if (!recomp_chars)
+ {
+ FREE(decomp_chars);
+ return NULL;
+ }
+
+ last_class = -1; /* this eliminates a special check */
+ starter_pos = 0;
+ target_pos = 1;
+ starter_ch = recomp_chars[0] = decomp_chars[0];
+
+ for (count = 1; count < decomp_size; count++)
+ {
+ pg_wchar ch = decomp_chars[count];
+ int ch_class = get_canonical_class(ch);
+ pg_wchar composite;
+
+ if (last_class < ch_class &&
+ recompose_code(starter_ch, ch, &composite))
+ {
+ recomp_chars[starter_pos] = composite;
+ starter_ch = composite;
+ }
+ else if (ch_class == 0)
+ {
+ starter_pos = target_pos;
+ starter_ch = ch;
+ last_class = -1;
+ recomp_chars[target_pos++] = ch;
+ }
+ else
+ {
+ last_class = ch_class;
+ recomp_chars[target_pos++] = ch;
+ }
+ }
+ recomp_chars[target_pos] = (pg_wchar) '\0';
+
+ FREE(decomp_chars);
+
+ return recomp_chars;
+}
+
+/*
+ * Normalization "quick check" algorithm; see
+ * <http://www.unicode.org/reports/tr15/#Detecting_Normalization_Forms>
+ */
+
+/* We only need this in the backend. */
+#ifndef FRONTEND
+
+static const pg_unicode_normprops *
+qc_hash_lookup(pg_wchar ch, const pg_unicode_norminfo *norminfo)
+{
+ int h;
+ uint32 hashkey;
+
+ /*
+ * Compute the hash function. The hash key is the codepoint with the bytes
+ * in network order.
+ */
+ hashkey = pg_hton32(ch);
+ h = norminfo->hash(&hashkey);
+
+ /* An out-of-range result implies no match */
+ if (h < 0 || h >= norminfo->num_normprops)
+ return NULL;
+
+ /*
+ * Since it's a perfect hash, we need only match to the specific codepoint
+ * it identifies.
+ */
+ if (ch != norminfo->normprops[h].codepoint)
+ return NULL;
+
+ /* Success! */
+ return &norminfo->normprops[h];
+}
+
+/*
+ * Look up the normalization quick check character property
+ */
+static UnicodeNormalizationQC
+qc_is_allowed(UnicodeNormalizationForm form, pg_wchar ch)
+{
+ const pg_unicode_normprops *found = NULL;
+
+ switch (form)
+ {
+ case UNICODE_NFC:
+ found = qc_hash_lookup(ch, &UnicodeNormInfo_NFC_QC);
+ break;
+ case UNICODE_NFKC:
+ found = qc_hash_lookup(ch, &UnicodeNormInfo_NFKC_QC);
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+
+ if (found)
+ return found->quickcheck;
+ else
+ return UNICODE_NORM_QC_YES;
+}
+
+UnicodeNormalizationQC
+unicode_is_normalized_quickcheck(UnicodeNormalizationForm form, const pg_wchar *input)
+{
+ uint8 lastCanonicalClass = 0;
+ UnicodeNormalizationQC result = UNICODE_NORM_QC_YES;
+
+ /*
+ * For the "D" forms, we don't run the quickcheck. We don't include the
+ * lookup tables for those because they are huge, checking for these
+ * particular forms is less common, and running the slow path is faster
+ * for the "D" forms than the "C" forms because you don't need to
+ * recompose, which is slow.
+ */
+ if (form == UNICODE_NFD || form == UNICODE_NFKD)
+ return UNICODE_NORM_QC_MAYBE;
+
+ for (const pg_wchar *p = input; *p; p++)
+ {
+ pg_wchar ch = *p;
+ uint8 canonicalClass;
+ UnicodeNormalizationQC check;
+
+ canonicalClass = get_canonical_class(ch);
+ if (lastCanonicalClass > canonicalClass && canonicalClass != 0)
+ return UNICODE_NORM_QC_NO;
+
+ check = qc_is_allowed(form, ch);
+ if (check == UNICODE_NORM_QC_NO)
+ return UNICODE_NORM_QC_NO;
+ else if (check == UNICODE_NORM_QC_MAYBE)
+ result = UNICODE_NORM_QC_MAYBE;
+
+ lastCanonicalClass = canonicalClass;
+ }
+ return result;
+}
+
+#endif /* !FRONTEND */
diff --git a/contrib/libs/libpq/src/common/username.c b/contrib/libs/libpq/src/common/username.c
new file mode 100644
index 0000000000..e8ac4c4977
--- /dev/null
+++ b/contrib/libs/libpq/src/common/username.c
@@ -0,0 +1,87 @@
+/*-------------------------------------------------------------------------
+ *
+ * username.c
+ * get user name
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/common/username.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#include <pwd.h>
+#include <unistd.h>
+
+#include "common/username.h"
+
+/*
+ * Returns the current user name in a static buffer
+ * On error, returns NULL and sets *errstr to point to a palloc'd message
+ */
+const char *
+get_user_name(char **errstr)
+{
+#ifndef WIN32
+ struct passwd *pw;
+ uid_t user_id = geteuid();
+
+ *errstr = NULL;
+
+ errno = 0; /* clear errno before call */
+ pw = getpwuid(user_id);
+ if (!pw)
+ {
+ *errstr = psprintf(_("could not look up effective user ID %ld: %s"),
+ (long) user_id,
+ errno ? strerror(errno) : _("user does not exist"));
+ return NULL;
+ }
+
+ return pw->pw_name;
+#else
+ /* Microsoft recommends buffer size of UNLEN+1, where UNLEN = 256 */
+ /* "static" variable remains after function exit */
+ static char username[256 + 1];
+ DWORD len = sizeof(username);
+
+ *errstr = NULL;
+
+ if (!GetUserName(username, &len))
+ {
+ *errstr = psprintf(_("user name lookup failure: error code %lu"),
+ GetLastError());
+ return NULL;
+ }
+
+ return username;
+#endif
+}
+
+
+/*
+ * Returns the current user name in a static buffer or exits
+ */
+const char *
+get_user_name_or_exit(const char *progname)
+{
+ const char *user_name;
+ char *errstr;
+
+ user_name = get_user_name(&errstr);
+
+ if (!user_name)
+ {
+ fprintf(stderr, "%s: %s\n", progname, errstr);
+ exit(1);
+ }
+ return user_name;
+}
diff --git a/contrib/libs/libpq/src/common/wait_error.c b/contrib/libs/libpq/src/common/wait_error.c
new file mode 100644
index 0000000000..a90b745f07
--- /dev/null
+++ b/contrib/libs/libpq/src/common/wait_error.c
@@ -0,0 +1,148 @@
+/*-------------------------------------------------------------------------
+ *
+ * wait_error.c
+ * Convert a wait/waitpid(2) result code to a human-readable string
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/common/wait_error.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#include <signal.h>
+#include <sys/wait.h>
+
+/*
+ * Return a human-readable string explaining the reason a child process
+ * terminated. The argument is a return code returned by wait(2) or
+ * waitpid(2), which also applies to pclose(3) and system(3). The result is a
+ * translated, palloc'd or malloc'd string.
+ */
+char *
+wait_result_to_str(int exitstatus)
+{
+ char str[512];
+
+ /*
+ * To simplify using this after pclose() and system(), handle status -1
+ * first. In that case, there is no wait result but some error indicated
+ * by errno.
+ */
+ if (exitstatus == -1)
+ {
+ snprintf(str, sizeof(str), "%m");
+ }
+ else if (WIFEXITED(exitstatus))
+ {
+ /*
+ * Give more specific error message for some common exit codes that
+ * have a special meaning in shells.
+ */
+ switch (WEXITSTATUS(exitstatus))
+ {
+ case 126:
+ snprintf(str, sizeof(str), _("command not executable"));
+ break;
+
+ case 127:
+ snprintf(str, sizeof(str), _("command not found"));
+ break;
+
+ default:
+ snprintf(str, sizeof(str),
+ _("child process exited with exit code %d"),
+ WEXITSTATUS(exitstatus));
+ }
+ }
+ else if (WIFSIGNALED(exitstatus))
+ {
+#if defined(WIN32)
+ snprintf(str, sizeof(str),
+ _("child process was terminated by exception 0x%X"),
+ WTERMSIG(exitstatus));
+#else
+ snprintf(str, sizeof(str),
+ _("child process was terminated by signal %d: %s"),
+ WTERMSIG(exitstatus), pg_strsignal(WTERMSIG(exitstatus)));
+#endif
+ }
+ else
+ snprintf(str, sizeof(str),
+ _("child process exited with unrecognized status %d"),
+ exitstatus);
+
+ return pstrdup(str);
+}
+
+/*
+ * Return true if a wait(2) result indicates that the child process
+ * died due to the specified signal.
+ *
+ * The reason this is worth having a wrapper function for is that
+ * there are two cases: the signal might have been received by our
+ * immediate child process, or there might've been a shell process
+ * between us and the child that died. The shell will, per POSIX,
+ * report the child death using exit code 128 + signal number.
+ *
+ * If there is no possibility of an intermediate shell, this function
+ * need not (and probably should not) be used.
+ */
+bool
+wait_result_is_signal(int exit_status, int signum)
+{
+ if (WIFSIGNALED(exit_status) && WTERMSIG(exit_status) == signum)
+ return true;
+ if (WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == 128 + signum)
+ return true;
+ return false;
+}
+
+/*
+ * Return true if a wait(2) result indicates that the child process
+ * died due to any signal. We consider either direct child death
+ * or a shell report of child process death as matching the condition.
+ *
+ * If include_command_not_found is true, also return true for shell
+ * exit codes indicating "command not found" and the like
+ * (specifically, exit codes 126 and 127; see above).
+ */
+bool
+wait_result_is_any_signal(int exit_status, bool include_command_not_found)
+{
+ if (WIFSIGNALED(exit_status))
+ return true;
+ if (WIFEXITED(exit_status) &&
+ WEXITSTATUS(exit_status) > (include_command_not_found ? 125 : 128))
+ return true;
+ return false;
+}
+
+/*
+ * Return the shell exit code (normally 0 to 255) that corresponds to the
+ * given wait status. The argument is a wait status as returned by wait(2)
+ * or waitpid(2), which also applies to pclose(3) and system(3). To support
+ * the latter two cases, we pass through "-1" unchanged.
+ */
+int
+wait_result_to_exit_code(int exit_status)
+{
+ if (exit_status == -1)
+ return -1; /* failure of pclose() or system() */
+ if (WIFEXITED(exit_status))
+ return WEXITSTATUS(exit_status);
+ if (WIFSIGNALED(exit_status))
+ return 128 + WTERMSIG(exit_status);
+ /* On many systems, this is unreachable */
+ return -1;
+}
diff --git a/contrib/libs/libpq/src/common/wchar.c b/contrib/libs/libpq/src/common/wchar.c
new file mode 100644
index 0000000000..fb9d9f5c85
--- /dev/null
+++ b/contrib/libs/libpq/src/common/wchar.c
@@ -0,0 +1,2193 @@
+/*-------------------------------------------------------------------------
+ *
+ * wchar.c
+ * Functions for working with multibyte characters in various encodings.
+ *
+ * Portions Copyright (c) 1998-2023, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/common/wchar.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "c.h"
+
+#include "mb/pg_wchar.h"
+
+
+/*
+ * Operations on multi-byte encodings are driven by a table of helper
+ * functions.
+ *
+ * To add an encoding support, define mblen(), dsplen(), verifychar() and
+ * verifystr() for the encoding. For server-encodings, also define mb2wchar()
+ * and wchar2mb() conversion functions.
+ *
+ * These functions generally assume that their input is validly formed.
+ * The "verifier" functions, further down in the file, have to be more
+ * paranoid.
+ *
+ * We expect that mblen() does not need to examine more than the first byte
+ * of the character to discover the correct length. GB18030 is an exception
+ * to that rule, though, as it also looks at second byte. But even that
+ * behaves in a predictable way, if you only pass the first byte: it will
+ * treat 4-byte encoded characters as two 2-byte encoded characters, which is
+ * good enough for all current uses.
+ *
+ * Note: for the display output of psql to work properly, the return values
+ * of the dsplen functions must conform to the Unicode standard. In particular
+ * the NUL character is zero width and control characters are generally
+ * width -1. It is recommended that non-ASCII encodings refer their ASCII
+ * subset to the ASCII routines to ensure consistency.
+ */
+
+/*
+ * SQL/ASCII
+ */
+static int
+pg_ascii2wchar_with_len(const unsigned char *from, pg_wchar *to, int len)
+{
+ int cnt = 0;
+
+ while (len > 0 && *from)
+ {
+ *to++ = *from++;
+ len--;
+ cnt++;
+ }
+ *to = 0;
+ return cnt;
+}
+
+static int
+pg_ascii_mblen(const unsigned char *s)
+{
+ return 1;
+}
+
+static int
+pg_ascii_dsplen(const unsigned char *s)
+{
+ if (*s == '\0')
+ return 0;
+ if (*s < 0x20 || *s == 0x7f)
+ return -1;
+
+ return 1;
+}
+
+/*
+ * EUC
+ */
+static int
+pg_euc2wchar_with_len(const unsigned char *from, pg_wchar *to, int len)
+{
+ int cnt = 0;
+
+ while (len > 0 && *from)
+ {
+ if (*from == SS2 && len >= 2) /* JIS X 0201 (so called "1 byte
+ * KANA") */
+ {
+ from++;
+ *to = (SS2 << 8) | *from++;
+ len -= 2;
+ }
+ else if (*from == SS3 && len >= 3) /* JIS X 0212 KANJI */
+ {
+ from++;
+ *to = (SS3 << 16) | (*from++ << 8);
+ *to |= *from++;
+ len -= 3;
+ }
+ else if (IS_HIGHBIT_SET(*from) && len >= 2) /* JIS X 0208 KANJI */
+ {
+ *to = *from++ << 8;
+ *to |= *from++;
+ len -= 2;
+ }
+ else /* must be ASCII */
+ {
+ *to = *from++;
+ len--;
+ }
+ to++;
+ cnt++;
+ }
+ *to = 0;
+ return cnt;
+}
+
+static inline int
+pg_euc_mblen(const unsigned char *s)
+{
+ int len;
+
+ if (*s == SS2)
+ len = 2;
+ else if (*s == SS3)
+ len = 3;
+ else if (IS_HIGHBIT_SET(*s))
+ len = 2;
+ else
+ len = 1;
+ return len;
+}
+
+static inline int
+pg_euc_dsplen(const unsigned char *s)
+{
+ int len;
+
+ if (*s == SS2)
+ len = 2;
+ else if (*s == SS3)
+ len = 2;
+ else if (IS_HIGHBIT_SET(*s))
+ len = 2;
+ else
+ len = pg_ascii_dsplen(s);
+ return len;
+}
+
+/*
+ * EUC_JP
+ */
+static int
+pg_eucjp2wchar_with_len(const unsigned char *from, pg_wchar *to, int len)
+{
+ return pg_euc2wchar_with_len(from, to, len);
+}
+
+static int
+pg_eucjp_mblen(const unsigned char *s)
+{
+ return pg_euc_mblen(s);
+}
+
+static int
+pg_eucjp_dsplen(const unsigned char *s)
+{
+ int len;
+
+ if (*s == SS2)
+ len = 1;
+ else if (*s == SS3)
+ len = 2;
+ else if (IS_HIGHBIT_SET(*s))
+ len = 2;
+ else
+ len = pg_ascii_dsplen(s);
+ return len;
+}
+
+/*
+ * EUC_KR
+ */
+static int
+pg_euckr2wchar_with_len(const unsigned char *from, pg_wchar *to, int len)
+{
+ return pg_euc2wchar_with_len(from, to, len);
+}
+
+static int
+pg_euckr_mblen(const unsigned char *s)
+{
+ return pg_euc_mblen(s);
+}
+
+static int
+pg_euckr_dsplen(const unsigned char *s)
+{
+ return pg_euc_dsplen(s);
+}
+
+/*
+ * EUC_CN
+ *
+ */
+static int
+pg_euccn2wchar_with_len(const unsigned char *from, pg_wchar *to, int len)
+{
+ int cnt = 0;
+
+ while (len > 0 && *from)
+ {
+ if (*from == SS2 && len >= 3) /* code set 2 (unused?) */
+ {
+ from++;
+ *to = (SS2 << 16) | (*from++ << 8);
+ *to |= *from++;
+ len -= 3;
+ }
+ else if (*from == SS3 && len >= 3) /* code set 3 (unused ?) */
+ {
+ from++;
+ *to = (SS3 << 16) | (*from++ << 8);
+ *to |= *from++;
+ len -= 3;
+ }
+ else if (IS_HIGHBIT_SET(*from) && len >= 2) /* code set 1 */
+ {
+ *to = *from++ << 8;
+ *to |= *from++;
+ len -= 2;
+ }
+ else
+ {
+ *to = *from++;
+ len--;
+ }
+ to++;
+ cnt++;
+ }
+ *to = 0;
+ return cnt;
+}
+
+static int
+pg_euccn_mblen(const unsigned char *s)
+{
+ int len;
+
+ if (IS_HIGHBIT_SET(*s))
+ len = 2;
+ else
+ len = 1;
+ return len;
+}
+
+static int
+pg_euccn_dsplen(const unsigned char *s)
+{
+ int len;
+
+ if (IS_HIGHBIT_SET(*s))
+ len = 2;
+ else
+ len = pg_ascii_dsplen(s);
+ return len;
+}
+
+/*
+ * EUC_TW
+ *
+ */
+static int
+pg_euctw2wchar_with_len(const unsigned char *from, pg_wchar *to, int len)
+{
+ int cnt = 0;
+
+ while (len > 0 && *from)
+ {
+ if (*from == SS2 && len >= 4) /* code set 2 */
+ {
+ from++;
+ *to = (((uint32) SS2) << 24) | (*from++ << 16);
+ *to |= *from++ << 8;
+ *to |= *from++;
+ len -= 4;
+ }
+ else if (*from == SS3 && len >= 3) /* code set 3 (unused?) */
+ {
+ from++;
+ *to = (SS3 << 16) | (*from++ << 8);
+ *to |= *from++;
+ len -= 3;
+ }
+ else if (IS_HIGHBIT_SET(*from) && len >= 2) /* code set 2 */
+ {
+ *to = *from++ << 8;
+ *to |= *from++;
+ len -= 2;
+ }
+ else
+ {
+ *to = *from++;
+ len--;
+ }
+ to++;
+ cnt++;
+ }
+ *to = 0;
+ return cnt;
+}
+
+static int
+pg_euctw_mblen(const unsigned char *s)
+{
+ int len;
+
+ if (*s == SS2)
+ len = 4;
+ else if (*s == SS3)
+ len = 3;
+ else if (IS_HIGHBIT_SET(*s))
+ len = 2;
+ else
+ len = 1;
+ return len;
+}
+
+static int
+pg_euctw_dsplen(const unsigned char *s)
+{
+ int len;
+
+ if (*s == SS2)
+ len = 2;
+ else if (*s == SS3)
+ len = 2;
+ else if (IS_HIGHBIT_SET(*s))
+ len = 2;
+ else
+ len = pg_ascii_dsplen(s);
+ return len;
+}
+
+/*
+ * Convert pg_wchar to EUC_* encoding.
+ * caller must allocate enough space for "to", including a trailing zero!
+ * len: length of from.
+ * "from" not necessarily null terminated.
+ */
+static int
+pg_wchar2euc_with_len(const pg_wchar *from, unsigned char *to, int len)
+{
+ int cnt = 0;
+
+ while (len > 0 && *from)
+ {
+ unsigned char c;
+
+ if ((c = (*from >> 24)))
+ {
+ *to++ = c;
+ *to++ = (*from >> 16) & 0xff;
+ *to++ = (*from >> 8) & 0xff;
+ *to++ = *from & 0xff;
+ cnt += 4;
+ }
+ else if ((c = (*from >> 16)))
+ {
+ *to++ = c;
+ *to++ = (*from >> 8) & 0xff;
+ *to++ = *from & 0xff;
+ cnt += 3;
+ }
+ else if ((c = (*from >> 8)))
+ {
+ *to++ = c;
+ *to++ = *from & 0xff;
+ cnt += 2;
+ }
+ else
+ {
+ *to++ = *from;
+ cnt++;
+ }
+ from++;
+ len--;
+ }
+ *to = 0;
+ return cnt;
+}
+
+
+/*
+ * JOHAB
+ */
+static int
+pg_johab_mblen(const unsigned char *s)
+{
+ return pg_euc_mblen(s);
+}
+
+static int
+pg_johab_dsplen(const unsigned char *s)
+{
+ return pg_euc_dsplen(s);
+}
+
+/*
+ * convert UTF8 string to pg_wchar (UCS-4)
+ * caller must allocate enough space for "to", including a trailing zero!
+ * len: length of from.
+ * "from" not necessarily null terminated.
+ */
+static int
+pg_utf2wchar_with_len(const unsigned char *from, pg_wchar *to, int len)
+{
+ int cnt = 0;
+ uint32 c1,
+ c2,
+ c3,
+ c4;
+
+ while (len > 0 && *from)
+ {
+ if ((*from & 0x80) == 0)
+ {
+ *to = *from++;
+ len--;
+ }
+ else if ((*from & 0xe0) == 0xc0)
+ {
+ if (len < 2)
+ break; /* drop trailing incomplete char */
+ c1 = *from++ & 0x1f;
+ c2 = *from++ & 0x3f;
+ *to = (c1 << 6) | c2;
+ len -= 2;
+ }
+ else if ((*from & 0xf0) == 0xe0)
+ {
+ if (len < 3)
+ break; /* drop trailing incomplete char */
+ c1 = *from++ & 0x0f;
+ c2 = *from++ & 0x3f;
+ c3 = *from++ & 0x3f;
+ *to = (c1 << 12) | (c2 << 6) | c3;
+ len -= 3;
+ }
+ else if ((*from & 0xf8) == 0xf0)
+ {
+ if (len < 4)
+ break; /* drop trailing incomplete char */
+ c1 = *from++ & 0x07;
+ c2 = *from++ & 0x3f;
+ c3 = *from++ & 0x3f;
+ c4 = *from++ & 0x3f;
+ *to = (c1 << 18) | (c2 << 12) | (c3 << 6) | c4;
+ len -= 4;
+ }
+ else
+ {
+ /* treat a bogus char as length 1; not ours to raise error */
+ *to = *from++;
+ len--;
+ }
+ to++;
+ cnt++;
+ }
+ *to = 0;
+ return cnt;
+}
+
+
+/*
+ * Map a Unicode code point to UTF-8. utf8string must have 4 bytes of
+ * space allocated.
+ */
+unsigned char *
+unicode_to_utf8(pg_wchar c, unsigned char *utf8string)
+{
+ if (c <= 0x7F)
+ {
+ utf8string[0] = c;
+ }
+ else if (c <= 0x7FF)
+ {
+ utf8string[0] = 0xC0 | ((c >> 6) & 0x1F);
+ utf8string[1] = 0x80 | (c & 0x3F);
+ }
+ else if (c <= 0xFFFF)
+ {
+ utf8string[0] = 0xE0 | ((c >> 12) & 0x0F);
+ utf8string[1] = 0x80 | ((c >> 6) & 0x3F);
+ utf8string[2] = 0x80 | (c & 0x3F);
+ }
+ else
+ {
+ utf8string[0] = 0xF0 | ((c >> 18) & 0x07);
+ utf8string[1] = 0x80 | ((c >> 12) & 0x3F);
+ utf8string[2] = 0x80 | ((c >> 6) & 0x3F);
+ utf8string[3] = 0x80 | (c & 0x3F);
+ }
+
+ return utf8string;
+}
+
+/*
+ * Trivial conversion from pg_wchar to UTF-8.
+ * caller should allocate enough space for "to"
+ * len: length of from.
+ * "from" not necessarily null terminated.
+ */
+static int
+pg_wchar2utf_with_len(const pg_wchar *from, unsigned char *to, int len)
+{
+ int cnt = 0;
+
+ while (len > 0 && *from)
+ {
+ int char_len;
+
+ unicode_to_utf8(*from, to);
+ char_len = pg_utf_mblen(to);
+ cnt += char_len;
+ to += char_len;
+ from++;
+ len--;
+ }
+ *to = 0;
+ return cnt;
+}
+
+/*
+ * Return the byte length of a UTF8 character pointed to by s
+ *
+ * Note: in the current implementation we do not support UTF8 sequences
+ * of more than 4 bytes; hence do NOT return a value larger than 4.
+ * We return "1" for any leading byte that is either flat-out illegal or
+ * indicates a length larger than we support.
+ *
+ * pg_utf2wchar_with_len(), utf8_to_unicode(), pg_utf8_islegal(), and perhaps
+ * other places would need to be fixed to change this.
+ */
+int
+pg_utf_mblen(const unsigned char *s)
+{
+ int len;
+
+ if ((*s & 0x80) == 0)
+ len = 1;
+ else if ((*s & 0xe0) == 0xc0)
+ len = 2;
+ else if ((*s & 0xf0) == 0xe0)
+ len = 3;
+ else if ((*s & 0xf8) == 0xf0)
+ len = 4;
+#ifdef NOT_USED
+ else if ((*s & 0xfc) == 0xf8)
+ len = 5;
+ else if ((*s & 0xfe) == 0xfc)
+ len = 6;
+#endif
+ else
+ len = 1;
+ return len;
+}
+
+/*
+ * This is an implementation of wcwidth() and wcswidth() as defined in
+ * "The Single UNIX Specification, Version 2, The Open Group, 1997"
+ * <http://www.unix.org/online.html>
+ *
+ * Markus Kuhn -- 2001-09-08 -- public domain
+ *
+ * customised for PostgreSQL
+ *
+ * original available at : http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
+ */
+
+struct mbinterval
+{
+ unsigned int first;
+ unsigned int last;
+};
+
+/* auxiliary function for binary search in interval table */
+static int
+mbbisearch(pg_wchar ucs, const struct mbinterval *table, int max)
+{
+ int min = 0;
+ int mid;
+
+ if (ucs < table[0].first || ucs > table[max].last)
+ return 0;
+ while (max >= min)
+ {
+ mid = (min + max) / 2;
+ if (ucs > table[mid].last)
+ min = mid + 1;
+ else if (ucs < table[mid].first)
+ max = mid - 1;
+ else
+ return 1;
+ }
+
+ return 0;
+}
+
+
+/* The following functions define the column width of an ISO 10646
+ * character as follows:
+ *
+ * - The null character (U+0000) has a column width of 0.
+ *
+ * - Other C0/C1 control characters and DEL will lead to a return
+ * value of -1.
+ *
+ * - Non-spacing and enclosing combining characters (general
+ * category code Mn, Me or Cf in the Unicode database) have a
+ * column width of 0.
+ *
+ * - Spacing characters in the East Asian Wide (W) or East Asian
+ * FullWidth (F) category as defined in Unicode Technical
+ * Report #11 have a column width of 2.
+ *
+ * - All remaining characters (including all printable
+ * ISO 8859-1 and WGL4 characters, Unicode control characters,
+ * etc.) have a column width of 1.
+ *
+ * This implementation assumes that wchar_t characters are encoded
+ * in ISO 10646.
+ */
+
+static int
+ucs_wcwidth(pg_wchar ucs)
+{
+#include "common/unicode_nonspacing_table.h"
+#include "common/unicode_east_asian_fw_table.h"
+
+ /* test for 8-bit control characters */
+ if (ucs == 0)
+ return 0;
+
+ if (ucs < 0x20 || (ucs >= 0x7f && ucs < 0xa0) || ucs > 0x0010ffff)
+ return -1;
+
+ /*
+ * binary search in table of non-spacing characters
+ *
+ * XXX: In the official Unicode sources, it is possible for a character to
+ * be described as both non-spacing and wide at the same time. As of
+ * Unicode 13.0, treating the non-spacing property as the determining
+ * factor for display width leads to the correct behavior, so do that
+ * search first.
+ */
+ if (mbbisearch(ucs, nonspacing,
+ sizeof(nonspacing) / sizeof(struct mbinterval) - 1))
+ return 0;
+
+ /* binary search in table of wide characters */
+ if (mbbisearch(ucs, east_asian_fw,
+ sizeof(east_asian_fw) / sizeof(struct mbinterval) - 1))
+ return 2;
+
+ return 1;
+}
+
+/*
+ * Convert a UTF-8 character to a Unicode code point.
+ * This is a one-character version of pg_utf2wchar_with_len.
+ *
+ * No error checks here, c must point to a long-enough string.
+ */
+pg_wchar
+utf8_to_unicode(const unsigned char *c)
+{
+ if ((*c & 0x80) == 0)
+ return (pg_wchar) c[0];
+ else if ((*c & 0xe0) == 0xc0)
+ return (pg_wchar) (((c[0] & 0x1f) << 6) |
+ (c[1] & 0x3f));
+ else if ((*c & 0xf0) == 0xe0)
+ return (pg_wchar) (((c[0] & 0x0f) << 12) |
+ ((c[1] & 0x3f) << 6) |
+ (c[2] & 0x3f));
+ else if ((*c & 0xf8) == 0xf0)
+ return (pg_wchar) (((c[0] & 0x07) << 18) |
+ ((c[1] & 0x3f) << 12) |
+ ((c[2] & 0x3f) << 6) |
+ (c[3] & 0x3f));
+ else
+ /* that is an invalid code on purpose */
+ return 0xffffffff;
+}
+
+static int
+pg_utf_dsplen(const unsigned char *s)
+{
+ return ucs_wcwidth(utf8_to_unicode(s));
+}
+
+/*
+ * convert mule internal code to pg_wchar
+ * caller should allocate enough space for "to"
+ * len: length of from.
+ * "from" not necessarily null terminated.
+ */
+static int
+pg_mule2wchar_with_len(const unsigned char *from, pg_wchar *to, int len)
+{
+ int cnt = 0;
+
+ while (len > 0 && *from)
+ {
+ if (IS_LC1(*from) && len >= 2)
+ {
+ *to = *from++ << 16;
+ *to |= *from++;
+ len -= 2;
+ }
+ else if (IS_LCPRV1(*from) && len >= 3)
+ {
+ from++;
+ *to = *from++ << 16;
+ *to |= *from++;
+ len -= 3;
+ }
+ else if (IS_LC2(*from) && len >= 3)
+ {
+ *to = *from++ << 16;
+ *to |= *from++ << 8;
+ *to |= *from++;
+ len -= 3;
+ }
+ else if (IS_LCPRV2(*from) && len >= 4)
+ {
+ from++;
+ *to = *from++ << 16;
+ *to |= *from++ << 8;
+ *to |= *from++;
+ len -= 4;
+ }
+ else
+ { /* assume ASCII */
+ *to = (unsigned char) *from++;
+ len--;
+ }
+ to++;
+ cnt++;
+ }
+ *to = 0;
+ return cnt;
+}
+
+/*
+ * convert pg_wchar to mule internal code
+ * caller should allocate enough space for "to"
+ * len: length of from.
+ * "from" not necessarily null terminated.
+ */
+static int
+pg_wchar2mule_with_len(const pg_wchar *from, unsigned char *to, int len)
+{
+ int cnt = 0;
+
+ while (len > 0 && *from)
+ {
+ unsigned char lb;
+
+ lb = (*from >> 16) & 0xff;
+ if (IS_LC1(lb))
+ {
+ *to++ = lb;
+ *to++ = *from & 0xff;
+ cnt += 2;
+ }
+ else if (IS_LC2(lb))
+ {
+ *to++ = lb;
+ *to++ = (*from >> 8) & 0xff;
+ *to++ = *from & 0xff;
+ cnt += 3;
+ }
+ else if (IS_LCPRV1_A_RANGE(lb))
+ {
+ *to++ = LCPRV1_A;
+ *to++ = lb;
+ *to++ = *from & 0xff;
+ cnt += 3;
+ }
+ else if (IS_LCPRV1_B_RANGE(lb))
+ {
+ *to++ = LCPRV1_B;
+ *to++ = lb;
+ *to++ = *from & 0xff;
+ cnt += 3;
+ }
+ else if (IS_LCPRV2_A_RANGE(lb))
+ {
+ *to++ = LCPRV2_A;
+ *to++ = lb;
+ *to++ = (*from >> 8) & 0xff;
+ *to++ = *from & 0xff;
+ cnt += 4;
+ }
+ else if (IS_LCPRV2_B_RANGE(lb))
+ {
+ *to++ = LCPRV2_B;
+ *to++ = lb;
+ *to++ = (*from >> 8) & 0xff;
+ *to++ = *from & 0xff;
+ cnt += 4;
+ }
+ else
+ {
+ *to++ = *from & 0xff;
+ cnt += 1;
+ }
+ from++;
+ len--;
+ }
+ *to = 0;
+ return cnt;
+}
+
+/* exported for direct use by conv.c */
+int
+pg_mule_mblen(const unsigned char *s)
+{
+ int len;
+
+ if (IS_LC1(*s))
+ len = 2;
+ else if (IS_LCPRV1(*s))
+ len = 3;
+ else if (IS_LC2(*s))
+ len = 3;
+ else if (IS_LCPRV2(*s))
+ len = 4;
+ else
+ len = 1; /* assume ASCII */
+ return len;
+}
+
+static int
+pg_mule_dsplen(const unsigned char *s)
+{
+ int len;
+
+ /*
+ * Note: it's not really appropriate to assume that all multibyte charsets
+ * are double-wide on screen. But this seems an okay approximation for
+ * the MULE charsets we currently support.
+ */
+
+ if (IS_LC1(*s))
+ len = 1;
+ else if (IS_LCPRV1(*s))
+ len = 1;
+ else if (IS_LC2(*s))
+ len = 2;
+ else if (IS_LCPRV2(*s))
+ len = 2;
+ else
+ len = 1; /* assume ASCII */
+
+ return len;
+}
+
+/*
+ * ISO8859-1
+ */
+static int
+pg_latin12wchar_with_len(const unsigned char *from, pg_wchar *to, int len)
+{
+ int cnt = 0;
+
+ while (len > 0 && *from)
+ {
+ *to++ = *from++;
+ len--;
+ cnt++;
+ }
+ *to = 0;
+ return cnt;
+}
+
+/*
+ * Trivial conversion from pg_wchar to single byte encoding. Just ignores
+ * high bits.
+ * caller should allocate enough space for "to"
+ * len: length of from.
+ * "from" not necessarily null terminated.
+ */
+static int
+pg_wchar2single_with_len(const pg_wchar *from, unsigned char *to, int len)
+{
+ int cnt = 0;
+
+ while (len > 0 && *from)
+ {
+ *to++ = *from++;
+ len--;
+ cnt++;
+ }
+ *to = 0;
+ return cnt;
+}
+
+static int
+pg_latin1_mblen(const unsigned char *s)
+{
+ return 1;
+}
+
+static int
+pg_latin1_dsplen(const unsigned char *s)
+{
+ return pg_ascii_dsplen(s);
+}
+
+/*
+ * SJIS
+ */
+static int
+pg_sjis_mblen(const unsigned char *s)
+{
+ int len;
+
+ if (*s >= 0xa1 && *s <= 0xdf)
+ len = 1; /* 1 byte kana? */
+ else if (IS_HIGHBIT_SET(*s))
+ len = 2; /* kanji? */
+ else
+ len = 1; /* should be ASCII */
+ return len;
+}
+
+static int
+pg_sjis_dsplen(const unsigned char *s)
+{
+ int len;
+
+ if (*s >= 0xa1 && *s <= 0xdf)
+ len = 1; /* 1 byte kana? */
+ else if (IS_HIGHBIT_SET(*s))
+ len = 2; /* kanji? */
+ else
+ len = pg_ascii_dsplen(s); /* should be ASCII */
+ return len;
+}
+
+/*
+ * Big5
+ */
+static int
+pg_big5_mblen(const unsigned char *s)
+{
+ int len;
+
+ if (IS_HIGHBIT_SET(*s))
+ len = 2; /* kanji? */
+ else
+ len = 1; /* should be ASCII */
+ return len;
+}
+
+static int
+pg_big5_dsplen(const unsigned char *s)
+{
+ int len;
+
+ if (IS_HIGHBIT_SET(*s))
+ len = 2; /* kanji? */
+ else
+ len = pg_ascii_dsplen(s); /* should be ASCII */
+ return len;
+}
+
+/*
+ * GBK
+ */
+static int
+pg_gbk_mblen(const unsigned char *s)
+{
+ int len;
+
+ if (IS_HIGHBIT_SET(*s))
+ len = 2; /* kanji? */
+ else
+ len = 1; /* should be ASCII */
+ return len;
+}
+
+static int
+pg_gbk_dsplen(const unsigned char *s)
+{
+ int len;
+
+ if (IS_HIGHBIT_SET(*s))
+ len = 2; /* kanji? */
+ else
+ len = pg_ascii_dsplen(s); /* should be ASCII */
+ return len;
+}
+
+/*
+ * UHC
+ */
+static int
+pg_uhc_mblen(const unsigned char *s)
+{
+ int len;
+
+ if (IS_HIGHBIT_SET(*s))
+ len = 2; /* 2byte? */
+ else
+ len = 1; /* should be ASCII */
+ return len;
+}
+
+static int
+pg_uhc_dsplen(const unsigned char *s)
+{
+ int len;
+
+ if (IS_HIGHBIT_SET(*s))
+ len = 2; /* 2byte? */
+ else
+ len = pg_ascii_dsplen(s); /* should be ASCII */
+ return len;
+}
+
+/*
+ * GB18030
+ * Added by Bill Huang <bhuang@redhat.com>,<bill_huanghb@ybb.ne.jp>
+ */
+
+/*
+ * Unlike all other mblen() functions, this also looks at the second byte of
+ * the input. However, if you only pass the first byte of a multi-byte
+ * string, and \0 as the second byte, this still works in a predictable way:
+ * a 4-byte character will be reported as two 2-byte characters. That's
+ * enough for all current uses, as a client-only encoding. It works that
+ * way, because in any valid 4-byte GB18030-encoded character, the third and
+ * fourth byte look like a 2-byte encoded character, when looked at
+ * separately.
+ */
+static int
+pg_gb18030_mblen(const unsigned char *s)
+{
+ int len;
+
+ if (!IS_HIGHBIT_SET(*s))
+ len = 1; /* ASCII */
+ else if (*(s + 1) >= 0x30 && *(s + 1) <= 0x39)
+ len = 4;
+ else
+ len = 2;
+ return len;
+}
+
+static int
+pg_gb18030_dsplen(const unsigned char *s)
+{
+ int len;
+
+ if (IS_HIGHBIT_SET(*s))
+ len = 2;
+ else
+ len = pg_ascii_dsplen(s); /* ASCII */
+ return len;
+}
+
+/*
+ *-------------------------------------------------------------------
+ * multibyte sequence validators
+ *
+ * The verifychar functions accept "s", a pointer to the first byte of a
+ * string, and "len", the remaining length of the string. If there is a
+ * validly encoded character beginning at *s, return its length in bytes;
+ * else return -1.
+ *
+ * The verifystr functions also accept "s", a pointer to a string and "len",
+ * the length of the string. They verify the whole string, and return the
+ * number of input bytes (<= len) that are valid. In other words, if the
+ * whole string is valid, verifystr returns "len", otherwise it returns the
+ * byte offset of the first invalid character. The verifystr functions must
+ * test for and reject zeroes in the input.
+ *
+ * The verifychar functions can assume that len > 0 and that *s != '\0', but
+ * they must test for and reject zeroes in any additional bytes of a
+ * multibyte character. Note that this definition allows the function for a
+ * single-byte encoding to be just "return 1".
+ *-------------------------------------------------------------------
+ */
+static int
+pg_ascii_verifychar(const unsigned char *s, int len)
+{
+ return 1;
+}
+
+static int
+pg_ascii_verifystr(const unsigned char *s, int len)
+{
+ const unsigned char *nullpos = memchr(s, 0, len);
+
+ if (nullpos == NULL)
+ return len;
+ else
+ return nullpos - s;
+}
+
+#define IS_EUC_RANGE_VALID(c) ((c) >= 0xa1 && (c) <= 0xfe)
+
+static int
+pg_eucjp_verifychar(const unsigned char *s, int len)
+{
+ int l;
+ unsigned char c1,
+ c2;
+
+ c1 = *s++;
+
+ switch (c1)
+ {
+ case SS2: /* JIS X 0201 */
+ l = 2;
+ if (l > len)
+ return -1;
+ c2 = *s++;
+ if (c2 < 0xa1 || c2 > 0xdf)
+ return -1;
+ break;
+
+ case SS3: /* JIS X 0212 */
+ l = 3;
+ if (l > len)
+ return -1;
+ c2 = *s++;
+ if (!IS_EUC_RANGE_VALID(c2))
+ return -1;
+ c2 = *s++;
+ if (!IS_EUC_RANGE_VALID(c2))
+ return -1;
+ break;
+
+ default:
+ if (IS_HIGHBIT_SET(c1)) /* JIS X 0208? */
+ {
+ l = 2;
+ if (l > len)
+ return -1;
+ if (!IS_EUC_RANGE_VALID(c1))
+ return -1;
+ c2 = *s++;
+ if (!IS_EUC_RANGE_VALID(c2))
+ return -1;
+ }
+ else
+ /* must be ASCII */
+ {
+ l = 1;
+ }
+ break;
+ }
+
+ return l;
+}
+
+static int
+pg_eucjp_verifystr(const unsigned char *s, int len)
+{
+ const unsigned char *start = s;
+
+ while (len > 0)
+ {
+ int l;
+
+ /* fast path for ASCII-subset characters */
+ if (!IS_HIGHBIT_SET(*s))
+ {
+ if (*s == '\0')
+ break;
+ l = 1;
+ }
+ else
+ {
+ l = pg_eucjp_verifychar(s, len);
+ if (l == -1)
+ break;
+ }
+ s += l;
+ len -= l;
+ }
+
+ return s - start;
+}
+
+static int
+pg_euckr_verifychar(const unsigned char *s, int len)
+{
+ int l;
+ unsigned char c1,
+ c2;
+
+ c1 = *s++;
+
+ if (IS_HIGHBIT_SET(c1))
+ {
+ l = 2;
+ if (l > len)
+ return -1;
+ if (!IS_EUC_RANGE_VALID(c1))
+ return -1;
+ c2 = *s++;
+ if (!IS_EUC_RANGE_VALID(c2))
+ return -1;
+ }
+ else
+ /* must be ASCII */
+ {
+ l = 1;
+ }
+
+ return l;
+}
+
+static int
+pg_euckr_verifystr(const unsigned char *s, int len)
+{
+ const unsigned char *start = s;
+
+ while (len > 0)
+ {
+ int l;
+
+ /* fast path for ASCII-subset characters */
+ if (!IS_HIGHBIT_SET(*s))
+ {
+ if (*s == '\0')
+ break;
+ l = 1;
+ }
+ else
+ {
+ l = pg_euckr_verifychar(s, len);
+ if (l == -1)
+ break;
+ }
+ s += l;
+ len -= l;
+ }
+
+ return s - start;
+}
+
+/* EUC-CN byte sequences are exactly same as EUC-KR */
+#define pg_euccn_verifychar pg_euckr_verifychar
+#define pg_euccn_verifystr pg_euckr_verifystr
+
+static int
+pg_euctw_verifychar(const unsigned char *s, int len)
+{
+ int l;
+ unsigned char c1,
+ c2;
+
+ c1 = *s++;
+
+ switch (c1)
+ {
+ case SS2: /* CNS 11643 Plane 1-7 */
+ l = 4;
+ if (l > len)
+ return -1;
+ c2 = *s++;
+ if (c2 < 0xa1 || c2 > 0xa7)
+ return -1;
+ c2 = *s++;
+ if (!IS_EUC_RANGE_VALID(c2))
+ return -1;
+ c2 = *s++;
+ if (!IS_EUC_RANGE_VALID(c2))
+ return -1;
+ break;
+
+ case SS3: /* unused */
+ return -1;
+
+ default:
+ if (IS_HIGHBIT_SET(c1)) /* CNS 11643 Plane 1 */
+ {
+ l = 2;
+ if (l > len)
+ return -1;
+ /* no further range check on c1? */
+ c2 = *s++;
+ if (!IS_EUC_RANGE_VALID(c2))
+ return -1;
+ }
+ else
+ /* must be ASCII */
+ {
+ l = 1;
+ }
+ break;
+ }
+ return l;
+}
+
+static int
+pg_euctw_verifystr(const unsigned char *s, int len)
+{
+ const unsigned char *start = s;
+
+ while (len > 0)
+ {
+ int l;
+
+ /* fast path for ASCII-subset characters */
+ if (!IS_HIGHBIT_SET(*s))
+ {
+ if (*s == '\0')
+ break;
+ l = 1;
+ }
+ else
+ {
+ l = pg_euctw_verifychar(s, len);
+ if (l == -1)
+ break;
+ }
+ s += l;
+ len -= l;
+ }
+
+ return s - start;
+}
+
+static int
+pg_johab_verifychar(const unsigned char *s, int len)
+{
+ int l,
+ mbl;
+ unsigned char c;
+
+ l = mbl = pg_johab_mblen(s);
+
+ if (len < l)
+ return -1;
+
+ if (!IS_HIGHBIT_SET(*s))
+ return mbl;
+
+ while (--l > 0)
+ {
+ c = *++s;
+ if (!IS_EUC_RANGE_VALID(c))
+ return -1;
+ }
+ return mbl;
+}
+
+static int
+pg_johab_verifystr(const unsigned char *s, int len)
+{
+ const unsigned char *start = s;
+
+ while (len > 0)
+ {
+ int l;
+
+ /* fast path for ASCII-subset characters */
+ if (!IS_HIGHBIT_SET(*s))
+ {
+ if (*s == '\0')
+ break;
+ l = 1;
+ }
+ else
+ {
+ l = pg_johab_verifychar(s, len);
+ if (l == -1)
+ break;
+ }
+ s += l;
+ len -= l;
+ }
+
+ return s - start;
+}
+
+static int
+pg_mule_verifychar(const unsigned char *s, int len)
+{
+ int l,
+ mbl;
+ unsigned char c;
+
+ l = mbl = pg_mule_mblen(s);
+
+ if (len < l)
+ return -1;
+
+ while (--l > 0)
+ {
+ c = *++s;
+ if (!IS_HIGHBIT_SET(c))
+ return -1;
+ }
+ return mbl;
+}
+
+static int
+pg_mule_verifystr(const unsigned char *s, int len)
+{
+ const unsigned char *start = s;
+
+ while (len > 0)
+ {
+ int l;
+
+ /* fast path for ASCII-subset characters */
+ if (!IS_HIGHBIT_SET(*s))
+ {
+ if (*s == '\0')
+ break;
+ l = 1;
+ }
+ else
+ {
+ l = pg_mule_verifychar(s, len);
+ if (l == -1)
+ break;
+ }
+ s += l;
+ len -= l;
+ }
+
+ return s - start;
+}
+
+static int
+pg_latin1_verifychar(const unsigned char *s, int len)
+{
+ return 1;
+}
+
+static int
+pg_latin1_verifystr(const unsigned char *s, int len)
+{
+ const unsigned char *nullpos = memchr(s, 0, len);
+
+ if (nullpos == NULL)
+ return len;
+ else
+ return nullpos - s;
+}
+
+static int
+pg_sjis_verifychar(const unsigned char *s, int len)
+{
+ int l,
+ mbl;
+ unsigned char c1,
+ c2;
+
+ l = mbl = pg_sjis_mblen(s);
+
+ if (len < l)
+ return -1;
+
+ if (l == 1) /* pg_sjis_mblen already verified it */
+ return mbl;
+
+ c1 = *s++;
+ c2 = *s;
+ if (!ISSJISHEAD(c1) || !ISSJISTAIL(c2))
+ return -1;
+ return mbl;
+}
+
+static int
+pg_sjis_verifystr(const unsigned char *s, int len)
+{
+ const unsigned char *start = s;
+
+ while (len > 0)
+ {
+ int l;
+
+ /* fast path for ASCII-subset characters */
+ if (!IS_HIGHBIT_SET(*s))
+ {
+ if (*s == '\0')
+ break;
+ l = 1;
+ }
+ else
+ {
+ l = pg_sjis_verifychar(s, len);
+ if (l == -1)
+ break;
+ }
+ s += l;
+ len -= l;
+ }
+
+ return s - start;
+}
+
+static int
+pg_big5_verifychar(const unsigned char *s, int len)
+{
+ int l,
+ mbl;
+
+ l = mbl = pg_big5_mblen(s);
+
+ if (len < l)
+ return -1;
+
+ while (--l > 0)
+ {
+ if (*++s == '\0')
+ return -1;
+ }
+
+ return mbl;
+}
+
+static int
+pg_big5_verifystr(const unsigned char *s, int len)
+{
+ const unsigned char *start = s;
+
+ while (len > 0)
+ {
+ int l;
+
+ /* fast path for ASCII-subset characters */
+ if (!IS_HIGHBIT_SET(*s))
+ {
+ if (*s == '\0')
+ break;
+ l = 1;
+ }
+ else
+ {
+ l = pg_big5_verifychar(s, len);
+ if (l == -1)
+ break;
+ }
+ s += l;
+ len -= l;
+ }
+
+ return s - start;
+}
+
+static int
+pg_gbk_verifychar(const unsigned char *s, int len)
+{
+ int l,
+ mbl;
+
+ l = mbl = pg_gbk_mblen(s);
+
+ if (len < l)
+ return -1;
+
+ while (--l > 0)
+ {
+ if (*++s == '\0')
+ return -1;
+ }
+
+ return mbl;
+}
+
+static int
+pg_gbk_verifystr(const unsigned char *s, int len)
+{
+ const unsigned char *start = s;
+
+ while (len > 0)
+ {
+ int l;
+
+ /* fast path for ASCII-subset characters */
+ if (!IS_HIGHBIT_SET(*s))
+ {
+ if (*s == '\0')
+ break;
+ l = 1;
+ }
+ else
+ {
+ l = pg_gbk_verifychar(s, len);
+ if (l == -1)
+ break;
+ }
+ s += l;
+ len -= l;
+ }
+
+ return s - start;
+}
+
+static int
+pg_uhc_verifychar(const unsigned char *s, int len)
+{
+ int l,
+ mbl;
+
+ l = mbl = pg_uhc_mblen(s);
+
+ if (len < l)
+ return -1;
+
+ while (--l > 0)
+ {
+ if (*++s == '\0')
+ return -1;
+ }
+
+ return mbl;
+}
+
+static int
+pg_uhc_verifystr(const unsigned char *s, int len)
+{
+ const unsigned char *start = s;
+
+ while (len > 0)
+ {
+ int l;
+
+ /* fast path for ASCII-subset characters */
+ if (!IS_HIGHBIT_SET(*s))
+ {
+ if (*s == '\0')
+ break;
+ l = 1;
+ }
+ else
+ {
+ l = pg_uhc_verifychar(s, len);
+ if (l == -1)
+ break;
+ }
+ s += l;
+ len -= l;
+ }
+
+ return s - start;
+}
+
+static int
+pg_gb18030_verifychar(const unsigned char *s, int len)
+{
+ int l;
+
+ if (!IS_HIGHBIT_SET(*s))
+ l = 1; /* ASCII */
+ else if (len >= 4 && *(s + 1) >= 0x30 && *(s + 1) <= 0x39)
+ {
+ /* Should be 4-byte, validate remaining bytes */
+ if (*s >= 0x81 && *s <= 0xfe &&
+ *(s + 2) >= 0x81 && *(s + 2) <= 0xfe &&
+ *(s + 3) >= 0x30 && *(s + 3) <= 0x39)
+ l = 4;
+ else
+ l = -1;
+ }
+ else if (len >= 2 && *s >= 0x81 && *s <= 0xfe)
+ {
+ /* Should be 2-byte, validate */
+ if ((*(s + 1) >= 0x40 && *(s + 1) <= 0x7e) ||
+ (*(s + 1) >= 0x80 && *(s + 1) <= 0xfe))
+ l = 2;
+ else
+ l = -1;
+ }
+ else
+ l = -1;
+ return l;
+}
+
+static int
+pg_gb18030_verifystr(const unsigned char *s, int len)
+{
+ const unsigned char *start = s;
+
+ while (len > 0)
+ {
+ int l;
+
+ /* fast path for ASCII-subset characters */
+ if (!IS_HIGHBIT_SET(*s))
+ {
+ if (*s == '\0')
+ break;
+ l = 1;
+ }
+ else
+ {
+ l = pg_gb18030_verifychar(s, len);
+ if (l == -1)
+ break;
+ }
+ s += l;
+ len -= l;
+ }
+
+ return s - start;
+}
+
+static int
+pg_utf8_verifychar(const unsigned char *s, int len)
+{
+ int l;
+
+ if ((*s & 0x80) == 0)
+ {
+ if (*s == '\0')
+ return -1;
+ return 1;
+ }
+ else if ((*s & 0xe0) == 0xc0)
+ l = 2;
+ else if ((*s & 0xf0) == 0xe0)
+ l = 3;
+ else if ((*s & 0xf8) == 0xf0)
+ l = 4;
+ else
+ l = 1;
+
+ if (l > len)
+ return -1;
+
+ if (!pg_utf8_islegal(s, l))
+ return -1;
+
+ return l;
+}
+
+/*
+ * The fast path of the UTF-8 verifier uses a deterministic finite automaton
+ * (DFA) for multibyte characters. In a traditional table-driven DFA, the
+ * input byte and current state are used to compute an index into an array of
+ * state transitions. Since the address of the next transition is dependent
+ * on this computation, there is latency in executing the load instruction,
+ * and the CPU is not kept busy.
+ *
+ * Instead, we use a "shift-based" DFA as described by Per Vognsen:
+ *
+ * https://gist.github.com/pervognsen/218ea17743e1442e59bb60d29b1aa725
+ *
+ * In a shift-based DFA, the input byte is an index into array of integers
+ * whose bit pattern encodes the state transitions. To compute the next
+ * state, we simply right-shift the integer by the current state and apply a
+ * mask. In this scheme, the address of the transition only depends on the
+ * input byte, so there is better pipelining.
+ *
+ * The naming convention for states and transitions was adopted from a UTF-8
+ * to UTF-16/32 transcoder, whose table is reproduced below:
+ *
+ * https://github.com/BobSteagall/utf_utils/blob/6b7a465265de2f5fa6133d653df0c9bdd73bbcf8/src/utf_utils.cpp
+ *
+ * ILL ASC CR1 CR2 CR3 L2A L3A L3B L3C L4A L4B L4C CLASS / STATE
+ * ==========================================================================
+ * err, END, err, err, err, CS1, P3A, CS2, P3B, P4A, CS3, P4B, | BGN/END
+ * err, err, err, err, err, err, err, err, err, err, err, err, | ERR
+ * |
+ * err, err, END, END, END, err, err, err, err, err, err, err, | CS1
+ * err, err, CS1, CS1, CS1, err, err, err, err, err, err, err, | CS2
+ * err, err, CS2, CS2, CS2, err, err, err, err, err, err, err, | CS3
+ * |
+ * err, err, err, err, CS1, err, err, err, err, err, err, err, | P3A
+ * err, err, CS1, CS1, err, err, err, err, err, err, err, err, | P3B
+ * |
+ * err, err, err, CS2, CS2, err, err, err, err, err, err, err, | P4A
+ * err, err, CS2, err, err, err, err, err, err, err, err, err, | P4B
+ *
+ * In the most straightforward implementation, a shift-based DFA for UTF-8
+ * requires 64-bit integers to encode the transitions, but with an SMT solver
+ * it's possible to find state numbers such that the transitions fit within
+ * 32-bit integers, as Dougall Johnson demonstrated:
+ *
+ * https://gist.github.com/dougallj/166e326de6ad4cf2c94be97a204c025f
+ *
+ * This packed representation is the reason for the seemingly odd choice of
+ * state values below.
+ */
+
+/* Error */
+#define ERR 0
+/* Begin */
+#define BGN 11
+/* Continuation states, expect 1/2/3 continuation bytes */
+#define CS1 16
+#define CS2 1
+#define CS3 5
+/* Partial states, where the first continuation byte has a restricted range */
+#define P3A 6 /* Lead was E0, check for 3-byte overlong */
+#define P3B 20 /* Lead was ED, check for surrogate */
+#define P4A 25 /* Lead was F0, check for 4-byte overlong */
+#define P4B 30 /* Lead was F4, check for too-large */
+/* Begin and End are the same state */
+#define END BGN
+
+/* the encoded state transitions for the lookup table */
+
+/* ASCII */
+#define ASC (END << BGN)
+/* 2-byte lead */
+#define L2A (CS1 << BGN)
+/* 3-byte lead */
+#define L3A (P3A << BGN)
+#define L3B (CS2 << BGN)
+#define L3C (P3B << BGN)
+/* 4-byte lead */
+#define L4A (P4A << BGN)
+#define L4B (CS3 << BGN)
+#define L4C (P4B << BGN)
+/* continuation byte */
+#define CR1 (END << CS1) | (CS1 << CS2) | (CS2 << CS3) | (CS1 << P3B) | (CS2 << P4B)
+#define CR2 (END << CS1) | (CS1 << CS2) | (CS2 << CS3) | (CS1 << P3B) | (CS2 << P4A)
+#define CR3 (END << CS1) | (CS1 << CS2) | (CS2 << CS3) | (CS1 << P3A) | (CS2 << P4A)
+/* invalid byte */
+#define ILL ERR
+
+static const uint32 Utf8Transition[256] =
+{
+ /* ASCII */
+
+ ILL, ASC, ASC, ASC, ASC, ASC, ASC, ASC,
+ ASC, ASC, ASC, ASC, ASC, ASC, ASC, ASC,
+ ASC, ASC, ASC, ASC, ASC, ASC, ASC, ASC,
+ ASC, ASC, ASC, ASC, ASC, ASC, ASC, ASC,
+
+ ASC, ASC, ASC, ASC, ASC, ASC, ASC, ASC,
+ ASC, ASC, ASC, ASC, ASC, ASC, ASC, ASC,
+ ASC, ASC, ASC, ASC, ASC, ASC, ASC, ASC,
+ ASC, ASC, ASC, ASC, ASC, ASC, ASC, ASC,
+
+ ASC, ASC, ASC, ASC, ASC, ASC, ASC, ASC,
+ ASC, ASC, ASC, ASC, ASC, ASC, ASC, ASC,
+ ASC, ASC, ASC, ASC, ASC, ASC, ASC, ASC,
+ ASC, ASC, ASC, ASC, ASC, ASC, ASC, ASC,
+
+ ASC, ASC, ASC, ASC, ASC, ASC, ASC, ASC,
+ ASC, ASC, ASC, ASC, ASC, ASC, ASC, ASC,
+ ASC, ASC, ASC, ASC, ASC, ASC, ASC, ASC,
+ ASC, ASC, ASC, ASC, ASC, ASC, ASC, ASC,
+
+ /* continuation bytes */
+
+ /* 80..8F */
+ CR1, CR1, CR1, CR1, CR1, CR1, CR1, CR1,
+ CR1, CR1, CR1, CR1, CR1, CR1, CR1, CR1,
+
+ /* 90..9F */
+ CR2, CR2, CR2, CR2, CR2, CR2, CR2, CR2,
+ CR2, CR2, CR2, CR2, CR2, CR2, CR2, CR2,
+
+ /* A0..BF */
+ CR3, CR3, CR3, CR3, CR3, CR3, CR3, CR3,
+ CR3, CR3, CR3, CR3, CR3, CR3, CR3, CR3,
+ CR3, CR3, CR3, CR3, CR3, CR3, CR3, CR3,
+ CR3, CR3, CR3, CR3, CR3, CR3, CR3, CR3,
+
+ /* leading bytes */
+
+ /* C0..DF */
+ ILL, ILL, L2A, L2A, L2A, L2A, L2A, L2A,
+ L2A, L2A, L2A, L2A, L2A, L2A, L2A, L2A,
+ L2A, L2A, L2A, L2A, L2A, L2A, L2A, L2A,
+ L2A, L2A, L2A, L2A, L2A, L2A, L2A, L2A,
+
+ /* E0..EF */
+ L3A, L3B, L3B, L3B, L3B, L3B, L3B, L3B,
+ L3B, L3B, L3B, L3B, L3B, L3C, L3B, L3B,
+
+ /* F0..FF */
+ L4A, L4B, L4B, L4B, L4C, ILL, ILL, ILL,
+ ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL
+};
+
+static void
+utf8_advance(const unsigned char *s, uint32 *state, int len)
+{
+ /* Note: We deliberately don't check the state's value here. */
+ while (len > 0)
+ {
+ /*
+ * It's important that the mask value is 31: In most instruction sets,
+ * a shift by a 32-bit operand is understood to be a shift by its mod
+ * 32, so the compiler should elide the mask operation.
+ */
+ *state = Utf8Transition[*s++] >> (*state & 31);
+ len--;
+ }
+
+ *state &= 31;
+}
+
+static int
+pg_utf8_verifystr(const unsigned char *s, int len)
+{
+ const unsigned char *start = s;
+ const int orig_len = len;
+ uint32 state = BGN;
+
+/*
+ * With a stride of two vector widths, gcc will unroll the loop. Even if
+ * the compiler can unroll a longer loop, it's not worth it because we
+ * must fall back to the byte-wise algorithm if we find any non-ASCII.
+ */
+#define STRIDE_LENGTH (2 * sizeof(Vector8))
+
+ if (len >= STRIDE_LENGTH)
+ {
+ while (len >= STRIDE_LENGTH)
+ {
+ /*
+ * If the chunk is all ASCII, we can skip the full UTF-8 check,
+ * but we must first check for a non-END state, which means the
+ * previous chunk ended in the middle of a multibyte sequence.
+ */
+ if (state != END || !is_valid_ascii(s, STRIDE_LENGTH))
+ utf8_advance(s, &state, STRIDE_LENGTH);
+
+ s += STRIDE_LENGTH;
+ len -= STRIDE_LENGTH;
+ }
+
+ /* The error state persists, so we only need to check for it here. */
+ if (state == ERR)
+ {
+ /*
+ * Start over from the beginning with the slow path so we can
+ * count the valid bytes.
+ */
+ len = orig_len;
+ s = start;
+ }
+ else if (state != END)
+ {
+ /*
+ * The fast path exited in the middle of a multibyte sequence.
+ * Walk backwards to find the leading byte so that the slow path
+ * can resume checking from there. We must always backtrack at
+ * least one byte, since the current byte could be e.g. an ASCII
+ * byte after a 2-byte lead, which is invalid.
+ */
+ do
+ {
+ Assert(s > start);
+ s--;
+ len++;
+ Assert(IS_HIGHBIT_SET(*s));
+ } while (pg_utf_mblen(s) <= 1);
+ }
+ }
+
+ /* check remaining bytes */
+ while (len > 0)
+ {
+ int l;
+
+ /* fast path for ASCII-subset characters */
+ if (!IS_HIGHBIT_SET(*s))
+ {
+ if (*s == '\0')
+ break;
+ l = 1;
+ }
+ else
+ {
+ l = pg_utf8_verifychar(s, len);
+ if (l == -1)
+ break;
+ }
+ s += l;
+ len -= l;
+ }
+
+ return s - start;
+}
+
+/*
+ * Check for validity of a single UTF-8 encoded character
+ *
+ * This directly implements the rules in RFC3629. The bizarre-looking
+ * restrictions on the second byte are meant to ensure that there isn't
+ * more than one encoding of a given Unicode character point; that is,
+ * you may not use a longer-than-necessary byte sequence with high order
+ * zero bits to represent a character that would fit in fewer bytes.
+ * To do otherwise is to create security hazards (eg, create an apparent
+ * non-ASCII character that decodes to plain ASCII).
+ *
+ * length is assumed to have been obtained by pg_utf_mblen(), and the
+ * caller must have checked that that many bytes are present in the buffer.
+ */
+bool
+pg_utf8_islegal(const unsigned char *source, int length)
+{
+ unsigned char a;
+
+ switch (length)
+ {
+ default:
+ /* reject lengths 5 and 6 for now */
+ return false;
+ case 4:
+ a = source[3];
+ if (a < 0x80 || a > 0xBF)
+ return false;
+ /* FALL THRU */
+ case 3:
+ a = source[2];
+ if (a < 0x80 || a > 0xBF)
+ return false;
+ /* FALL THRU */
+ case 2:
+ a = source[1];
+ switch (*source)
+ {
+ case 0xE0:
+ if (a < 0xA0 || a > 0xBF)
+ return false;
+ break;
+ case 0xED:
+ if (a < 0x80 || a > 0x9F)
+ return false;
+ break;
+ case 0xF0:
+ if (a < 0x90 || a > 0xBF)
+ return false;
+ break;
+ case 0xF4:
+ if (a < 0x80 || a > 0x8F)
+ return false;
+ break;
+ default:
+ if (a < 0x80 || a > 0xBF)
+ return false;
+ break;
+ }
+ /* FALL THRU */
+ case 1:
+ a = *source;
+ if (a >= 0x80 && a < 0xC2)
+ return false;
+ if (a > 0xF4)
+ return false;
+ break;
+ }
+ return true;
+}
+
+
+/*
+ *-------------------------------------------------------------------
+ * encoding info table
+ * XXX must be sorted by the same order as enum pg_enc (in mb/pg_wchar.h)
+ *-------------------------------------------------------------------
+ */
+const pg_wchar_tbl pg_wchar_table[] = {
+ {pg_ascii2wchar_with_len, pg_wchar2single_with_len, pg_ascii_mblen, pg_ascii_dsplen, pg_ascii_verifychar, pg_ascii_verifystr, 1}, /* PG_SQL_ASCII */
+ {pg_eucjp2wchar_with_len, pg_wchar2euc_with_len, pg_eucjp_mblen, pg_eucjp_dsplen, pg_eucjp_verifychar, pg_eucjp_verifystr, 3}, /* PG_EUC_JP */
+ {pg_euccn2wchar_with_len, pg_wchar2euc_with_len, pg_euccn_mblen, pg_euccn_dsplen, pg_euccn_verifychar, pg_euccn_verifystr, 2}, /* PG_EUC_CN */
+ {pg_euckr2wchar_with_len, pg_wchar2euc_with_len, pg_euckr_mblen, pg_euckr_dsplen, pg_euckr_verifychar, pg_euckr_verifystr, 3}, /* PG_EUC_KR */
+ {pg_euctw2wchar_with_len, pg_wchar2euc_with_len, pg_euctw_mblen, pg_euctw_dsplen, pg_euctw_verifychar, pg_euctw_verifystr, 4}, /* PG_EUC_TW */
+ {pg_eucjp2wchar_with_len, pg_wchar2euc_with_len, pg_eucjp_mblen, pg_eucjp_dsplen, pg_eucjp_verifychar, pg_eucjp_verifystr, 3}, /* PG_EUC_JIS_2004 */
+ {pg_utf2wchar_with_len, pg_wchar2utf_with_len, pg_utf_mblen, pg_utf_dsplen, pg_utf8_verifychar, pg_utf8_verifystr, 4}, /* PG_UTF8 */
+ {pg_mule2wchar_with_len, pg_wchar2mule_with_len, pg_mule_mblen, pg_mule_dsplen, pg_mule_verifychar, pg_mule_verifystr, 4}, /* PG_MULE_INTERNAL */
+ {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifychar, pg_latin1_verifystr, 1}, /* PG_LATIN1 */
+ {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifychar, pg_latin1_verifystr, 1}, /* PG_LATIN2 */
+ {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifychar, pg_latin1_verifystr, 1}, /* PG_LATIN3 */
+ {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifychar, pg_latin1_verifystr, 1}, /* PG_LATIN4 */
+ {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifychar, pg_latin1_verifystr, 1}, /* PG_LATIN5 */
+ {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifychar, pg_latin1_verifystr, 1}, /* PG_LATIN6 */
+ {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifychar, pg_latin1_verifystr, 1}, /* PG_LATIN7 */
+ {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifychar, pg_latin1_verifystr, 1}, /* PG_LATIN8 */
+ {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifychar, pg_latin1_verifystr, 1}, /* PG_LATIN9 */
+ {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifychar, pg_latin1_verifystr, 1}, /* PG_LATIN10 */
+ {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifychar, pg_latin1_verifystr, 1}, /* PG_WIN1256 */
+ {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifychar, pg_latin1_verifystr, 1}, /* PG_WIN1258 */
+ {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifychar, pg_latin1_verifystr, 1}, /* PG_WIN866 */
+ {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifychar, pg_latin1_verifystr, 1}, /* PG_WIN874 */
+ {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifychar, pg_latin1_verifystr, 1}, /* PG_KOI8R */
+ {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifychar, pg_latin1_verifystr, 1}, /* PG_WIN1251 */
+ {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifychar, pg_latin1_verifystr, 1}, /* PG_WIN1252 */
+ {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifychar, pg_latin1_verifystr, 1}, /* ISO-8859-5 */
+ {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifychar, pg_latin1_verifystr, 1}, /* ISO-8859-6 */
+ {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifychar, pg_latin1_verifystr, 1}, /* ISO-8859-7 */
+ {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifychar, pg_latin1_verifystr, 1}, /* ISO-8859-8 */
+ {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifychar, pg_latin1_verifystr, 1}, /* PG_WIN1250 */
+ {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifychar, pg_latin1_verifystr, 1}, /* PG_WIN1253 */
+ {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifychar, pg_latin1_verifystr, 1}, /* PG_WIN1254 */
+ {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifychar, pg_latin1_verifystr, 1}, /* PG_WIN1255 */
+ {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifychar, pg_latin1_verifystr, 1}, /* PG_WIN1257 */
+ {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifychar, pg_latin1_verifystr, 1}, /* PG_KOI8U */
+ {0, 0, pg_sjis_mblen, pg_sjis_dsplen, pg_sjis_verifychar, pg_sjis_verifystr, 2}, /* PG_SJIS */
+ {0, 0, pg_big5_mblen, pg_big5_dsplen, pg_big5_verifychar, pg_big5_verifystr, 2}, /* PG_BIG5 */
+ {0, 0, pg_gbk_mblen, pg_gbk_dsplen, pg_gbk_verifychar, pg_gbk_verifystr, 2}, /* PG_GBK */
+ {0, 0, pg_uhc_mblen, pg_uhc_dsplen, pg_uhc_verifychar, pg_uhc_verifystr, 2}, /* PG_UHC */
+ {0, 0, pg_gb18030_mblen, pg_gb18030_dsplen, pg_gb18030_verifychar, pg_gb18030_verifystr, 4}, /* PG_GB18030 */
+ {0, 0, pg_johab_mblen, pg_johab_dsplen, pg_johab_verifychar, pg_johab_verifystr, 3}, /* PG_JOHAB */
+ {0, 0, pg_sjis_mblen, pg_sjis_dsplen, pg_sjis_verifychar, pg_sjis_verifystr, 2} /* PG_SHIFT_JIS_2004 */
+};
+
+/*
+ * Returns the byte length of a multibyte character.
+ *
+ * Caution: when dealing with text that is not certainly valid in the
+ * specified encoding, the result may exceed the actual remaining
+ * string length. Callers that are not prepared to deal with that
+ * should use pg_encoding_mblen_bounded() instead.
+ */
+int
+pg_encoding_mblen(int encoding, const char *mbstr)
+{
+ return (PG_VALID_ENCODING(encoding) ?
+ pg_wchar_table[encoding].mblen((const unsigned char *) mbstr) :
+ pg_wchar_table[PG_SQL_ASCII].mblen((const unsigned char *) mbstr));
+}
+
+/*
+ * Returns the byte length of a multibyte character; but not more than
+ * the distance to end of string.
+ */
+int
+pg_encoding_mblen_bounded(int encoding, const char *mbstr)
+{
+ return strnlen(mbstr, pg_encoding_mblen(encoding, mbstr));
+}
+
+/*
+ * Returns the display length of a multibyte character.
+ */
+int
+pg_encoding_dsplen(int encoding, const char *mbstr)
+{
+ return (PG_VALID_ENCODING(encoding) ?
+ pg_wchar_table[encoding].dsplen((const unsigned char *) mbstr) :
+ pg_wchar_table[PG_SQL_ASCII].dsplen((const unsigned char *) mbstr));
+}
+
+/*
+ * Verify the first multibyte character of the given string.
+ * Return its byte length if good, -1 if bad. (See comments above for
+ * full details of the mbverifychar API.)
+ */
+int
+pg_encoding_verifymbchar(int encoding, const char *mbstr, int len)
+{
+ return (PG_VALID_ENCODING(encoding) ?
+ pg_wchar_table[encoding].mbverifychar((const unsigned char *) mbstr, len) :
+ pg_wchar_table[PG_SQL_ASCII].mbverifychar((const unsigned char *) mbstr, len));
+}
+
+/*
+ * Verify that a string is valid for the given encoding.
+ * Returns the number of input bytes (<= len) that form a valid string.
+ * (See comments above for full details of the mbverifystr API.)
+ */
+int
+pg_encoding_verifymbstr(int encoding, const char *mbstr, int len)
+{
+ return (PG_VALID_ENCODING(encoding) ?
+ pg_wchar_table[encoding].mbverifystr((const unsigned char *) mbstr, len) :
+ pg_wchar_table[PG_SQL_ASCII].mbverifystr((const unsigned char *) mbstr, len));
+}
+
+/*
+ * fetch maximum length of a given encoding
+ */
+int
+pg_encoding_max_length(int encoding)
+{
+ Assert(PG_VALID_ENCODING(encoding));
+
+ return pg_wchar_table[encoding].maxmblen;
+}
diff --git a/contrib/libs/libpq/src/include/access/rmgr.h b/contrib/libs/libpq/src/include/access/rmgr.h
new file mode 100644
index 0000000000..3b6a497e1b
--- /dev/null
+++ b/contrib/libs/libpq/src/include/access/rmgr.h
@@ -0,0 +1,62 @@
+/*
+ * rmgr.h
+ *
+ * Resource managers definition
+ *
+ * src/include/access/rmgr.h
+ */
+#ifndef RMGR_H
+#define RMGR_H
+
+typedef uint8 RmgrId;
+
+/*
+ * Built-in resource managers
+ *
+ * The actual numerical values for each rmgr ID are defined by the order
+ * of entries in rmgrlist.h.
+ *
+ * Note: RM_MAX_ID must fit in RmgrId; widening that type will affect the XLOG
+ * file format.
+ */
+#define PG_RMGR(symname,name,redo,desc,identify,startup,cleanup,mask,decode) \
+ symname,
+
+typedef enum RmgrIds
+{
+#include "access/rmgrlist.h"
+ RM_NEXT_ID
+} RmgrIds;
+
+#undef PG_RMGR
+
+#define RM_MAX_ID UINT8_MAX
+#define RM_MAX_BUILTIN_ID (RM_NEXT_ID - 1)
+#define RM_MIN_CUSTOM_ID 128
+#define RM_MAX_CUSTOM_ID UINT8_MAX
+#define RM_N_IDS (UINT8_MAX + 1)
+#define RM_N_BUILTIN_IDS (RM_MAX_BUILTIN_ID + 1)
+#define RM_N_CUSTOM_IDS (RM_MAX_CUSTOM_ID - RM_MIN_CUSTOM_ID + 1)
+
+static inline bool
+RmgrIdIsBuiltin(int rmid)
+{
+ return rmid <= RM_MAX_BUILTIN_ID;
+}
+
+static inline bool
+RmgrIdIsCustom(int rmid)
+{
+ return rmid >= RM_MIN_CUSTOM_ID && rmid <= RM_MAX_CUSTOM_ID;
+}
+
+#define RmgrIdIsValid(rmid) (RmgrIdIsBuiltin((rmid)) || RmgrIdIsCustom((rmid)))
+
+/*
+ * RmgrId to use for extensions that require an RmgrId, but are still in
+ * development and have not reserved their own unique RmgrId yet. See:
+ * https://wiki.postgresql.org/wiki/CustomWALResourceManagers
+ */
+#define RM_EXPERIMENTAL_ID 128
+
+#endif /* RMGR_H */
diff --git a/contrib/libs/libpq/src/include/access/rmgrlist.h b/contrib/libs/libpq/src/include/access/rmgrlist.h
new file mode 100644
index 0000000000..463bcb67c5
--- /dev/null
+++ b/contrib/libs/libpq/src/include/access/rmgrlist.h
@@ -0,0 +1,49 @@
+/*---------------------------------------------------------------------------
+ * rmgrlist.h
+ *
+ * The resource manager list is kept in its own source file for possible
+ * use by automatic tools. The exact representation of a rmgr is determined
+ * by the PG_RMGR macro, which is not defined in this file; it can be
+ * defined by the caller for special purposes.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/rmgrlist.h
+ *---------------------------------------------------------------------------
+ */
+
+/* there is deliberately not an #ifndef RMGRLIST_H here */
+
+/*
+ * List of resource manager entries. Note that order of entries defines the
+ * numerical values of each rmgr's ID, which is stored in WAL records. New
+ * entries should be added at the end, to avoid changing IDs of existing
+ * entries.
+ *
+ * Changes to this list possibly need an XLOG_PAGE_MAGIC bump.
+ */
+
+/* symbol name, textual name, redo, desc, identify, startup, cleanup, mask, decode */
+PG_RMGR(RM_XLOG_ID, "XLOG", xlog_redo, xlog_desc, xlog_identify, NULL, NULL, NULL, xlog_decode)
+PG_RMGR(RM_XACT_ID, "Transaction", xact_redo, xact_desc, xact_identify, NULL, NULL, NULL, xact_decode)
+PG_RMGR(RM_SMGR_ID, "Storage", smgr_redo, smgr_desc, smgr_identify, NULL, NULL, NULL, NULL)
+PG_RMGR(RM_CLOG_ID, "CLOG", clog_redo, clog_desc, clog_identify, NULL, NULL, NULL, NULL)
+PG_RMGR(RM_DBASE_ID, "Database", dbase_redo, dbase_desc, dbase_identify, NULL, NULL, NULL, NULL)
+PG_RMGR(RM_TBLSPC_ID, "Tablespace", tblspc_redo, tblspc_desc, tblspc_identify, NULL, NULL, NULL, NULL)
+PG_RMGR(RM_MULTIXACT_ID, "MultiXact", multixact_redo, multixact_desc, multixact_identify, NULL, NULL, NULL, NULL)
+PG_RMGR(RM_RELMAP_ID, "RelMap", relmap_redo, relmap_desc, relmap_identify, NULL, NULL, NULL, NULL)
+PG_RMGR(RM_STANDBY_ID, "Standby", standby_redo, standby_desc, standby_identify, NULL, NULL, NULL, standby_decode)
+PG_RMGR(RM_HEAP2_ID, "Heap2", heap2_redo, heap2_desc, heap2_identify, NULL, NULL, heap_mask, heap2_decode)
+PG_RMGR(RM_HEAP_ID, "Heap", heap_redo, heap_desc, heap_identify, NULL, NULL, heap_mask, heap_decode)
+PG_RMGR(RM_BTREE_ID, "Btree", btree_redo, btree_desc, btree_identify, btree_xlog_startup, btree_xlog_cleanup, btree_mask, NULL)
+PG_RMGR(RM_HASH_ID, "Hash", hash_redo, hash_desc, hash_identify, NULL, NULL, hash_mask, NULL)
+PG_RMGR(RM_GIN_ID, "Gin", gin_redo, gin_desc, gin_identify, gin_xlog_startup, gin_xlog_cleanup, gin_mask, NULL)
+PG_RMGR(RM_GIST_ID, "Gist", gist_redo, gist_desc, gist_identify, gist_xlog_startup, gist_xlog_cleanup, gist_mask, NULL)
+PG_RMGR(RM_SEQ_ID, "Sequence", seq_redo, seq_desc, seq_identify, NULL, NULL, seq_mask, NULL)
+PG_RMGR(RM_SPGIST_ID, "SPGist", spg_redo, spg_desc, spg_identify, spg_xlog_startup, spg_xlog_cleanup, spg_mask, NULL)
+PG_RMGR(RM_BRIN_ID, "BRIN", brin_redo, brin_desc, brin_identify, NULL, NULL, brin_mask, NULL)
+PG_RMGR(RM_COMMIT_TS_ID, "CommitTs", commit_ts_redo, commit_ts_desc, commit_ts_identify, NULL, NULL, NULL, NULL)
+PG_RMGR(RM_REPLORIGIN_ID, "ReplicationOrigin", replorigin_redo, replorigin_desc, replorigin_identify, NULL, NULL, NULL, NULL)
+PG_RMGR(RM_GENERIC_ID, "Generic", generic_redo, generic_desc, generic_identify, NULL, NULL, generic_mask, NULL)
+PG_RMGR(RM_LOGICALMSG_ID, "LogicalMessage", logicalmsg_redo, logicalmsg_desc, logicalmsg_identify, NULL, NULL, NULL, logicalmsg_decode)
diff --git a/contrib/libs/libpq/src/include/access/transam.h b/contrib/libs/libpq/src/include/access/transam.h
new file mode 100644
index 0000000000..f5af6d3055
--- /dev/null
+++ b/contrib/libs/libpq/src/include/access/transam.h
@@ -0,0 +1,375 @@
+/*-------------------------------------------------------------------------
+ *
+ * transam.h
+ * postgres transaction access method support code
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/transam.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef TRANSAM_H
+#define TRANSAM_H
+
+#include "access/xlogdefs.h"
+
+
+/* ----------------
+ * Special transaction ID values
+ *
+ * BootstrapTransactionId is the XID for "bootstrap" operations, and
+ * FrozenTransactionId is used for very old tuples. Both should
+ * always be considered valid.
+ *
+ * FirstNormalTransactionId is the first "normal" transaction id.
+ * Note: if you need to change it, you must change pg_class.h as well.
+ * ----------------
+ */
+#define InvalidTransactionId ((TransactionId) 0)
+#define BootstrapTransactionId ((TransactionId) 1)
+#define FrozenTransactionId ((TransactionId) 2)
+#define FirstNormalTransactionId ((TransactionId) 3)
+#define MaxTransactionId ((TransactionId) 0xFFFFFFFF)
+
+/* ----------------
+ * transaction ID manipulation macros
+ * ----------------
+ */
+#define TransactionIdIsValid(xid) ((xid) != InvalidTransactionId)
+#define TransactionIdIsNormal(xid) ((xid) >= FirstNormalTransactionId)
+#define TransactionIdEquals(id1, id2) ((id1) == (id2))
+#define TransactionIdStore(xid, dest) (*(dest) = (xid))
+#define StoreInvalidTransactionId(dest) (*(dest) = InvalidTransactionId)
+
+#define EpochFromFullTransactionId(x) ((uint32) ((x).value >> 32))
+#define XidFromFullTransactionId(x) ((uint32) (x).value)
+#define U64FromFullTransactionId(x) ((x).value)
+#define FullTransactionIdEquals(a, b) ((a).value == (b).value)
+#define FullTransactionIdPrecedes(a, b) ((a).value < (b).value)
+#define FullTransactionIdPrecedesOrEquals(a, b) ((a).value <= (b).value)
+#define FullTransactionIdFollows(a, b) ((a).value > (b).value)
+#define FullTransactionIdFollowsOrEquals(a, b) ((a).value >= (b).value)
+#define FullTransactionIdIsValid(x) TransactionIdIsValid(XidFromFullTransactionId(x))
+#define InvalidFullTransactionId FullTransactionIdFromEpochAndXid(0, InvalidTransactionId)
+#define FirstNormalFullTransactionId FullTransactionIdFromEpochAndXid(0, FirstNormalTransactionId)
+#define FullTransactionIdIsNormal(x) FullTransactionIdFollowsOrEquals(x, FirstNormalFullTransactionId)
+
+/*
+ * A 64 bit value that contains an epoch and a TransactionId. This is
+ * wrapped in a struct to prevent implicit conversion to/from TransactionId.
+ * Not all values represent valid normal XIDs.
+ */
+typedef struct FullTransactionId
+{
+ uint64 value;
+} FullTransactionId;
+
+static inline FullTransactionId
+FullTransactionIdFromEpochAndXid(uint32 epoch, TransactionId xid)
+{
+ FullTransactionId result;
+
+ result.value = ((uint64) epoch) << 32 | xid;
+
+ return result;
+}
+
+static inline FullTransactionId
+FullTransactionIdFromU64(uint64 value)
+{
+ FullTransactionId result;
+
+ result.value = value;
+
+ return result;
+}
+
+/* advance a transaction ID variable, handling wraparound correctly */
+#define TransactionIdAdvance(dest) \
+ do { \
+ (dest)++; \
+ if ((dest) < FirstNormalTransactionId) \
+ (dest) = FirstNormalTransactionId; \
+ } while(0)
+
+/*
+ * Retreat a FullTransactionId variable, stepping over xids that would appear
+ * to be special only when viewed as 32bit XIDs.
+ */
+static inline void
+FullTransactionIdRetreat(FullTransactionId *dest)
+{
+ dest->value--;
+
+ /*
+ * In contrast to 32bit XIDs don't step over the "actual" special xids.
+ * For 64bit xids these can't be reached as part of a wraparound as they
+ * can in the 32bit case.
+ */
+ if (FullTransactionIdPrecedes(*dest, FirstNormalFullTransactionId))
+ return;
+
+ /*
+ * But we do need to step over XIDs that'd appear special only for 32bit
+ * XIDs.
+ */
+ while (XidFromFullTransactionId(*dest) < FirstNormalTransactionId)
+ dest->value--;
+}
+
+/*
+ * Advance a FullTransactionId variable, stepping over xids that would appear
+ * to be special only when viewed as 32bit XIDs.
+ */
+static inline void
+FullTransactionIdAdvance(FullTransactionId *dest)
+{
+ dest->value++;
+
+ /* see FullTransactionIdAdvance() */
+ if (FullTransactionIdPrecedes(*dest, FirstNormalFullTransactionId))
+ return;
+
+ while (XidFromFullTransactionId(*dest) < FirstNormalTransactionId)
+ dest->value++;
+}
+
+/* back up a transaction ID variable, handling wraparound correctly */
+#define TransactionIdRetreat(dest) \
+ do { \
+ (dest)--; \
+ } while ((dest) < FirstNormalTransactionId)
+
+/* compare two XIDs already known to be normal; this is a macro for speed */
+#define NormalTransactionIdPrecedes(id1, id2) \
+ (AssertMacro(TransactionIdIsNormal(id1) && TransactionIdIsNormal(id2)), \
+ (int32) ((id1) - (id2)) < 0)
+
+/* compare two XIDs already known to be normal; this is a macro for speed */
+#define NormalTransactionIdFollows(id1, id2) \
+ (AssertMacro(TransactionIdIsNormal(id1) && TransactionIdIsNormal(id2)), \
+ (int32) ((id1) - (id2)) > 0)
+
+/* ----------
+ * Object ID (OID) zero is InvalidOid.
+ *
+ * OIDs 1-9999 are reserved for manual assignment (see .dat files in
+ * src/include/catalog/). Of these, 8000-9999 are reserved for
+ * development purposes (such as in-progress patches and forks);
+ * they should not appear in released versions.
+ *
+ * OIDs 10000-11999 are reserved for assignment by genbki.pl, for use
+ * when the .dat files in src/include/catalog/ do not specify an OID
+ * for a catalog entry that requires one. Note that genbki.pl assigns
+ * these OIDs independently in each catalog, so they're not guaranteed
+ * to be globally unique. Furthermore, the bootstrap backend and
+ * initdb's post-bootstrap processing can also assign OIDs in this range.
+ * The normal OID-generation logic takes care of any OID conflicts that
+ * might arise from that.
+ *
+ * OIDs 12000-16383 are reserved for unpinned objects created by initdb's
+ * post-bootstrap processing. initdb forces the OID generator up to
+ * 12000 as soon as it's made the pinned objects it's responsible for.
+ *
+ * OIDs beginning at 16384 are assigned from the OID generator
+ * during normal multiuser operation. (We force the generator up to
+ * 16384 as soon as we are in normal operation.)
+ *
+ * The choices of 8000, 10000 and 12000 are completely arbitrary, and can be
+ * moved if we run low on OIDs in any category. Changing the macros below,
+ * and updating relevant documentation (see bki.sgml and RELEASE_CHANGES),
+ * should be sufficient to do this. Moving the 16384 boundary between
+ * initdb-assigned OIDs and user-defined objects would be substantially
+ * more painful, however, since some user-defined OIDs will appear in
+ * on-disk data; such a change would probably break pg_upgrade.
+ *
+ * NOTE: if the OID generator wraps around, we skip over OIDs 0-16383
+ * and resume with 16384. This minimizes the odds of OID conflict, by not
+ * reassigning OIDs that might have been assigned during initdb. Critically,
+ * it also ensures that no user-created object will be considered pinned.
+ * ----------
+ */
+#define FirstGenbkiObjectId 10000
+#define FirstUnpinnedObjectId 12000
+#define FirstNormalObjectId 16384
+
+/*
+ * VariableCache is a data structure in shared memory that is used to track
+ * OID and XID assignment state. For largely historical reasons, there is
+ * just one struct with different fields that are protected by different
+ * LWLocks.
+ *
+ * Note: xidWrapLimit and oldestXidDB are not "active" values, but are
+ * used just to generate useful messages when xidWarnLimit or xidStopLimit
+ * are exceeded.
+ */
+typedef struct VariableCacheData
+{
+ /*
+ * These fields are protected by OidGenLock.
+ */
+ Oid nextOid; /* next OID to assign */
+ uint32 oidCount; /* OIDs available before must do XLOG work */
+
+ /*
+ * These fields are protected by XidGenLock.
+ */
+ FullTransactionId nextXid; /* next XID to assign */
+
+ TransactionId oldestXid; /* cluster-wide minimum datfrozenxid */
+ TransactionId xidVacLimit; /* start forcing autovacuums here */
+ TransactionId xidWarnLimit; /* start complaining here */
+ TransactionId xidStopLimit; /* refuse to advance nextXid beyond here */
+ TransactionId xidWrapLimit; /* where the world ends */
+ Oid oldestXidDB; /* database with minimum datfrozenxid */
+
+ /*
+ * These fields are protected by CommitTsLock
+ */
+ TransactionId oldestCommitTsXid;
+ TransactionId newestCommitTsXid;
+
+ /*
+ * These fields are protected by ProcArrayLock.
+ */
+ FullTransactionId latestCompletedXid; /* newest full XID that has
+ * committed or aborted */
+
+ /*
+ * Number of top-level transactions with xids (i.e. which may have
+ * modified the database) that completed in some form since the start of
+ * the server. This currently is solely used to check whether
+ * GetSnapshotData() needs to recompute the contents of the snapshot, or
+ * not. There are likely other users of this. Always above 1.
+ */
+ uint64 xactCompletionCount;
+
+ /*
+ * These fields are protected by XactTruncationLock
+ */
+ TransactionId oldestClogXid; /* oldest it's safe to look up in clog */
+
+} VariableCacheData;
+
+typedef VariableCacheData *VariableCache;
+
+
+/* ----------------
+ * extern declarations
+ * ----------------
+ */
+
+/* in transam/xact.c */
+extern bool TransactionStartedDuringRecovery(void);
+
+/* in transam/varsup.c */
+extern PGDLLIMPORT VariableCache ShmemVariableCache;
+
+/*
+ * prototypes for functions in transam/transam.c
+ */
+extern bool TransactionIdDidCommit(TransactionId transactionId);
+extern bool TransactionIdDidAbort(TransactionId transactionId);
+extern void TransactionIdCommitTree(TransactionId xid, int nxids, TransactionId *xids);
+extern void TransactionIdAsyncCommitTree(TransactionId xid, int nxids, TransactionId *xids, XLogRecPtr lsn);
+extern void TransactionIdAbortTree(TransactionId xid, int nxids, TransactionId *xids);
+extern bool TransactionIdPrecedes(TransactionId id1, TransactionId id2);
+extern bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2);
+extern bool TransactionIdFollows(TransactionId id1, TransactionId id2);
+extern bool TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2);
+extern TransactionId TransactionIdLatest(TransactionId mainxid,
+ int nxids, const TransactionId *xids);
+extern XLogRecPtr TransactionIdGetCommitLSN(TransactionId xid);
+
+/* in transam/varsup.c */
+extern FullTransactionId GetNewTransactionId(bool isSubXact);
+extern void AdvanceNextFullTransactionIdPastXid(TransactionId xid);
+extern FullTransactionId ReadNextFullTransactionId(void);
+extern void SetTransactionIdLimit(TransactionId oldest_datfrozenxid,
+ Oid oldest_datoid);
+extern void AdvanceOldestClogXid(TransactionId oldest_datfrozenxid);
+extern bool ForceTransactionIdLimitUpdate(void);
+extern Oid GetNewObjectId(void);
+extern void StopGeneratingPinnedObjectIds(void);
+
+#ifdef USE_ASSERT_CHECKING
+extern void AssertTransactionIdInAllowableRange(TransactionId xid);
+#else
+#define AssertTransactionIdInAllowableRange(xid) ((void)true)
+#endif
+
+/*
+ * Some frontend programs include this header. For compilers that emit static
+ * inline functions even when they're unused, that leads to unsatisfied
+ * external references; hence hide them with #ifndef FRONTEND.
+ */
+#ifndef FRONTEND
+
+/*
+ * For callers that just need the XID part of the next transaction ID.
+ */
+static inline TransactionId
+ReadNextTransactionId(void)
+{
+ return XidFromFullTransactionId(ReadNextFullTransactionId());
+}
+
+/* return transaction ID backed up by amount, handling wraparound correctly */
+static inline TransactionId
+TransactionIdRetreatedBy(TransactionId xid, uint32 amount)
+{
+ xid -= amount;
+
+ while (xid < FirstNormalTransactionId)
+ xid--;
+
+ return xid;
+}
+
+/* return the older of the two IDs */
+static inline TransactionId
+TransactionIdOlder(TransactionId a, TransactionId b)
+{
+ if (!TransactionIdIsValid(a))
+ return b;
+
+ if (!TransactionIdIsValid(b))
+ return a;
+
+ if (TransactionIdPrecedes(a, b))
+ return a;
+ return b;
+}
+
+/* return the older of the two IDs, assuming they're both normal */
+static inline TransactionId
+NormalTransactionIdOlder(TransactionId a, TransactionId b)
+{
+ Assert(TransactionIdIsNormal(a));
+ Assert(TransactionIdIsNormal(b));
+ if (NormalTransactionIdPrecedes(a, b))
+ return a;
+ return b;
+}
+
+/* return the newer of the two IDs */
+static inline FullTransactionId
+FullTransactionIdNewer(FullTransactionId a, FullTransactionId b)
+{
+ if (!FullTransactionIdIsValid(a))
+ return b;
+
+ if (!FullTransactionIdIsValid(b))
+ return a;
+
+ if (FullTransactionIdFollows(a, b))
+ return a;
+ return b;
+}
+
+#endif /* FRONTEND */
+
+#endif /* TRANSAM_H */
diff --git a/contrib/libs/libpq/src/include/access/xlog_internal.h b/contrib/libs/libpq/src/include/access/xlog_internal.h
new file mode 100644
index 0000000000..b0fd338a00
--- /dev/null
+++ b/contrib/libs/libpq/src/include/access/xlog_internal.h
@@ -0,0 +1,404 @@
+/*
+ * xlog_internal.h
+ *
+ * PostgreSQL write-ahead log internal declarations
+ *
+ * NOTE: this file is intended to contain declarations useful for
+ * manipulating the XLOG files directly, but it is not supposed to be
+ * needed by rmgr routines (redo support for individual record types).
+ * So the XLogRecord typedef and associated stuff appear in xlogrecord.h.
+ *
+ * Note: This file must be includable in both frontend and backend contexts,
+ * to allow stand-alone tools like pg_receivewal to deal with WAL files.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/xlog_internal.h
+ */
+#ifndef XLOG_INTERNAL_H
+#define XLOG_INTERNAL_H
+
+#include "access/xlogdefs.h"
+#include "access/xlogreader.h"
+#include "datatype/timestamp.h"
+#include "lib/stringinfo.h"
+#include "pgtime.h"
+#include "storage/block.h"
+#include "storage/relfilelocator.h"
+
+
+/*
+ * Each page of XLOG file has a header like this:
+ */
+#define XLOG_PAGE_MAGIC 0xD113 /* can be used as WAL version indicator */
+
+typedef struct XLogPageHeaderData
+{
+ uint16 xlp_magic; /* magic value for correctness checks */
+ uint16 xlp_info; /* flag bits, see below */
+ TimeLineID xlp_tli; /* TimeLineID of first record on page */
+ XLogRecPtr xlp_pageaddr; /* XLOG address of this page */
+
+ /*
+ * When there is not enough space on current page for whole record, we
+ * continue on the next page. xlp_rem_len is the number of bytes
+ * remaining from a previous page; it tracks xl_tot_len in the initial
+ * header. Note that the continuation data isn't necessarily aligned.
+ */
+ uint32 xlp_rem_len; /* total len of remaining data for record */
+} XLogPageHeaderData;
+
+#define SizeOfXLogShortPHD MAXALIGN(sizeof(XLogPageHeaderData))
+
+typedef XLogPageHeaderData *XLogPageHeader;
+
+/*
+ * When the XLP_LONG_HEADER flag is set, we store additional fields in the
+ * page header. (This is ordinarily done just in the first page of an
+ * XLOG file.) The additional fields serve to identify the file accurately.
+ */
+typedef struct XLogLongPageHeaderData
+{
+ XLogPageHeaderData std; /* standard header fields */
+ uint64 xlp_sysid; /* system identifier from pg_control */
+ uint32 xlp_seg_size; /* just as a cross-check */
+ uint32 xlp_xlog_blcksz; /* just as a cross-check */
+} XLogLongPageHeaderData;
+
+#define SizeOfXLogLongPHD MAXALIGN(sizeof(XLogLongPageHeaderData))
+
+typedef XLogLongPageHeaderData *XLogLongPageHeader;
+
+/* When record crosses page boundary, set this flag in new page's header */
+#define XLP_FIRST_IS_CONTRECORD 0x0001
+/* This flag indicates a "long" page header */
+#define XLP_LONG_HEADER 0x0002
+/* This flag indicates backup blocks starting in this page are optional */
+#define XLP_BKP_REMOVABLE 0x0004
+/* Replaces a missing contrecord; see CreateOverwriteContrecordRecord */
+#define XLP_FIRST_IS_OVERWRITE_CONTRECORD 0x0008
+/* All defined flag bits in xlp_info (used for validity checking of header) */
+#define XLP_ALL_FLAGS 0x000F
+
+#define XLogPageHeaderSize(hdr) \
+ (((hdr)->xlp_info & XLP_LONG_HEADER) ? SizeOfXLogLongPHD : SizeOfXLogShortPHD)
+
+/* wal_segment_size can range from 1MB to 1GB */
+#define WalSegMinSize 1024 * 1024
+#define WalSegMaxSize 1024 * 1024 * 1024
+/* default number of min and max wal segments */
+#define DEFAULT_MIN_WAL_SEGS 5
+#define DEFAULT_MAX_WAL_SEGS 64
+
+/* check that the given size is a valid wal_segment_size */
+#define IsPowerOf2(x) (x > 0 && ((x) & ((x)-1)) == 0)
+#define IsValidWalSegSize(size) \
+ (IsPowerOf2(size) && \
+ ((size) >= WalSegMinSize && (size) <= WalSegMaxSize))
+
+#define XLogSegmentsPerXLogId(wal_segsz_bytes) \
+ (UINT64CONST(0x100000000) / (wal_segsz_bytes))
+
+#define XLogSegNoOffsetToRecPtr(segno, offset, wal_segsz_bytes, dest) \
+ (dest) = (segno) * (wal_segsz_bytes) + (offset)
+
+#define XLogSegmentOffset(xlogptr, wal_segsz_bytes) \
+ ((xlogptr) & ((wal_segsz_bytes) - 1))
+
+/*
+ * Compute a segment number from an XLogRecPtr.
+ *
+ * For XLByteToSeg, do the computation at face value. For XLByteToPrevSeg,
+ * a boundary byte is taken to be in the previous segment. This is suitable
+ * for deciding which segment to write given a pointer to a record end,
+ * for example.
+ */
+#define XLByteToSeg(xlrp, logSegNo, wal_segsz_bytes) \
+ logSegNo = (xlrp) / (wal_segsz_bytes)
+
+#define XLByteToPrevSeg(xlrp, logSegNo, wal_segsz_bytes) \
+ logSegNo = ((xlrp) - 1) / (wal_segsz_bytes)
+
+/*
+ * Convert values of GUCs measured in megabytes to equiv. segment count.
+ * Rounds down.
+ */
+#define XLogMBVarToSegs(mbvar, wal_segsz_bytes) \
+ ((mbvar) / ((wal_segsz_bytes) / (1024 * 1024)))
+
+/*
+ * Is an XLogRecPtr within a particular XLOG segment?
+ *
+ * For XLByteInSeg, do the computation at face value. For XLByteInPrevSeg,
+ * a boundary byte is taken to be in the previous segment.
+ */
+#define XLByteInSeg(xlrp, logSegNo, wal_segsz_bytes) \
+ (((xlrp) / (wal_segsz_bytes)) == (logSegNo))
+
+#define XLByteInPrevSeg(xlrp, logSegNo, wal_segsz_bytes) \
+ ((((xlrp) - 1) / (wal_segsz_bytes)) == (logSegNo))
+
+/* Check if an XLogRecPtr value is in a plausible range */
+#define XRecOffIsValid(xlrp) \
+ ((xlrp) % XLOG_BLCKSZ >= SizeOfXLogShortPHD)
+
+/*
+ * The XLog directory and control file (relative to $PGDATA)
+ */
+#define XLOGDIR "pg_wal"
+#define XLOG_CONTROL_FILE "global/pg_control"
+
+/*
+ * These macros encapsulate knowledge about the exact layout of XLog file
+ * names, timeline history file names, and archive-status file names.
+ */
+#define MAXFNAMELEN 64
+
+/* Length of XLog file name */
+#define XLOG_FNAME_LEN 24
+
+/*
+ * Generate a WAL segment file name. Do not use this function in a helper
+ * function allocating the result generated.
+ */
+static inline void
+XLogFileName(char *fname, TimeLineID tli, XLogSegNo logSegNo, int wal_segsz_bytes)
+{
+ snprintf(fname, MAXFNAMELEN, "%08X%08X%08X", tli,
+ (uint32) (logSegNo / XLogSegmentsPerXLogId(wal_segsz_bytes)),
+ (uint32) (logSegNo % XLogSegmentsPerXLogId(wal_segsz_bytes)));
+}
+
+static inline void
+XLogFileNameById(char *fname, TimeLineID tli, uint32 log, uint32 seg)
+{
+ snprintf(fname, MAXFNAMELEN, "%08X%08X%08X", tli, log, seg);
+}
+
+static inline bool
+IsXLogFileName(const char *fname)
+{
+ return (strlen(fname) == XLOG_FNAME_LEN && \
+ strspn(fname, "0123456789ABCDEF") == XLOG_FNAME_LEN);
+}
+
+/*
+ * XLOG segment with .partial suffix. Used by pg_receivewal and at end of
+ * archive recovery, when we want to archive a WAL segment but it might not
+ * be complete yet.
+ */
+static inline bool
+IsPartialXLogFileName(const char *fname)
+{
+ return (strlen(fname) == XLOG_FNAME_LEN + strlen(".partial") &&
+ strspn(fname, "0123456789ABCDEF") == XLOG_FNAME_LEN &&
+ strcmp(fname + XLOG_FNAME_LEN, ".partial") == 0);
+}
+
+static inline void
+XLogFromFileName(const char *fname, TimeLineID *tli, XLogSegNo *logSegNo, int wal_segsz_bytes)
+{
+ uint32 log;
+ uint32 seg;
+
+ sscanf(fname, "%08X%08X%08X", tli, &log, &seg);
+ *logSegNo = (uint64) log * XLogSegmentsPerXLogId(wal_segsz_bytes) + seg;
+}
+
+static inline void
+XLogFilePath(char *path, TimeLineID tli, XLogSegNo logSegNo, int wal_segsz_bytes)
+{
+ snprintf(path, MAXPGPATH, XLOGDIR "/%08X%08X%08X", tli,
+ (uint32) (logSegNo / XLogSegmentsPerXLogId(wal_segsz_bytes)),
+ (uint32) (logSegNo % XLogSegmentsPerXLogId(wal_segsz_bytes)));
+}
+
+static inline void
+TLHistoryFileName(char *fname, TimeLineID tli)
+{
+ snprintf(fname, MAXFNAMELEN, "%08X.history", tli);
+}
+
+static inline bool
+IsTLHistoryFileName(const char *fname)
+{
+ return (strlen(fname) == 8 + strlen(".history") &&
+ strspn(fname, "0123456789ABCDEF") == 8 &&
+ strcmp(fname + 8, ".history") == 0);
+}
+
+static inline void
+TLHistoryFilePath(char *path, TimeLineID tli)
+{
+ snprintf(path, MAXPGPATH, XLOGDIR "/%08X.history", tli);
+}
+
+static inline void
+StatusFilePath(char *path, const char *xlog, const char *suffix)
+{
+ snprintf(path, MAXPGPATH, XLOGDIR "/archive_status/%s%s", xlog, suffix);
+}
+
+static inline void
+BackupHistoryFileName(char *fname, TimeLineID tli, XLogSegNo logSegNo, XLogRecPtr startpoint, int wal_segsz_bytes)
+{
+ snprintf(fname, MAXFNAMELEN, "%08X%08X%08X.%08X.backup", tli,
+ (uint32) (logSegNo / XLogSegmentsPerXLogId(wal_segsz_bytes)),
+ (uint32) (logSegNo % XLogSegmentsPerXLogId(wal_segsz_bytes)),
+ (uint32) (XLogSegmentOffset(startpoint, wal_segsz_bytes)));
+}
+
+static inline bool
+IsBackupHistoryFileName(const char *fname)
+{
+ return (strlen(fname) > XLOG_FNAME_LEN &&
+ strspn(fname, "0123456789ABCDEF") == XLOG_FNAME_LEN &&
+ strcmp(fname + strlen(fname) - strlen(".backup"), ".backup") == 0);
+}
+
+static inline void
+BackupHistoryFilePath(char *path, TimeLineID tli, XLogSegNo logSegNo, XLogRecPtr startpoint, int wal_segsz_bytes)
+{
+ snprintf(path, MAXPGPATH, XLOGDIR "/%08X%08X%08X.%08X.backup", tli,
+ (uint32) (logSegNo / XLogSegmentsPerXLogId(wal_segsz_bytes)),
+ (uint32) (logSegNo % XLogSegmentsPerXLogId(wal_segsz_bytes)),
+ (uint32) (XLogSegmentOffset((startpoint), wal_segsz_bytes)));
+}
+
+/*
+ * Information logged when we detect a change in one of the parameters
+ * important for Hot Standby.
+ */
+typedef struct xl_parameter_change
+{
+ int MaxConnections;
+ int max_worker_processes;
+ int max_wal_senders;
+ int max_prepared_xacts;
+ int max_locks_per_xact;
+ int wal_level;
+ bool wal_log_hints;
+ bool track_commit_timestamp;
+} xl_parameter_change;
+
+/* logs restore point */
+typedef struct xl_restore_point
+{
+ TimestampTz rp_time;
+ char rp_name[MAXFNAMELEN];
+} xl_restore_point;
+
+/* Overwrite of prior contrecord */
+typedef struct xl_overwrite_contrecord
+{
+ XLogRecPtr overwritten_lsn;
+ TimestampTz overwrite_time;
+} xl_overwrite_contrecord;
+
+/* End of recovery mark, when we don't do an END_OF_RECOVERY checkpoint */
+typedef struct xl_end_of_recovery
+{
+ TimestampTz end_time;
+ TimeLineID ThisTimeLineID; /* new TLI */
+ TimeLineID PrevTimeLineID; /* previous TLI we forked off from */
+} xl_end_of_recovery;
+
+/*
+ * The functions in xloginsert.c construct a chain of XLogRecData structs
+ * to represent the final WAL record.
+ */
+typedef struct XLogRecData
+{
+ struct XLogRecData *next; /* next struct in chain, or NULL */
+ char *data; /* start of rmgr data to include */
+ uint32 len; /* length of rmgr data to include */
+} XLogRecData;
+
+/*
+ * Recovery target action.
+ */
+typedef enum
+{
+ RECOVERY_TARGET_ACTION_PAUSE,
+ RECOVERY_TARGET_ACTION_PROMOTE,
+ RECOVERY_TARGET_ACTION_SHUTDOWN
+} RecoveryTargetAction;
+
+struct LogicalDecodingContext;
+struct XLogRecordBuffer;
+
+/*
+ * Method table for resource managers.
+ *
+ * This struct must be kept in sync with the PG_RMGR definition in
+ * rmgr.c.
+ *
+ * rm_identify must return a name for the record based on xl_info (without
+ * reference to the rmid). For example, XLOG_BTREE_VACUUM would be named
+ * "VACUUM". rm_desc can then be called to obtain additional detail for the
+ * record, if available (e.g. the last block).
+ *
+ * rm_mask takes as input a page modified by the resource manager and masks
+ * out bits that shouldn't be flagged by wal_consistency_checking.
+ *
+ * RmgrTable[] is indexed by RmgrId values (see rmgrlist.h). If rm_name is
+ * NULL, the corresponding RmgrTable entry is considered invalid.
+ */
+typedef struct RmgrData
+{
+ const char *rm_name;
+ void (*rm_redo) (XLogReaderState *record);
+ void (*rm_desc) (StringInfo buf, XLogReaderState *record);
+ const char *(*rm_identify) (uint8 info);
+ void (*rm_startup) (void);
+ void (*rm_cleanup) (void);
+ void (*rm_mask) (char *pagedata, BlockNumber blkno);
+ void (*rm_decode) (struct LogicalDecodingContext *ctx,
+ struct XLogRecordBuffer *buf);
+} RmgrData;
+
+extern PGDLLIMPORT RmgrData RmgrTable[];
+extern void RmgrStartup(void);
+extern void RmgrCleanup(void);
+extern void RmgrNotFound(RmgrId rmid);
+extern void RegisterCustomRmgr(RmgrId rmid, const RmgrData *rmgr);
+
+#ifndef FRONTEND
+static inline bool
+RmgrIdExists(RmgrId rmid)
+{
+ return RmgrTable[rmid].rm_name != NULL;
+}
+
+static inline RmgrData
+GetRmgr(RmgrId rmid)
+{
+ if (unlikely(!RmgrIdExists(rmid)))
+ RmgrNotFound(rmid);
+ return RmgrTable[rmid];
+}
+#endif
+
+/*
+ * Exported to support xlog switching from checkpointer
+ */
+extern pg_time_t GetLastSegSwitchData(XLogRecPtr *lastSwitchLSN);
+extern XLogRecPtr RequestXLogSwitch(bool mark_unimportant);
+
+extern void GetOldestRestartPoint(XLogRecPtr *oldrecptr, TimeLineID *oldtli);
+
+extern void XLogRecGetBlockRefInfo(XLogReaderState *record, bool pretty,
+ bool detailed_format, StringInfo buf,
+ uint32 *fpi_len);
+
+/*
+ * Exported for the functions in timeline.c and xlogarchive.c. Only valid
+ * in the startup process.
+ */
+extern PGDLLIMPORT bool ArchiveRecoveryRequested;
+extern PGDLLIMPORT bool InArchiveRecovery;
+extern PGDLLIMPORT bool StandbyMode;
+extern PGDLLIMPORT char *recoveryRestoreCommand;
+
+#endif /* XLOG_INTERNAL_H */
diff --git a/contrib/libs/libpq/src/include/access/xlogdefs.h b/contrib/libs/libpq/src/include/access/xlogdefs.h
new file mode 100644
index 0000000000..fe794c7740
--- /dev/null
+++ b/contrib/libs/libpq/src/include/access/xlogdefs.h
@@ -0,0 +1,82 @@
+/*
+ * xlogdefs.h
+ *
+ * Postgres write-ahead log manager record pointer and
+ * timeline number definitions
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/xlogdefs.h
+ */
+#ifndef XLOG_DEFS_H
+#define XLOG_DEFS_H
+
+#include <fcntl.h> /* need open() flags */
+
+/*
+ * Pointer to a location in the XLOG. These pointers are 64 bits wide,
+ * because we don't want them ever to overflow.
+ */
+typedef uint64 XLogRecPtr;
+
+/*
+ * Zero is used indicate an invalid pointer. Bootstrap skips the first possible
+ * WAL segment, initializing the first WAL page at WAL segment size, so no XLOG
+ * record can begin at zero.
+ */
+#define InvalidXLogRecPtr 0
+#define XLogRecPtrIsInvalid(r) ((r) == InvalidXLogRecPtr)
+
+/*
+ * First LSN to use for "fake" LSNs.
+ *
+ * Values smaller than this can be used for special per-AM purposes.
+ */
+#define FirstNormalUnloggedLSN ((XLogRecPtr) 1000)
+
+/*
+ * Handy macro for printing XLogRecPtr in conventional format, e.g.,
+ *
+ * printf("%X/%X", LSN_FORMAT_ARGS(lsn));
+ */
+#define LSN_FORMAT_ARGS(lsn) (AssertVariableIsOfTypeMacro((lsn), XLogRecPtr), (uint32) ((lsn) >> 32)), ((uint32) (lsn))
+
+/*
+ * XLogSegNo - physical log file sequence number.
+ */
+typedef uint64 XLogSegNo;
+
+/*
+ * TimeLineID (TLI) - identifies different database histories to prevent
+ * confusion after restoring a prior state of a database installation.
+ * TLI does not change in a normal stop/restart of the database (including
+ * crash-and-recover cases); but we must assign a new TLI after doing
+ * a recovery to a prior state, a/k/a point-in-time recovery. This makes
+ * the new WAL logfile sequence we generate distinguishable from the
+ * sequence that was generated in the previous incarnation.
+ */
+typedef uint32 TimeLineID;
+
+/*
+ * Replication origin id - this is located in this file to avoid having to
+ * include origin.h in a bunch of xlog related places.
+ */
+typedef uint16 RepOriginId;
+
+/*
+ * This chunk of hackery attempts to determine which file sync methods
+ * are available on the current platform, and to choose an appropriate
+ * default method.
+ *
+ * Note that we define our own O_DSYNC on Windows, but not O_SYNC.
+ */
+#if defined(PLATFORM_DEFAULT_SYNC_METHOD)
+#define DEFAULT_SYNC_METHOD PLATFORM_DEFAULT_SYNC_METHOD
+#elif defined(O_DSYNC) && (!defined(O_SYNC) || O_DSYNC != O_SYNC)
+#define DEFAULT_SYNC_METHOD SYNC_METHOD_OPEN_DSYNC
+#else
+#define DEFAULT_SYNC_METHOD SYNC_METHOD_FDATASYNC
+#endif
+
+#endif /* XLOG_DEFS_H */
diff --git a/contrib/libs/libpq/src/include/access/xlogreader.h b/contrib/libs/libpq/src/include/access/xlogreader.h
new file mode 100644
index 0000000000..da32c7db77
--- /dev/null
+++ b/contrib/libs/libpq/src/include/access/xlogreader.h
@@ -0,0 +1,444 @@
+/*-------------------------------------------------------------------------
+ *
+ * xlogreader.h
+ * Definitions for the generic XLog reading facility
+ *
+ * Portions Copyright (c) 2013-2023, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/include/access/xlogreader.h
+ *
+ * NOTES
+ * See the definition of the XLogReaderState struct for instructions on
+ * how to use the XLogReader infrastructure.
+ *
+ * The basic idea is to allocate an XLogReaderState via
+ * XLogReaderAllocate(), position the reader to the first record with
+ * XLogBeginRead() or XLogFindNextRecord(), and call XLogReadRecord()
+ * until it returns NULL.
+ *
+ * Callers supply a page_read callback if they want to call
+ * XLogReadRecord or XLogFindNextRecord; it can be passed in as NULL
+ * otherwise. The WALRead function can be used as a helper to write
+ * page_read callbacks, but it is not mandatory; callers that use it,
+ * must supply segment_open callbacks. The segment_close callback
+ * must always be supplied.
+ *
+ * After reading a record with XLogReadRecord(), it's decomposed into
+ * the per-block and main data parts, and the parts can be accessed
+ * with the XLogRec* macros and functions. You can also decode a
+ * record that's already constructed in memory, without reading from
+ * disk, by calling the DecodeXLogRecord() function.
+ *-------------------------------------------------------------------------
+ */
+#ifndef XLOGREADER_H
+#define XLOGREADER_H
+
+#ifndef FRONTEND
+#include "access/transam.h"
+#endif
+
+#include "access/xlogrecord.h"
+#include "storage/buf.h"
+
+/* WALOpenSegment represents a WAL segment being read. */
+typedef struct WALOpenSegment
+{
+ int ws_file; /* segment file descriptor */
+ XLogSegNo ws_segno; /* segment number */
+ TimeLineID ws_tli; /* timeline ID of the currently open file */
+} WALOpenSegment;
+
+/* WALSegmentContext carries context information about WAL segments to read */
+typedef struct WALSegmentContext
+{
+ char ws_dir[MAXPGPATH];
+ int ws_segsize;
+} WALSegmentContext;
+
+typedef struct XLogReaderState XLogReaderState;
+
+/* Function type definitions for various xlogreader interactions */
+typedef int (*XLogPageReadCB) (XLogReaderState *xlogreader,
+ XLogRecPtr targetPagePtr,
+ int reqLen,
+ XLogRecPtr targetRecPtr,
+ char *readBuf);
+typedef void (*WALSegmentOpenCB) (XLogReaderState *xlogreader,
+ XLogSegNo nextSegNo,
+ TimeLineID *tli_p);
+typedef void (*WALSegmentCloseCB) (XLogReaderState *xlogreader);
+
+typedef struct XLogReaderRoutine
+{
+ /*
+ * Data input callback
+ *
+ * This callback shall read at least reqLen valid bytes of the xlog page
+ * starting at targetPagePtr, and store them in readBuf. The callback
+ * shall return the number of bytes read (never more than XLOG_BLCKSZ), or
+ * -1 on failure. The callback shall sleep, if necessary, to wait for the
+ * requested bytes to become available. The callback will not be invoked
+ * again for the same page unless more than the returned number of bytes
+ * are needed.
+ *
+ * targetRecPtr is the position of the WAL record we're reading. Usually
+ * it is equal to targetPagePtr + reqLen, but sometimes xlogreader needs
+ * to read and verify the page or segment header, before it reads the
+ * actual WAL record it's interested in. In that case, targetRecPtr can
+ * be used to determine which timeline to read the page from.
+ *
+ * The callback shall set ->seg.ws_tli to the TLI of the file the page was
+ * read from.
+ */
+ XLogPageReadCB page_read;
+
+ /*
+ * Callback to open the specified WAL segment for reading. ->seg.ws_file
+ * shall be set to the file descriptor of the opened segment. In case of
+ * failure, an error shall be raised by the callback and it shall not
+ * return.
+ *
+ * "nextSegNo" is the number of the segment to be opened.
+ *
+ * "tli_p" is an input/output argument. WALRead() uses it to pass the
+ * timeline in which the new segment should be found, but the callback can
+ * use it to return the TLI that it actually opened.
+ */
+ WALSegmentOpenCB segment_open;
+
+ /*
+ * WAL segment close callback. ->seg.ws_file shall be set to a negative
+ * number.
+ */
+ WALSegmentCloseCB segment_close;
+} XLogReaderRoutine;
+
+#define XL_ROUTINE(...) &(XLogReaderRoutine){__VA_ARGS__}
+
+typedef struct
+{
+ /* Is this block ref in use? */
+ bool in_use;
+
+ /* Identify the block this refers to */
+ RelFileLocator rlocator;
+ ForkNumber forknum;
+ BlockNumber blkno;
+
+ /* Prefetching workspace. */
+ Buffer prefetch_buffer;
+
+ /* copy of the fork_flags field from the XLogRecordBlockHeader */
+ uint8 flags;
+
+ /* Information on full-page image, if any */
+ bool has_image; /* has image, even for consistency checking */
+ bool apply_image; /* has image that should be restored */
+ char *bkp_image;
+ uint16 hole_offset;
+ uint16 hole_length;
+ uint16 bimg_len;
+ uint8 bimg_info;
+
+ /* Buffer holding the rmgr-specific data associated with this block */
+ bool has_data;
+ char *data;
+ uint16 data_len;
+ uint16 data_bufsz;
+} DecodedBkpBlock;
+
+/*
+ * The decoded contents of a record. This occupies a contiguous region of
+ * memory, with main_data and blocks[n].data pointing to memory after the
+ * members declared here.
+ */
+typedef struct DecodedXLogRecord
+{
+ /* Private member used for resource management. */
+ size_t size; /* total size of decoded record */
+ bool oversized; /* outside the regular decode buffer? */
+ struct DecodedXLogRecord *next; /* decoded record queue link */
+
+ /* Public members. */
+ XLogRecPtr lsn; /* location */
+ XLogRecPtr next_lsn; /* location of next record */
+ XLogRecord header; /* header */
+ RepOriginId record_origin;
+ TransactionId toplevel_xid; /* XID of top-level transaction */
+ char *main_data; /* record's main data portion */
+ uint32 main_data_len; /* main data portion's length */
+ int max_block_id; /* highest block_id in use (-1 if none) */
+ DecodedBkpBlock blocks[FLEXIBLE_ARRAY_MEMBER];
+} DecodedXLogRecord;
+
+struct XLogReaderState
+{
+ /*
+ * Operational callbacks
+ */
+ XLogReaderRoutine routine;
+
+ /* ----------------------------------------
+ * Public parameters
+ * ----------------------------------------
+ */
+
+ /*
+ * System identifier of the xlog files we're about to read. Set to zero
+ * (the default value) if unknown or unimportant.
+ */
+ uint64 system_identifier;
+
+ /*
+ * Opaque data for callbacks to use. Not used by XLogReader.
+ */
+ void *private_data;
+
+ /*
+ * Start and end point of last record read. EndRecPtr is also used as the
+ * position to read next. Calling XLogBeginRead() sets EndRecPtr to the
+ * starting position and ReadRecPtr to invalid.
+ *
+ * Start and end point of last record returned by XLogReadRecord(). These
+ * are also available as record->lsn and record->next_lsn.
+ */
+ XLogRecPtr ReadRecPtr; /* start of last record read */
+ XLogRecPtr EndRecPtr; /* end+1 of last record read */
+
+ /*
+ * Set at the end of recovery: the start point of a partial record at the
+ * end of WAL (InvalidXLogRecPtr if there wasn't one), and the start
+ * location of its first contrecord that went missing.
+ */
+ XLogRecPtr abortedRecPtr;
+ XLogRecPtr missingContrecPtr;
+ /* Set when XLP_FIRST_IS_OVERWRITE_CONTRECORD is found */
+ XLogRecPtr overwrittenRecPtr;
+
+
+ /* ----------------------------------------
+ * Decoded representation of current record
+ *
+ * Use XLogRecGet* functions to investigate the record; these fields
+ * should not be accessed directly.
+ * ----------------------------------------
+ * Start and end point of the last record read and decoded by
+ * XLogReadRecordInternal(). NextRecPtr is also used as the position to
+ * decode next. Calling XLogBeginRead() sets NextRecPtr and EndRecPtr to
+ * the requested starting position.
+ */
+ XLogRecPtr DecodeRecPtr; /* start of last record decoded */
+ XLogRecPtr NextRecPtr; /* end+1 of last record decoded */
+ XLogRecPtr PrevRecPtr; /* start of previous record decoded */
+
+ /* Last record returned by XLogReadRecord(). */
+ DecodedXLogRecord *record;
+
+ /* ----------------------------------------
+ * private/internal state
+ * ----------------------------------------
+ */
+
+ /*
+ * Buffer for decoded records. This is a circular buffer, though
+ * individual records can't be split in the middle, so some space is often
+ * wasted at the end. Oversized records that don't fit in this space are
+ * allocated separately.
+ */
+ char *decode_buffer;
+ size_t decode_buffer_size;
+ bool free_decode_buffer; /* need to free? */
+ char *decode_buffer_head; /* data is read from the head */
+ char *decode_buffer_tail; /* new data is written at the tail */
+
+ /*
+ * Queue of records that have been decoded. This is a linked list that
+ * usually consists of consecutive records in decode_buffer, but may also
+ * contain oversized records allocated with palloc().
+ */
+ DecodedXLogRecord *decode_queue_head; /* oldest decoded record */
+ DecodedXLogRecord *decode_queue_tail; /* newest decoded record */
+
+ /*
+ * Buffer for currently read page (XLOG_BLCKSZ bytes, valid up to at least
+ * readLen bytes)
+ */
+ char *readBuf;
+ uint32 readLen;
+
+ /* last read XLOG position for data currently in readBuf */
+ WALSegmentContext segcxt;
+ WALOpenSegment seg;
+ uint32 segoff;
+
+ /*
+ * beginning of prior page read, and its TLI. Doesn't necessarily
+ * correspond to what's in readBuf; used for timeline sanity checks.
+ */
+ XLogRecPtr latestPagePtr;
+ TimeLineID latestPageTLI;
+
+ /* beginning of the WAL record being read. */
+ XLogRecPtr currRecPtr;
+ /* timeline to read it from, 0 if a lookup is required */
+ TimeLineID currTLI;
+
+ /*
+ * Safe point to read to in currTLI if current TLI is historical
+ * (tliSwitchPoint) or InvalidXLogRecPtr if on current timeline.
+ *
+ * Actually set to the start of the segment containing the timeline switch
+ * that ends currTLI's validity, not the LSN of the switch its self, since
+ * we can't assume the old segment will be present.
+ */
+ XLogRecPtr currTLIValidUntil;
+
+ /*
+ * If currTLI is not the most recent known timeline, the next timeline to
+ * read from when currTLIValidUntil is reached.
+ */
+ TimeLineID nextTLI;
+
+ /*
+ * Buffer for current ReadRecord result (expandable), used when a record
+ * crosses a page boundary.
+ */
+ char *readRecordBuf;
+ uint32 readRecordBufSize;
+
+ /* Buffer to hold error message */
+ char *errormsg_buf;
+ bool errormsg_deferred;
+
+ /*
+ * Flag to indicate to XLogPageReadCB that it should not block waiting for
+ * data.
+ */
+ bool nonblocking;
+};
+
+/*
+ * Check if XLogNextRecord() has any more queued records or an error to return.
+ */
+static inline bool
+XLogReaderHasQueuedRecordOrError(XLogReaderState *state)
+{
+ return (state->decode_queue_head != NULL) || state->errormsg_deferred;
+}
+
+/* Get a new XLogReader */
+extern XLogReaderState *XLogReaderAllocate(int wal_segment_size,
+ const char *waldir,
+ XLogReaderRoutine *routine,
+ void *private_data);
+
+/* Free an XLogReader */
+extern void XLogReaderFree(XLogReaderState *state);
+
+/* Optionally provide a circular decoding buffer to allow readahead. */
+extern void XLogReaderSetDecodeBuffer(XLogReaderState *state,
+ void *buffer,
+ size_t size);
+
+/* Position the XLogReader to given record */
+extern void XLogBeginRead(XLogReaderState *state, XLogRecPtr RecPtr);
+extern XLogRecPtr XLogFindNextRecord(XLogReaderState *state, XLogRecPtr RecPtr);
+
+/* Return values from XLogPageReadCB. */
+typedef enum XLogPageReadResult
+{
+ XLREAD_SUCCESS = 0, /* record is successfully read */
+ XLREAD_FAIL = -1, /* failed during reading a record */
+ XLREAD_WOULDBLOCK = -2 /* nonblocking mode only, no data */
+} XLogPageReadResult;
+
+/* Read the next XLog record. Returns NULL on end-of-WAL or failure */
+extern struct XLogRecord *XLogReadRecord(XLogReaderState *state,
+ char **errormsg);
+
+/* Consume the next record or error. */
+extern DecodedXLogRecord *XLogNextRecord(XLogReaderState *state,
+ char **errormsg);
+
+/* Release the previously returned record, if necessary. */
+extern XLogRecPtr XLogReleasePreviousRecord(XLogReaderState *state);
+
+/* Try to read ahead, if there is data and space. */
+extern DecodedXLogRecord *XLogReadAhead(XLogReaderState *state,
+ bool nonblocking);
+
+/* Validate a page */
+extern bool XLogReaderValidatePageHeader(XLogReaderState *state,
+ XLogRecPtr recptr, char *phdr);
+
+/* Forget error produced by XLogReaderValidatePageHeader(). */
+extern void XLogReaderResetError(XLogReaderState *state);
+
+/*
+ * Error information from WALRead that both backend and frontend caller can
+ * process. Currently only errors from pg_pread can be reported.
+ */
+typedef struct WALReadError
+{
+ int wre_errno; /* errno set by the last pg_pread() */
+ int wre_off; /* Offset we tried to read from. */
+ int wre_req; /* Bytes requested to be read. */
+ int wre_read; /* Bytes read by the last read(). */
+ WALOpenSegment wre_seg; /* Segment we tried to read from. */
+} WALReadError;
+
+extern bool WALRead(XLogReaderState *state,
+ char *buf, XLogRecPtr startptr, Size count,
+ TimeLineID tli, WALReadError *errinfo);
+
+/* Functions for decoding an XLogRecord */
+
+extern size_t DecodeXLogRecordRequiredSpace(size_t xl_tot_len);
+extern bool DecodeXLogRecord(XLogReaderState *state,
+ DecodedXLogRecord *decoded,
+ XLogRecord *record,
+ XLogRecPtr lsn,
+ char **errormsg);
+
+/*
+ * Macros that provide access to parts of the record most recently returned by
+ * XLogReadRecord() or XLogNextRecord().
+ */
+#define XLogRecGetTotalLen(decoder) ((decoder)->record->header.xl_tot_len)
+#define XLogRecGetPrev(decoder) ((decoder)->record->header.xl_prev)
+#define XLogRecGetInfo(decoder) ((decoder)->record->header.xl_info)
+#define XLogRecGetRmid(decoder) ((decoder)->record->header.xl_rmid)
+#define XLogRecGetXid(decoder) ((decoder)->record->header.xl_xid)
+#define XLogRecGetOrigin(decoder) ((decoder)->record->record_origin)
+#define XLogRecGetTopXid(decoder) ((decoder)->record->toplevel_xid)
+#define XLogRecGetData(decoder) ((decoder)->record->main_data)
+#define XLogRecGetDataLen(decoder) ((decoder)->record->main_data_len)
+#define XLogRecHasAnyBlockRefs(decoder) ((decoder)->record->max_block_id >= 0)
+#define XLogRecMaxBlockId(decoder) ((decoder)->record->max_block_id)
+#define XLogRecGetBlock(decoder, i) (&(decoder)->record->blocks[(i)])
+#define XLogRecHasBlockRef(decoder, block_id) \
+ (((decoder)->record->max_block_id >= (block_id)) && \
+ ((decoder)->record->blocks[block_id].in_use))
+#define XLogRecHasBlockImage(decoder, block_id) \
+ ((decoder)->record->blocks[block_id].has_image)
+#define XLogRecBlockImageApply(decoder, block_id) \
+ ((decoder)->record->blocks[block_id].apply_image)
+#define XLogRecHasBlockData(decoder, block_id) \
+ ((decoder)->record->blocks[block_id].has_data)
+
+#ifndef FRONTEND
+extern FullTransactionId XLogRecGetFullXid(XLogReaderState *record);
+#endif
+
+extern bool RestoreBlockImage(XLogReaderState *record, uint8 block_id, char *page);
+extern char *XLogRecGetBlockData(XLogReaderState *record, uint8 block_id, Size *len);
+extern void XLogRecGetBlockTag(XLogReaderState *record, uint8 block_id,
+ RelFileLocator *rlocator, ForkNumber *forknum,
+ BlockNumber *blknum);
+extern bool XLogRecGetBlockTagExtended(XLogReaderState *record, uint8 block_id,
+ RelFileLocator *rlocator, ForkNumber *forknum,
+ BlockNumber *blknum,
+ Buffer *prefetch_buffer);
+
+#endif /* XLOGREADER_H */
diff --git a/contrib/libs/libpq/src/include/access/xlogrecord.h b/contrib/libs/libpq/src/include/access/xlogrecord.h
new file mode 100644
index 0000000000..f355e08e1d
--- /dev/null
+++ b/contrib/libs/libpq/src/include/access/xlogrecord.h
@@ -0,0 +1,248 @@
+/*
+ * xlogrecord.h
+ *
+ * Definitions for the WAL record format.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/xlogrecord.h
+ */
+#ifndef XLOGRECORD_H
+#define XLOGRECORD_H
+
+#include "access/rmgr.h"
+#include "access/xlogdefs.h"
+#include "port/pg_crc32c.h"
+#include "storage/block.h"
+#include "storage/relfilelocator.h"
+
+/*
+ * The overall layout of an XLOG record is:
+ * Fixed-size header (XLogRecord struct)
+ * XLogRecordBlockHeader struct
+ * XLogRecordBlockHeader struct
+ * ...
+ * XLogRecordDataHeader[Short|Long] struct
+ * block data
+ * block data
+ * ...
+ * main data
+ *
+ * There can be zero or more XLogRecordBlockHeaders, and 0 or more bytes of
+ * rmgr-specific data not associated with a block. XLogRecord structs
+ * always start on MAXALIGN boundaries in the WAL files, but the rest of
+ * the fields are not aligned.
+ *
+ * The XLogRecordBlockHeader, XLogRecordDataHeaderShort and
+ * XLogRecordDataHeaderLong structs all begin with a single 'id' byte. It's
+ * used to distinguish between block references, and the main data structs.
+ */
+typedef struct XLogRecord
+{
+ uint32 xl_tot_len; /* total len of entire record */
+ TransactionId xl_xid; /* xact id */
+ XLogRecPtr xl_prev; /* ptr to previous record in log */
+ uint8 xl_info; /* flag bits, see below */
+ RmgrId xl_rmid; /* resource manager for this record */
+ /* 2 bytes of padding here, initialize to zero */
+ pg_crc32c xl_crc; /* CRC for this record */
+
+ /* XLogRecordBlockHeaders and XLogRecordDataHeader follow, no padding */
+
+} XLogRecord;
+
+#define SizeOfXLogRecord (offsetof(XLogRecord, xl_crc) + sizeof(pg_crc32c))
+
+/*
+ * The high 4 bits in xl_info may be used freely by rmgr. The
+ * XLR_SPECIAL_REL_UPDATE and XLR_CHECK_CONSISTENCY bits can be passed by
+ * XLogInsert caller. The rest are set internally by XLogInsert.
+ */
+#define XLR_INFO_MASK 0x0F
+#define XLR_RMGR_INFO_MASK 0xF0
+
+/*
+ * XLogReader needs to allocate all the data of a WAL record in a single
+ * chunk. This means that a single XLogRecord cannot exceed MaxAllocSize
+ * in length if we ignore any allocation overhead of the XLogReader.
+ *
+ * To accommodate some overhead, this value allows for 4M of allocation
+ * overhead, that should be plenty enough for what
+ * DecodeXLogRecordRequiredSpace() expects as extra.
+ */
+#define XLogRecordMaxSize (1020 * 1024 * 1024)
+
+/*
+ * If a WAL record modifies any relation files, in ways not covered by the
+ * usual block references, this flag is set. This is not used for anything
+ * by PostgreSQL itself, but it allows external tools that read WAL and keep
+ * track of modified blocks to recognize such special record types.
+ */
+#define XLR_SPECIAL_REL_UPDATE 0x01
+
+/*
+ * Enforces consistency checks of replayed WAL at recovery. If enabled,
+ * each record will log a full-page write for each block modified by the
+ * record and will reuse it afterwards for consistency checks. The caller
+ * of XLogInsert can use this value if necessary, but if
+ * wal_consistency_checking is enabled for a rmgr this is set unconditionally.
+ */
+#define XLR_CHECK_CONSISTENCY 0x02
+
+/*
+ * Header info for block data appended to an XLOG record.
+ *
+ * 'data_length' is the length of the rmgr-specific payload data associated
+ * with this block. It does not include the possible full page image, nor
+ * XLogRecordBlockHeader struct itself.
+ *
+ * Note that we don't attempt to align the XLogRecordBlockHeader struct!
+ * So, the struct must be copied to aligned local storage before use.
+ */
+typedef struct XLogRecordBlockHeader
+{
+ uint8 id; /* block reference ID */
+ uint8 fork_flags; /* fork within the relation, and flags */
+ uint16 data_length; /* number of payload bytes (not including page
+ * image) */
+
+ /* If BKPBLOCK_HAS_IMAGE, an XLogRecordBlockImageHeader struct follows */
+ /* If BKPBLOCK_SAME_REL is not set, a RelFileLocator follows */
+ /* BlockNumber follows */
+} XLogRecordBlockHeader;
+
+#define SizeOfXLogRecordBlockHeader (offsetof(XLogRecordBlockHeader, data_length) + sizeof(uint16))
+
+/*
+ * Additional header information when a full-page image is included
+ * (i.e. when BKPBLOCK_HAS_IMAGE is set).
+ *
+ * The XLOG code is aware that PG data pages usually contain an unused "hole"
+ * in the middle, which contains only zero bytes. Since we know that the
+ * "hole" is all zeros, we remove it from the stored data (and it's not counted
+ * in the XLOG record's CRC, either). Hence, the amount of block data actually
+ * present is (BLCKSZ - <length of "hole" bytes>).
+ *
+ * Additionally, when wal_compression is enabled, we will try to compress full
+ * page images using one of the supported algorithms, after removing the
+ * "hole". This can reduce the WAL volume, but at some extra cost of CPU spent
+ * on the compression during WAL logging. In this case, since the "hole"
+ * length cannot be calculated by subtracting the number of page image bytes
+ * from BLCKSZ, basically it needs to be stored as an extra information.
+ * But when no "hole" exists, we can assume that the "hole" length is zero
+ * and no such an extra information needs to be stored. Note that
+ * the original version of page image is stored in WAL instead of the
+ * compressed one if the number of bytes saved by compression is less than
+ * the length of extra information. Hence, when a page image is successfully
+ * compressed, the amount of block data actually present is less than
+ * BLCKSZ - the length of "hole" bytes - the length of extra information.
+ */
+typedef struct XLogRecordBlockImageHeader
+{
+ uint16 length; /* number of page image bytes */
+ uint16 hole_offset; /* number of bytes before "hole" */
+ uint8 bimg_info; /* flag bits, see below */
+
+ /*
+ * If BKPIMAGE_HAS_HOLE and BKPIMAGE_COMPRESSED(), an
+ * XLogRecordBlockCompressHeader struct follows.
+ */
+} XLogRecordBlockImageHeader;
+
+#define SizeOfXLogRecordBlockImageHeader \
+ (offsetof(XLogRecordBlockImageHeader, bimg_info) + sizeof(uint8))
+
+/* Information stored in bimg_info */
+#define BKPIMAGE_HAS_HOLE 0x01 /* page image has "hole" */
+#define BKPIMAGE_APPLY 0x02 /* page image should be restored
+ * during replay */
+/* compression methods supported */
+#define BKPIMAGE_COMPRESS_PGLZ 0x04
+#define BKPIMAGE_COMPRESS_LZ4 0x08
+#define BKPIMAGE_COMPRESS_ZSTD 0x10
+
+#define BKPIMAGE_COMPRESSED(info) \
+ ((info & (BKPIMAGE_COMPRESS_PGLZ | BKPIMAGE_COMPRESS_LZ4 | \
+ BKPIMAGE_COMPRESS_ZSTD)) != 0)
+
+/*
+ * Extra header information used when page image has "hole" and
+ * is compressed.
+ */
+typedef struct XLogRecordBlockCompressHeader
+{
+ uint16 hole_length; /* number of bytes in "hole" */
+} XLogRecordBlockCompressHeader;
+
+#define SizeOfXLogRecordBlockCompressHeader \
+ sizeof(XLogRecordBlockCompressHeader)
+
+/*
+ * Maximum size of the header for a block reference. This is used to size a
+ * temporary buffer for constructing the header.
+ */
+#define MaxSizeOfXLogRecordBlockHeader \
+ (SizeOfXLogRecordBlockHeader + \
+ SizeOfXLogRecordBlockImageHeader + \
+ SizeOfXLogRecordBlockCompressHeader + \
+ sizeof(RelFileLocator) + \
+ sizeof(BlockNumber))
+
+/*
+ * The fork number fits in the lower 4 bits in the fork_flags field. The upper
+ * bits are used for flags.
+ */
+#define BKPBLOCK_FORK_MASK 0x0F
+#define BKPBLOCK_FLAG_MASK 0xF0
+#define BKPBLOCK_HAS_IMAGE 0x10 /* block data is an XLogRecordBlockImage */
+#define BKPBLOCK_HAS_DATA 0x20
+#define BKPBLOCK_WILL_INIT 0x40 /* redo will re-init the page */
+#define BKPBLOCK_SAME_REL 0x80 /* RelFileLocator omitted, same as
+ * previous */
+
+/*
+ * XLogRecordDataHeaderShort/Long are used for the "main data" portion of
+ * the record. If the length of the data is less than 256 bytes, the short
+ * form is used, with a single byte to hold the length. Otherwise the long
+ * form is used.
+ *
+ * (These structs are currently not used in the code, they are here just for
+ * documentation purposes).
+ */
+typedef struct XLogRecordDataHeaderShort
+{
+ uint8 id; /* XLR_BLOCK_ID_DATA_SHORT */
+ uint8 data_length; /* number of payload bytes */
+} XLogRecordDataHeaderShort;
+
+#define SizeOfXLogRecordDataHeaderShort (sizeof(uint8) * 2)
+
+typedef struct XLogRecordDataHeaderLong
+{
+ uint8 id; /* XLR_BLOCK_ID_DATA_LONG */
+ /* followed by uint32 data_length, unaligned */
+} XLogRecordDataHeaderLong;
+
+#define SizeOfXLogRecordDataHeaderLong (sizeof(uint8) + sizeof(uint32))
+
+/*
+ * Block IDs used to distinguish different kinds of record fragments. Block
+ * references are numbered from 0 to XLR_MAX_BLOCK_ID. A rmgr is free to use
+ * any ID number in that range (although you should stick to small numbers,
+ * because the WAL machinery is optimized for that case). A few ID
+ * numbers are reserved to denote the "main" data portion of the record,
+ * as well as replication-supporting transaction metadata.
+ *
+ * The maximum is currently set at 32, quite arbitrarily. Most records only
+ * need a handful of block references, but there are a few exceptions that
+ * need more.
+ */
+#define XLR_MAX_BLOCK_ID 32
+
+#define XLR_BLOCK_ID_DATA_SHORT 255
+#define XLR_BLOCK_ID_DATA_LONG 254
+#define XLR_BLOCK_ID_ORIGIN 253
+#define XLR_BLOCK_ID_TOPLEVEL_XID 252
+
+#endif /* XLOGRECORD_H */
diff --git a/contrib/libs/libpq/src/include/c.h b/contrib/libs/libpq/src/include/c.h
new file mode 100644
index 0000000000..ab459d646e
--- /dev/null
+++ b/contrib/libs/libpq/src/include/c.h
@@ -0,0 +1,1383 @@
+/*-------------------------------------------------------------------------
+ *
+ * c.h
+ * Fundamental C definitions. This is included by every .c file in
+ * PostgreSQL (via either postgres.h or postgres_fe.h, as appropriate).
+ *
+ * Note that the definitions here are not intended to be exposed to clients
+ * of the frontend interface libraries --- so we don't worry much about
+ * polluting the namespace with lots of stuff...
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/c.h
+ *
+ *-------------------------------------------------------------------------
+ */
+/*
+ *----------------------------------------------------------------
+ * TABLE OF CONTENTS
+ *
+ * When adding stuff to this file, please try to put stuff
+ * into the relevant section, or add new sections as appropriate.
+ *
+ * section description
+ * ------- ------------------------------------------------
+ * 0) pg_config.h and standard system headers
+ * 1) compiler characteristics
+ * 2) bool, true, false
+ * 3) standard system types
+ * 4) IsValid macros for system types
+ * 5) lengthof, alignment
+ * 6) assertions
+ * 7) widely useful macros
+ * 8) random stuff
+ * 9) system-specific hacks
+ *
+ * NOTE: since this file is included by both frontend and backend modules,
+ * it's usually wrong to put an "extern" declaration here, unless it's
+ * ifdef'd so that it's seen in only one case or the other.
+ * typedefs and macros are the kind of thing that might go here.
+ *
+ *----------------------------------------------------------------
+ */
+#ifndef C_H
+#define C_H
+
+#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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stddef.h>
+#include <stdarg.h>
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#include <stdint.h>
+#include <sys/types.h>
+#include <errno.h>
+#if defined(WIN32) || defined(__CYGWIN__)
+#include <fcntl.h> /* ensure O_BINARY is available */
+#endif
+#include <locale.h>
+#ifdef ENABLE_NLS
+#include <libintl.h>
+#endif
+
+
+/* ----------------------------------------------------------------
+ * Section 1: compiler characteristics
+ *
+ * type prefixes (const, signed, volatile, inline) are handled in pg_config.h.
+ * ----------------------------------------------------------------
+ */
+
+/*
+ * Disable "inline" if PG_FORCE_DISABLE_INLINE is defined.
+ * This is used to work around compiler bugs and might also be useful for
+ * investigatory purposes.
+ */
+#ifdef PG_FORCE_DISABLE_INLINE
+#undef inline
+#define inline
+#endif
+
+/*
+ * Attribute macros
+ *
+ * GCC: https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
+ * GCC: https://gcc.gnu.org/onlinedocs/gcc/Type-Attributes.html
+ * Clang: https://clang.llvm.org/docs/AttributeReference.html
+ * Sunpro: https://docs.oracle.com/cd/E18659_01/html/821-1384/gjzke.html
+ * XLC: https://www.ibm.com/support/knowledgecenter/SSGH2K_13.1.2/com.ibm.xlc131.aix.doc/language_ref/function_attributes.html
+ * XLC: https://www.ibm.com/support/knowledgecenter/SSGH2K_13.1.2/com.ibm.xlc131.aix.doc/language_ref/type_attrib.html
+ */
+
+/*
+ * For compilers which don't support __has_attribute, we just define
+ * __has_attribute(x) to 0 so that we can define macros for various
+ * __attribute__s more easily below.
+ */
+#ifndef __has_attribute
+#define __has_attribute(attribute) 0
+#endif
+
+/* only GCC supports the unused attribute */
+#ifdef __GNUC__
+#define pg_attribute_unused() __attribute__((unused))
+#else
+#define pg_attribute_unused()
+#endif
+
+/*
+ * pg_nodiscard means the compiler should warn if the result of a function
+ * call is ignored. The name "nodiscard" is chosen in alignment with
+ * (possibly future) C and C++ standards. For maximum compatibility, use it
+ * as a function declaration specifier, so it goes before the return type.
+ */
+#ifdef __GNUC__
+#define pg_nodiscard __attribute__((warn_unused_result))
+#else
+#define pg_nodiscard
+#endif
+
+/*
+ * Place this macro before functions that should be allowed to make misaligned
+ * accesses. Think twice before using it on non-x86-specific code!
+ * Testing can be done with "-fsanitize=alignment -fsanitize-trap=alignment"
+ * on clang, or "-fsanitize=alignment -fno-sanitize-recover=alignment" on gcc.
+ */
+#if __clang_major__ >= 7 || __GNUC__ >= 8
+#define pg_attribute_no_sanitize_alignment() __attribute__((no_sanitize("alignment")))
+#else
+#define pg_attribute_no_sanitize_alignment()
+#endif
+
+/*
+ * pg_attribute_nonnull means the compiler should warn if the function is
+ * called with the listed arguments set to NULL. If no arguments are
+ * listed, the compiler should warn if any pointer arguments are set to NULL.
+ */
+#if __has_attribute (nonnull)
+#define pg_attribute_nonnull(...) __attribute__((nonnull(__VA_ARGS__)))
+#else
+#define pg_attribute_nonnull(...)
+#endif
+
+/*
+ * Append PG_USED_FOR_ASSERTS_ONLY to definitions of variables that are only
+ * used in assert-enabled builds, to avoid compiler warnings about unused
+ * variables in assert-disabled builds.
+ */
+#ifdef USE_ASSERT_CHECKING
+#define PG_USED_FOR_ASSERTS_ONLY
+#else
+#define PG_USED_FOR_ASSERTS_ONLY pg_attribute_unused()
+#endif
+
+/* GCC and XLC support format attributes */
+#if defined(__GNUC__) || defined(__IBMC__)
+#define pg_attribute_format_arg(a) __attribute__((format_arg(a)))
+#define pg_attribute_printf(f,a) __attribute__((format(PG_PRINTF_ATTRIBUTE, f, a)))
+#else
+#define pg_attribute_format_arg(a)
+#define pg_attribute_printf(f,a)
+#endif
+
+/* GCC, Sunpro and XLC support aligned, packed and noreturn */
+#if defined(__GNUC__) || defined(__SUNPRO_C) || defined(__IBMC__)
+#define pg_attribute_aligned(a) __attribute__((aligned(a)))
+#define pg_attribute_noreturn() __attribute__((noreturn))
+#define pg_attribute_packed() __attribute__((packed))
+#define HAVE_PG_ATTRIBUTE_NORETURN 1
+#elif defined(_MSC_VER)
+/*
+ * MSVC supports aligned. noreturn is also possible but in MSVC it is
+ * declared before the definition while pg_attribute_noreturn() macro
+ * is currently used after the definition.
+ *
+ * Packing is also possible but only by wrapping the entire struct definition
+ * which doesn't fit into our current macro declarations.
+ */
+#define pg_attribute_aligned(a) __declspec(align(a))
+#define pg_attribute_noreturn()
+#else
+/*
+ * NB: aligned and packed are not given default definitions because they
+ * affect code functionality; they *must* be implemented by the compiler
+ * if they are to be used.
+ */
+#define pg_attribute_noreturn()
+#endif
+
+/*
+ * Use "pg_attribute_always_inline" in place of "inline" for functions that
+ * we wish to force inlining of, even when the compiler's heuristics would
+ * choose not to. But, if possible, don't force inlining in unoptimized
+ * debug builds.
+ */
+#if (defined(__GNUC__) && __GNUC__ > 3 && defined(__OPTIMIZE__)) || defined(__SUNPRO_C) || defined(__IBMC__)
+/* GCC > 3, Sunpro and XLC support always_inline via __attribute__ */
+#define pg_attribute_always_inline __attribute__((always_inline)) inline
+#elif defined(_MSC_VER)
+/* MSVC has a special keyword for this */
+#define pg_attribute_always_inline __forceinline
+#else
+/* Otherwise, the best we can do is to say "inline" */
+#define pg_attribute_always_inline inline
+#endif
+
+/*
+ * Forcing a function not to be inlined can be useful if it's the slow path of
+ * a performance-critical function, or should be visible in profiles to allow
+ * for proper cost attribution. Note that unlike the pg_attribute_XXX macros
+ * above, this should be placed before the function's return type and name.
+ */
+/* GCC, Sunpro and XLC support noinline via __attribute__ */
+#if (defined(__GNUC__) && __GNUC__ > 2) || defined(__SUNPRO_C) || defined(__IBMC__)
+#define pg_noinline __attribute__((noinline))
+/* msvc via declspec */
+#elif defined(_MSC_VER)
+#define pg_noinline __declspec(noinline)
+#else
+#define pg_noinline
+#endif
+
+/*
+ * For now, just define pg_attribute_cold and pg_attribute_hot to be empty
+ * macros on minGW 8.1. There appears to be a compiler bug that results in
+ * compilation failure. At this time, we still have at least one buildfarm
+ * animal running that compiler, so this should make that green again. It's
+ * likely this compiler is not popular enough to warrant keeping this code
+ * around forever, so let's just remove it once the last buildfarm animal
+ * upgrades.
+ */
+#if defined(__MINGW64__) && __GNUC__ == 8 && __GNUC_MINOR__ == 1
+
+#define pg_attribute_cold
+#define pg_attribute_hot
+
+#else
+/*
+ * Marking certain functions as "hot" or "cold" can be useful to assist the
+ * compiler in arranging the assembly code in a more efficient way.
+ */
+#if __has_attribute (cold)
+#define pg_attribute_cold __attribute__((cold))
+#else
+#define pg_attribute_cold
+#endif
+
+#if __has_attribute (hot)
+#define pg_attribute_hot __attribute__((hot))
+#else
+#define pg_attribute_hot
+#endif
+
+#endif /* defined(__MINGW64__) && __GNUC__ == 8 &&
+ * __GNUC_MINOR__ == 1 */
+/*
+ * Mark a point as unreachable in a portable fashion. This should preferably
+ * be something that the compiler understands, to aid code generation.
+ * In assert-enabled builds, we prefer abort() for debugging reasons.
+ */
+#if defined(HAVE__BUILTIN_UNREACHABLE) && !defined(USE_ASSERT_CHECKING)
+#define pg_unreachable() __builtin_unreachable()
+#elif defined(_MSC_VER) && !defined(USE_ASSERT_CHECKING)
+#define pg_unreachable() __assume(0)
+#else
+#define pg_unreachable() abort()
+#endif
+
+/*
+ * Hints to the compiler about the likelihood of a branch. Both likely() and
+ * unlikely() return the boolean value of the contained expression.
+ *
+ * These should only be used sparingly, in very hot code paths. It's very easy
+ * to mis-estimate likelihoods.
+ */
+#if __GNUC__ >= 3
+#define likely(x) __builtin_expect((x) != 0, 1)
+#define unlikely(x) __builtin_expect((x) != 0, 0)
+#else
+#define likely(x) ((x) != 0)
+#define unlikely(x) ((x) != 0)
+#endif
+
+/*
+ * CppAsString
+ * Convert the argument to a string, using the C preprocessor.
+ * CppAsString2
+ * Convert the argument to a string, after one round of macro expansion.
+ * CppConcat
+ * Concatenate two arguments together, using the C preprocessor.
+ *
+ * Note: There used to be support here for pre-ANSI C compilers that didn't
+ * support # and ##. Nowadays, these macros are just for clarity and/or
+ * backward compatibility with existing PostgreSQL code.
+ */
+#define CppAsString(identifier) #identifier
+#define CppAsString2(x) CppAsString(x)
+#define CppConcat(x, y) x##y
+
+/*
+ * VA_ARGS_NARGS
+ * Returns the number of macro arguments it is passed.
+ *
+ * An empty argument still counts as an argument, so effectively, this is
+ * "one more than the number of commas in the argument list".
+ *
+ * This works for up to 63 arguments. Internally, VA_ARGS_NARGS_() is passed
+ * 64+N arguments, and the C99 standard only requires macros to allow up to
+ * 127 arguments, so we can't portably go higher. The implementation is
+ * pretty trivial: VA_ARGS_NARGS_() returns its 64th argument, and we set up
+ * the call so that that is the appropriate one of the list of constants.
+ * This idea is due to Laurent Deniau.
+ *
+ * MSVC has an implementation of __VA_ARGS__ that doesn't conform to the
+ * standard unless you use the /Zc:preprocessor compiler flag, but that
+ * isn't available before Visual Studio 2019. For now, use a different
+ * definition that also works on older compilers.
+ */
+#ifdef _MSC_VER
+#define EXPAND(args) args
+#define VA_ARGS_NARGS(...) \
+ VA_ARGS_NARGS_ EXPAND((__VA_ARGS__, \
+ 63,62,61,60, \
+ 59,58,57,56,55,54,53,52,51,50, \
+ 49,48,47,46,45,44,43,42,41,40, \
+ 39,38,37,36,35,34,33,32,31,30, \
+ 29,28,27,26,25,24,23,22,21,20, \
+ 19,18,17,16,15,14,13,12,11,10, \
+ 9, 8, 7, 6, 5, 4, 3, 2, 1, 0))
+#else
+
+#define VA_ARGS_NARGS(...) \
+ VA_ARGS_NARGS_(__VA_ARGS__, \
+ 63,62,61,60, \
+ 59,58,57,56,55,54,53,52,51,50, \
+ 49,48,47,46,45,44,43,42,41,40, \
+ 39,38,37,36,35,34,33,32,31,30, \
+ 29,28,27,26,25,24,23,22,21,20, \
+ 19,18,17,16,15,14,13,12,11,10, \
+ 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
+#endif
+
+#define VA_ARGS_NARGS_( \
+ _01,_02,_03,_04,_05,_06,_07,_08,_09,_10, \
+ _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
+ _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
+ _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
+ _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
+ _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
+ _61,_62,_63, N, ...) \
+ (N)
+
+/*
+ * Generic function pointer. This can be used in the rare cases where it's
+ * necessary to cast a function pointer to a seemingly incompatible function
+ * pointer type while avoiding gcc's -Wcast-function-type warnings.
+ */
+typedef void (*pg_funcptr_t) (void);
+
+/*
+ * We require C99, hence the compiler should understand flexible array
+ * members. However, for documentation purposes we still consider it to be
+ * project style to write "field[FLEXIBLE_ARRAY_MEMBER]" not just "field[]".
+ * When computing the size of such an object, use "offsetof(struct s, f)"
+ * for portability. Don't use "offsetof(struct s, f[0])", as this doesn't
+ * work with MSVC and with C++ compilers.
+ */
+#define FLEXIBLE_ARRAY_MEMBER /* empty */
+
+/*
+ * Does the compiler support #pragma GCC system_header? We optionally use it
+ * to avoid warnings that we can't fix (e.g. in the perl headers).
+ * See https://gcc.gnu.org/onlinedocs/cpp/System-Headers.html
+ *
+ * Headers for which we do not want to show compiler warnings can,
+ * conditionally, use #pragma GCC system_header to avoid warnings. Obviously
+ * this should only be used for external headers over which we do not have
+ * control.
+ *
+ * Support for the pragma is tested here, instead of during configure, as gcc
+ * also warns about the pragma being used in a .c file. It's surprisingly hard
+ * to get autoconf to use .h as the file-ending. Looks like gcc has
+ * implemented the pragma since the 2000, so this test should suffice.
+ *
+ *
+ * Alternatively, we could add the include paths for problematic headers with
+ * -isystem, but that is a larger hammer and is harder to search for.
+ *
+ * A more granular alternative would be to use #pragma GCC diagnostic
+ * push/ignored/pop, but gcc warns about unknown warnings being ignored, so
+ * every to-be-ignored-temporarily compiler warning would require its own
+ * pg_config.h symbol and #ifdef.
+ */
+#ifdef __GNUC__
+#define HAVE_PRAGMA_GCC_SYSTEM_HEADER 1
+#endif
+
+
+/* ----------------------------------------------------------------
+ * Section 2: bool, true, false
+ * ----------------------------------------------------------------
+ */
+
+/*
+ * bool
+ * Boolean value, either true or false.
+ *
+ * We use stdbool.h if available and its bool has size 1. That's useful for
+ * better compiler and debugger output and for compatibility with third-party
+ * libraries. But PostgreSQL currently cannot deal with bool of other sizes;
+ * there are static assertions around the code to prevent that.
+ *
+ * For C++ compilers, we assume the compiler has a compatible built-in
+ * definition of bool.
+ *
+ * See also the version of this code in src/interfaces/ecpg/include/ecpglib.h.
+ */
+
+#ifndef __cplusplus
+
+#ifdef PG_USE_STDBOOL
+#include <stdbool.h>
+#else
+
+#ifndef bool
+typedef unsigned char bool;
+#endif
+
+#ifndef true
+#define true ((bool) 1)
+#endif
+
+#ifndef false
+#define false ((bool) 0)
+#endif
+
+#endif /* not PG_USE_STDBOOL */
+#endif /* not C++ */
+
+
+/* ----------------------------------------------------------------
+ * Section 3: standard system types
+ * ----------------------------------------------------------------
+ */
+
+/*
+ * Pointer
+ * Variable holding address of any memory resident object.
+ *
+ * XXX Pointer arithmetic is done with this, so it can't be void *
+ * under "true" ANSI compilers.
+ */
+typedef char *Pointer;
+
+/*
+ * intN
+ * Signed integer, EXACTLY N BITS IN SIZE,
+ * used for numerical computations and the
+ * frontend/backend protocol.
+ */
+#ifndef HAVE_INT8
+typedef signed char int8; /* == 8 bits */
+typedef signed short int16; /* == 16 bits */
+typedef signed int int32; /* == 32 bits */
+#endif /* not HAVE_INT8 */
+
+/*
+ * uintN
+ * Unsigned integer, EXACTLY N BITS IN SIZE,
+ * used for numerical computations and the
+ * frontend/backend protocol.
+ */
+#ifndef HAVE_UINT8
+typedef unsigned char uint8; /* == 8 bits */
+typedef unsigned short uint16; /* == 16 bits */
+typedef unsigned int uint32; /* == 32 bits */
+#endif /* not HAVE_UINT8 */
+
+/*
+ * bitsN
+ * Unit of bitwise operation, AT LEAST N BITS IN SIZE.
+ */
+typedef uint8 bits8; /* >= 8 bits */
+typedef uint16 bits16; /* >= 16 bits */
+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
+
+/* snprintf format strings to use for 64-bit integers */
+#define INT64_FORMAT "%" INT64_MODIFIER "d"
+#define UINT64_FORMAT "%" INT64_MODIFIER "u"
+
+/*
+ * 128-bit signed and unsigned integers
+ * There currently is only limited support for such types.
+ * E.g. 128bit literals and snprintf are not supported; but math is.
+ * Also, because we exclude such types when choosing MAXIMUM_ALIGNOF,
+ * it must be possible to coerce the compiler to allocate them on no
+ * more than MAXALIGN boundaries.
+ */
+#if defined(PG_INT128_TYPE)
+#if defined(pg_attribute_aligned) || ALIGNOF_PG_INT128_TYPE <= MAXIMUM_ALIGNOF
+#define HAVE_INT128 1
+
+typedef PG_INT128_TYPE int128
+#if defined(pg_attribute_aligned)
+ pg_attribute_aligned(MAXIMUM_ALIGNOF)
+#endif
+ ;
+
+typedef unsigned PG_INT128_TYPE uint128
+#if defined(pg_attribute_aligned)
+ pg_attribute_aligned(MAXIMUM_ALIGNOF)
+#endif
+ ;
+
+#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)
+
+/*
+ * We now always use int64 timestamps, but keep this symbol defined for the
+ * benefit of external code that might test it.
+ */
+#define HAVE_INT64_TIMESTAMP
+
+/*
+ * Size
+ * Size of any memory resident object, as returned by sizeof.
+ */
+typedef size_t Size;
+
+/*
+ * Index
+ * Index into any memory resident array.
+ *
+ * Note:
+ * Indices are non negative.
+ */
+typedef unsigned int Index;
+
+/*
+ * Offset
+ * Offset into any memory resident array.
+ *
+ * Note:
+ * This differs from an Index in that an Index is always
+ * non negative, whereas Offset may be negative.
+ */
+typedef signed int Offset;
+
+/*
+ * Common Postgres datatype names (as used in the catalogs)
+ */
+typedef float float4;
+typedef double float8;
+
+#ifdef USE_FLOAT8_BYVAL
+#define FLOAT8PASSBYVAL true
+#else
+#define FLOAT8PASSBYVAL false
+#endif
+
+/*
+ * Oid, RegProcedure, TransactionId, SubTransactionId, MultiXactId,
+ * CommandId
+ */
+
+/* typedef Oid is in postgres_ext.h */
+
+/*
+ * regproc is the type name used in the include/catalog headers, but
+ * RegProcedure is the preferred name in C code.
+ */
+typedef Oid regproc;
+typedef regproc RegProcedure;
+
+typedef uint32 TransactionId;
+
+typedef uint32 LocalTransactionId;
+
+typedef uint32 SubTransactionId;
+
+#define InvalidSubTransactionId ((SubTransactionId) 0)
+#define TopSubTransactionId ((SubTransactionId) 1)
+
+/* MultiXactId must be equivalent to TransactionId, to fit in t_xmax */
+typedef TransactionId MultiXactId;
+
+typedef uint32 MultiXactOffset;
+
+typedef uint32 CommandId;
+
+#define FirstCommandId ((CommandId) 0)
+#define InvalidCommandId (~(CommandId)0)
+
+
+/* ----------------
+ * Variable-length datatypes all share the 'struct varlena' header.
+ *
+ * NOTE: for TOASTable types, this is an oversimplification, since the value
+ * may be compressed or moved out-of-line. However datatype-specific routines
+ * are mostly content to deal with de-TOASTed values only, and of course
+ * client-side routines should never see a TOASTed value. But even in a
+ * de-TOASTed value, beware of touching vl_len_ directly, as its
+ * representation is no longer convenient. It's recommended that code always
+ * use macros VARDATA_ANY, VARSIZE_ANY, VARSIZE_ANY_EXHDR, VARDATA, VARSIZE,
+ * and SET_VARSIZE instead of relying on direct mentions of the struct fields.
+ * See postgres.h for details of the TOASTed form.
+ * ----------------
+ */
+struct varlena
+{
+ char vl_len_[4]; /* Do not touch this field directly! */
+ char vl_dat[FLEXIBLE_ARRAY_MEMBER]; /* Data content is here */
+};
+
+#define VARHDRSZ ((int32) sizeof(int32))
+
+/*
+ * These widely-used datatypes are just a varlena header and the data bytes.
+ * There is no terminating null or anything like that --- the data length is
+ * always VARSIZE_ANY_EXHDR(ptr).
+ */
+typedef struct varlena bytea;
+typedef struct varlena text;
+typedef struct varlena BpChar; /* blank-padded char, ie SQL char(n) */
+typedef struct varlena VarChar; /* var-length char, ie SQL varchar(n) */
+
+/*
+ * Specialized array types. These are physically laid out just the same
+ * as regular arrays (so that the regular array subscripting code works
+ * with them). They exist as distinct types mostly for historical reasons:
+ * they have nonstandard I/O behavior which we don't want to change for fear
+ * of breaking applications that look at the system catalogs. There is also
+ * an implementation issue for oidvector: it's part of the primary key for
+ * pg_proc, and we can't use the normal btree array support routines for that
+ * without circularity.
+ */
+typedef struct
+{
+ int32 vl_len_; /* these fields must match ArrayType! */
+ int ndim; /* always 1 for int2vector */
+ int32 dataoffset; /* always 0 for int2vector */
+ Oid elemtype;
+ int dim1;
+ int lbound1;
+ int16 values[FLEXIBLE_ARRAY_MEMBER];
+} int2vector;
+
+typedef struct
+{
+ int32 vl_len_; /* these fields must match ArrayType! */
+ int ndim; /* always 1 for oidvector */
+ int32 dataoffset; /* always 0 for oidvector */
+ Oid elemtype;
+ int dim1;
+ int lbound1;
+ Oid values[FLEXIBLE_ARRAY_MEMBER];
+} oidvector;
+
+/*
+ * Representation of a Name: effectively just a C string, but null-padded to
+ * exactly NAMEDATALEN bytes. The use of a struct is historical.
+ */
+typedef struct nameData
+{
+ char data[NAMEDATALEN];
+} NameData;
+typedef NameData *Name;
+
+#define NameStr(name) ((name).data)
+
+
+/* ----------------------------------------------------------------
+ * Section 4: IsValid macros for system types
+ * ----------------------------------------------------------------
+ */
+/*
+ * BoolIsValid
+ * True iff bool is valid.
+ */
+#define BoolIsValid(boolean) ((boolean) == false || (boolean) == true)
+
+/*
+ * PointerIsValid
+ * True iff pointer is valid.
+ */
+#define PointerIsValid(pointer) ((const void*)(pointer) != NULL)
+
+/*
+ * PointerIsAligned
+ * True iff pointer is properly aligned to point to the given type.
+ */
+#define PointerIsAligned(pointer, type) \
+ (((uintptr_t)(pointer) % (sizeof (type))) == 0)
+
+#define OffsetToPointer(base, offset) \
+ ((void *)((char *) base + offset))
+
+#define OidIsValid(objectId) ((bool) ((objectId) != InvalidOid))
+
+#define RegProcedureIsValid(p) OidIsValid(p)
+
+
+/* ----------------------------------------------------------------
+ * Section 5: lengthof, alignment
+ * ----------------------------------------------------------------
+ */
+/*
+ * lengthof
+ * Number of elements in an array.
+ */
+#define lengthof(array) (sizeof (array) / sizeof ((array)[0]))
+
+/* ----------------
+ * Alignment macros: align a length or address appropriately for a given type.
+ * The fooALIGN() macros round up to a multiple of the required alignment,
+ * while the fooALIGN_DOWN() macros round down. The latter are more useful
+ * for problems like "how many X-sized structures will fit in a page?".
+ *
+ * NOTE: TYPEALIGN[_DOWN] will not work if ALIGNVAL is not a power of 2.
+ * That case seems extremely unlikely to be needed in practice, however.
+ *
+ * NOTE: MAXIMUM_ALIGNOF, and hence MAXALIGN(), intentionally exclude any
+ * larger-than-8-byte types the compiler might have.
+ * ----------------
+ */
+
+#define TYPEALIGN(ALIGNVAL,LEN) \
+ (((uintptr_t) (LEN) + ((ALIGNVAL) - 1)) & ~((uintptr_t) ((ALIGNVAL) - 1)))
+
+#define SHORTALIGN(LEN) TYPEALIGN(ALIGNOF_SHORT, (LEN))
+#define INTALIGN(LEN) TYPEALIGN(ALIGNOF_INT, (LEN))
+#define LONGALIGN(LEN) TYPEALIGN(ALIGNOF_LONG, (LEN))
+#define DOUBLEALIGN(LEN) TYPEALIGN(ALIGNOF_DOUBLE, (LEN))
+#define MAXALIGN(LEN) TYPEALIGN(MAXIMUM_ALIGNOF, (LEN))
+/* MAXALIGN covers only built-in types, not buffers */
+#define BUFFERALIGN(LEN) TYPEALIGN(ALIGNOF_BUFFER, (LEN))
+#define CACHELINEALIGN(LEN) TYPEALIGN(PG_CACHE_LINE_SIZE, (LEN))
+
+#define TYPEALIGN_DOWN(ALIGNVAL,LEN) \
+ (((uintptr_t) (LEN)) & ~((uintptr_t) ((ALIGNVAL) - 1)))
+
+#define SHORTALIGN_DOWN(LEN) TYPEALIGN_DOWN(ALIGNOF_SHORT, (LEN))
+#define INTALIGN_DOWN(LEN) TYPEALIGN_DOWN(ALIGNOF_INT, (LEN))
+#define LONGALIGN_DOWN(LEN) TYPEALIGN_DOWN(ALIGNOF_LONG, (LEN))
+#define DOUBLEALIGN_DOWN(LEN) TYPEALIGN_DOWN(ALIGNOF_DOUBLE, (LEN))
+#define MAXALIGN_DOWN(LEN) TYPEALIGN_DOWN(MAXIMUM_ALIGNOF, (LEN))
+#define BUFFERALIGN_DOWN(LEN) TYPEALIGN_DOWN(ALIGNOF_BUFFER, (LEN))
+
+/*
+ * The above macros will not work with types wider than uintptr_t, like with
+ * uint64 on 32-bit platforms. That's not problem for the usual use where a
+ * pointer or a length is aligned, but for the odd case that you need to
+ * align something (potentially) wider, use TYPEALIGN64.
+ */
+#define TYPEALIGN64(ALIGNVAL,LEN) \
+ (((uint64) (LEN) + ((ALIGNVAL) - 1)) & ~((uint64) ((ALIGNVAL) - 1)))
+
+/* we don't currently need wider versions of the other ALIGN macros */
+#define MAXALIGN64(LEN) TYPEALIGN64(MAXIMUM_ALIGNOF, (LEN))
+
+
+/* ----------------------------------------------------------------
+ * Section 6: assertions
+ * ----------------------------------------------------------------
+ */
+
+/*
+ * USE_ASSERT_CHECKING, if defined, turns on all the assertions.
+ * - plai 9/5/90
+ *
+ * It should _NOT_ be defined in releases or in benchmark copies
+ */
+
+/*
+ * Assert() can be used in both frontend and backend code. In frontend code it
+ * just calls the standard assert, if it's available. If use of assertions is
+ * not configured, it does nothing.
+ */
+#ifndef USE_ASSERT_CHECKING
+
+#define Assert(condition) ((void)true)
+#define AssertMacro(condition) ((void)true)
+
+#elif defined(FRONTEND)
+
+#include <assert.h>
+#define Assert(p) assert(p)
+#define AssertMacro(p) ((void) assert(p))
+
+#else /* USE_ASSERT_CHECKING && !FRONTEND */
+
+/*
+ * Assert
+ * Generates a fatal exception if the given condition is false.
+ */
+#define Assert(condition) \
+ do { \
+ if (!(condition)) \
+ ExceptionalCondition(#condition, __FILE__, __LINE__); \
+ } while (0)
+
+/*
+ * AssertMacro is the same as Assert but it's suitable for use in
+ * expression-like macros, for example:
+ *
+ * #define foo(x) (AssertMacro(x != 0), bar(x))
+ */
+#define AssertMacro(condition) \
+ ((void) ((condition) || \
+ (ExceptionalCondition(#condition, __FILE__, __LINE__), 0)))
+
+#endif /* USE_ASSERT_CHECKING && !FRONTEND */
+
+/*
+ * Check that `ptr' is `bndr' aligned.
+ */
+#define AssertPointerAlignment(ptr, bndr) \
+ Assert(TYPEALIGN(bndr, (uintptr_t)(ptr)) == (uintptr_t)(ptr))
+
+/*
+ * ExceptionalCondition is compiled into the backend whether or not
+ * USE_ASSERT_CHECKING is defined, so as to support use of extensions
+ * that are built with that #define with a backend that isn't. Hence,
+ * we should declare it as long as !FRONTEND.
+ */
+#ifndef FRONTEND
+extern void ExceptionalCondition(const char *conditionName,
+ const char *fileName, int lineNumber) pg_attribute_noreturn();
+#endif
+
+/*
+ * Macros to support compile-time assertion checks.
+ *
+ * If the "condition" (a compile-time-constant expression) evaluates to false,
+ * throw a compile error using the "errmessage" (a string literal).
+ *
+ * C11 has _Static_assert(), and most C99 compilers already support that. For
+ * portability, we wrap it into StaticAssertDecl(). _Static_assert() is a
+ * "declaration", and so it must be placed where for example a variable
+ * declaration would be valid. As long as we compile with
+ * -Wno-declaration-after-statement, that also means it cannot be placed after
+ * statements in a function. Macros StaticAssertStmt() and StaticAssertExpr()
+ * make it safe to use as a statement or in an expression, respectively.
+ *
+ * For compilers without _Static_assert(), we fall back on a kluge that
+ * assumes the compiler will complain about a negative width for a struct
+ * bit-field. This will not include a helpful error message, but it beats not
+ * getting an error at all.
+ */
+#ifndef __cplusplus
+#ifdef HAVE__STATIC_ASSERT
+#define StaticAssertDecl(condition, errmessage) \
+ _Static_assert(condition, errmessage)
+#define StaticAssertStmt(condition, errmessage) \
+ do { _Static_assert(condition, errmessage); } while(0)
+#define StaticAssertExpr(condition, errmessage) \
+ ((void) ({ StaticAssertStmt(condition, errmessage); true; }))
+#else /* !HAVE__STATIC_ASSERT */
+#define StaticAssertDecl(condition, errmessage) \
+ extern void static_assert_func(int static_assert_failure[(condition) ? 1 : -1])
+#define StaticAssertStmt(condition, errmessage) \
+ ((void) sizeof(struct { int static_assert_failure : (condition) ? 1 : -1; }))
+#define StaticAssertExpr(condition, errmessage) \
+ StaticAssertStmt(condition, errmessage)
+#endif /* HAVE__STATIC_ASSERT */
+#else /* C++ */
+#if defined(__cpp_static_assert) && __cpp_static_assert >= 200410
+#define StaticAssertDecl(condition, errmessage) \
+ static_assert(condition, errmessage)
+#define StaticAssertStmt(condition, errmessage) \
+ static_assert(condition, errmessage)
+#define StaticAssertExpr(condition, errmessage) \
+ ({ static_assert(condition, errmessage); })
+#else /* !__cpp_static_assert */
+#define StaticAssertDecl(condition, errmessage) \
+ extern void static_assert_func(int static_assert_failure[(condition) ? 1 : -1])
+#define StaticAssertStmt(condition, errmessage) \
+ do { struct static_assert_struct { int static_assert_failure : (condition) ? 1 : -1; }; } while(0)
+#define StaticAssertExpr(condition, errmessage) \
+ ((void) ({ StaticAssertStmt(condition, errmessage); }))
+#endif /* __cpp_static_assert */
+#endif /* C++ */
+
+#ifdef _MSC_VER
+#undef StaticAssertStmt
+#undef StaticAssertDecl
+#define StaticAssertStmt(condition, errmessage)
+#define StaticAssertDecl(condition, errmessage)
+#endif
+
+/*
+ * Compile-time checks that a variable (or expression) has the specified type.
+ *
+ * AssertVariableIsOfType() can be used as a statement.
+ * AssertVariableIsOfTypeMacro() is intended for use in macros, eg
+ * #define foo(x) (AssertVariableIsOfTypeMacro(x, int), bar(x))
+ *
+ * If we don't have __builtin_types_compatible_p, we can still assert that
+ * the types have the same size. This is far from ideal (especially on 32-bit
+ * platforms) but it provides at least some coverage.
+ */
+#ifdef HAVE__BUILTIN_TYPES_COMPATIBLE_P
+#define AssertVariableIsOfType(varname, typename) \
+ StaticAssertStmt(__builtin_types_compatible_p(__typeof__(varname), typename), \
+ CppAsString(varname) " does not have type " CppAsString(typename))
+#define AssertVariableIsOfTypeMacro(varname, typename) \
+ (StaticAssertExpr(__builtin_types_compatible_p(__typeof__(varname), typename), \
+ CppAsString(varname) " does not have type " CppAsString(typename)))
+#else /* !HAVE__BUILTIN_TYPES_COMPATIBLE_P */
+#define AssertVariableIsOfType(varname, typename) \
+ StaticAssertStmt(sizeof(varname) == sizeof(typename), \
+ CppAsString(varname) " does not have type " CppAsString(typename))
+#define AssertVariableIsOfTypeMacro(varname, typename) \
+ (StaticAssertExpr(sizeof(varname) == sizeof(typename), \
+ CppAsString(varname) " does not have type " CppAsString(typename)))
+#endif /* HAVE__BUILTIN_TYPES_COMPATIBLE_P */
+
+
+/* ----------------------------------------------------------------
+ * Section 7: widely useful macros
+ * ----------------------------------------------------------------
+ */
+/*
+ * Max
+ * Return the maximum of two numbers.
+ */
+#define Max(x, y) ((x) > (y) ? (x) : (y))
+
+/*
+ * Min
+ * Return the minimum of two numbers.
+ */
+#define Min(x, y) ((x) < (y) ? (x) : (y))
+
+
+/* Get a bit mask of the bits set in non-long aligned addresses */
+#define LONG_ALIGN_MASK (sizeof(long) - 1)
+
+/*
+ * MemSet
+ * Exactly the same as standard library function memset(), but considerably
+ * faster for zeroing small word-aligned structures (such as parsetree nodes).
+ * This has to be a macro because the main point is to avoid function-call
+ * overhead. However, we have also found that the loop is faster than
+ * native libc memset() on some platforms, even those with assembler
+ * memset() functions. More research needs to be done, perhaps with
+ * MEMSET_LOOP_LIMIT tests in configure.
+ */
+#define MemSet(start, val, len) \
+ do \
+ { \
+ /* must be void* because we don't know if it is integer aligned yet */ \
+ void *_vstart = (void *) (start); \
+ int _val = (val); \
+ Size _len = (len); \
+\
+ if ((((uintptr_t) _vstart) & LONG_ALIGN_MASK) == 0 && \
+ (_len & LONG_ALIGN_MASK) == 0 && \
+ _val == 0 && \
+ _len <= MEMSET_LOOP_LIMIT && \
+ /* \
+ * If MEMSET_LOOP_LIMIT == 0, optimizer should find \
+ * the whole "if" false at compile time. \
+ */ \
+ MEMSET_LOOP_LIMIT != 0) \
+ { \
+ long *_start = (long *) _vstart; \
+ long *_stop = (long *) ((char *) _start + _len); \
+ while (_start < _stop) \
+ *_start++ = 0; \
+ } \
+ else \
+ memset(_vstart, _val, _len); \
+ } while (0)
+
+/*
+ * MemSetAligned is the same as MemSet except it omits the test to see if
+ * "start" is word-aligned. This is okay to use if the caller knows a-priori
+ * that the pointer is suitably aligned (typically, because he just got it
+ * from palloc(), which always delivers a max-aligned pointer).
+ */
+#define MemSetAligned(start, val, len) \
+ do \
+ { \
+ long *_start = (long *) (start); \
+ int _val = (val); \
+ Size _len = (len); \
+\
+ if ((_len & LONG_ALIGN_MASK) == 0 && \
+ _val == 0 && \
+ _len <= MEMSET_LOOP_LIMIT && \
+ MEMSET_LOOP_LIMIT != 0) \
+ { \
+ long *_stop = (long *) ((char *) _start + _len); \
+ while (_start < _stop) \
+ *_start++ = 0; \
+ } \
+ else \
+ memset(_start, _val, _len); \
+ } while (0)
+
+
+/*
+ * MemSetTest/MemSetLoop are a variant version that allow all the tests in
+ * MemSet to be done at compile time in cases where "val" and "len" are
+ * constants *and* we know the "start" pointer must be word-aligned.
+ * If MemSetTest succeeds, then it is okay to use MemSetLoop, otherwise use
+ * MemSetAligned. Beware of multiple evaluations of the arguments when using
+ * this approach.
+ */
+#define MemSetTest(val, len) \
+ ( ((len) & LONG_ALIGN_MASK) == 0 && \
+ (len) <= MEMSET_LOOP_LIMIT && \
+ MEMSET_LOOP_LIMIT != 0 && \
+ (val) == 0 )
+
+#define MemSetLoop(start, val, len) \
+ do \
+ { \
+ long * _start = (long *) (start); \
+ long * _stop = (long *) ((char *) _start + (Size) (len)); \
+ \
+ while (_start < _stop) \
+ *_start++ = 0; \
+ } while (0)
+
+/*
+ * Macros for range-checking float values before converting to integer.
+ * We must be careful here that the boundary values are expressed exactly
+ * in the float domain. PG_INTnn_MIN is an exact power of 2, so it will
+ * be represented exactly; but PG_INTnn_MAX isn't, and might get rounded
+ * off, so avoid using that.
+ * The input must be rounded to an integer beforehand, typically with rint(),
+ * else we might draw the wrong conclusion about close-to-the-limit values.
+ * These macros will do the right thing for Inf, but not necessarily for NaN,
+ * so check isnan(num) first if that's a possibility.
+ */
+#define FLOAT4_FITS_IN_INT16(num) \
+ ((num) >= (float4) PG_INT16_MIN && (num) < -((float4) PG_INT16_MIN))
+#define FLOAT4_FITS_IN_INT32(num) \
+ ((num) >= (float4) PG_INT32_MIN && (num) < -((float4) PG_INT32_MIN))
+#define FLOAT4_FITS_IN_INT64(num) \
+ ((num) >= (float4) PG_INT64_MIN && (num) < -((float4) PG_INT64_MIN))
+#define FLOAT8_FITS_IN_INT16(num) \
+ ((num) >= (float8) PG_INT16_MIN && (num) < -((float8) PG_INT16_MIN))
+#define FLOAT8_FITS_IN_INT32(num) \
+ ((num) >= (float8) PG_INT32_MIN && (num) < -((float8) PG_INT32_MIN))
+#define FLOAT8_FITS_IN_INT64(num) \
+ ((num) >= (float8) PG_INT64_MIN && (num) < -((float8) PG_INT64_MIN))
+
+
+/* ----------------------------------------------------------------
+ * Section 8: random stuff
+ * ----------------------------------------------------------------
+ */
+
+/*
+ * Invert the sign of a qsort-style comparison result, ie, exchange negative
+ * and positive integer values, being careful not to get the wrong answer
+ * for INT_MIN. The argument should be an integral variable.
+ */
+#define INVERT_COMPARE_RESULT(var) \
+ ((var) = ((var) < 0) ? 1 : -(var))
+
+/*
+ * Use this, not "char buf[BLCKSZ]", to declare a field or local variable
+ * holding a page buffer, if that page might be accessed as a page. Otherwise
+ * the variable might be under-aligned, causing problems on alignment-picky
+ * hardware. We include both "double" and "int64" in the union to ensure that
+ * the compiler knows the value must be MAXALIGN'ed (cf. configure's
+ * computation of MAXIMUM_ALIGNOF).
+ */
+typedef union PGAlignedBlock
+{
+ char data[BLCKSZ];
+ double force_align_d;
+ int64 force_align_i64;
+} PGAlignedBlock;
+
+/*
+ * Use this to declare a field or local variable holding a page buffer, if that
+ * page might be accessed as a page or passed to an SMgr I/O function. If
+ * allocating using the MemoryContext API, the aligned allocation functions
+ * should be used with PG_IO_ALIGN_SIZE. This alignment may be more efficient
+ * for I/O in general, but may be strictly required on some platforms when
+ * using direct I/O.
+ */
+typedef union PGIOAlignedBlock
+{
+#ifdef pg_attribute_aligned
+ pg_attribute_aligned(PG_IO_ALIGN_SIZE)
+#endif
+ char data[BLCKSZ];
+ double force_align_d;
+ int64 force_align_i64;
+} PGIOAlignedBlock;
+
+/* Same, but for an XLOG_BLCKSZ-sized buffer */
+typedef union PGAlignedXLogBlock
+{
+#ifdef pg_attribute_aligned
+ pg_attribute_aligned(PG_IO_ALIGN_SIZE)
+#endif
+ char data[XLOG_BLCKSZ];
+ double force_align_d;
+ int64 force_align_i64;
+} PGAlignedXLogBlock;
+
+/* msb for char */
+#define HIGHBIT (0x80)
+#define IS_HIGHBIT_SET(ch) ((unsigned char)(ch) & HIGHBIT)
+
+/*
+ * Support macros for escaping strings. escape_backslash should be true
+ * if generating a non-standard-conforming string. Prefixing a string
+ * with ESCAPE_STRING_SYNTAX guarantees it is non-standard-conforming.
+ * Beware of multiple evaluation of the "ch" argument!
+ */
+#define SQL_STR_DOUBLE(ch, escape_backslash) \
+ ((ch) == '\'' || ((ch) == '\\' && (escape_backslash)))
+
+#define ESCAPE_STRING_SYNTAX 'E'
+
+
+#define STATUS_OK (0)
+#define STATUS_ERROR (-1)
+#define STATUS_EOF (-2)
+
+/*
+ * gettext support
+ */
+
+#ifndef ENABLE_NLS
+/* stuff we'd otherwise get from <libintl.h> */
+#define gettext(x) (x)
+#define dgettext(d,x) (x)
+#define ngettext(s,p,n) ((n) == 1 ? (s) : (p))
+#define dngettext(d,s,p,n) ((n) == 1 ? (s) : (p))
+#endif
+
+#define _(x) gettext(x)
+
+/*
+ * Use this to mark string constants as needing translation at some later
+ * time, rather than immediately. This is useful for cases where you need
+ * access to the original string and translated string, and for cases where
+ * immediate translation is not possible, like when initializing global
+ * variables.
+ *
+ * https://www.gnu.org/software/gettext/manual/html_node/Special-cases.html
+ */
+#define gettext_noop(x) (x)
+
+/*
+ * To better support parallel installations of major PostgreSQL
+ * versions as well as parallel installations of major library soname
+ * versions, we mangle the gettext domain name by appending those
+ * version numbers. The coding rule ought to be that wherever the
+ * domain name is mentioned as a literal, it must be wrapped into
+ * PG_TEXTDOMAIN(). The macros below do not work on non-literals; but
+ * that is somewhat intentional because it avoids having to worry
+ * about multiple states of premangling and postmangling as the values
+ * are being passed around.
+ *
+ * Make sure this matches the installation rules in nls-global.mk.
+ */
+#ifdef SO_MAJOR_VERSION
+#define PG_TEXTDOMAIN(domain) (domain CppAsString2(SO_MAJOR_VERSION) "-" PG_MAJORVERSION)
+#else
+#define PG_TEXTDOMAIN(domain) (domain "-" PG_MAJORVERSION)
+#endif
+
+/*
+ * Macro that allows to cast constness and volatile away from an expression, but doesn't
+ * allow changing the underlying type. Enforcement of the latter
+ * currently only works for gcc like compilers.
+ *
+ * Please note IT IS NOT SAFE to cast constness away if the result will ever
+ * be modified (it would be undefined behaviour). Doing so anyway can cause
+ * compiler misoptimizations or runtime crashes (modifying readonly memory).
+ * It is only safe to use when the result will not be modified, but API
+ * design or language restrictions prevent you from declaring that
+ * (e.g. because a function returns both const and non-const variables).
+ *
+ * Note that this only works in function scope, not for global variables (it'd
+ * be nice, but not trivial, to improve that).
+ */
+#if defined(HAVE__BUILTIN_TYPES_COMPATIBLE_P)
+#define unconstify(underlying_type, expr) \
+ (StaticAssertExpr(__builtin_types_compatible_p(__typeof(expr), const underlying_type), \
+ "wrong cast"), \
+ (underlying_type) (expr))
+#define unvolatize(underlying_type, expr) \
+ (StaticAssertExpr(__builtin_types_compatible_p(__typeof(expr), volatile underlying_type), \
+ "wrong cast"), \
+ (underlying_type) (expr))
+#else
+#define unconstify(underlying_type, expr) \
+ ((underlying_type) (expr))
+#define unvolatize(underlying_type, expr) \
+ ((underlying_type) (expr))
+#endif
+
+/* ----------------------------------------------------------------
+ * Section 9: system-specific hacks
+ *
+ * This should be limited to things that absolutely have to be
+ * included in every source file. The port-specific header file
+ * is usually a better place for this sort of thing.
+ * ----------------------------------------------------------------
+ */
+
+/*
+ * NOTE: this is also used for opening text files.
+ * WIN32 treats Control-Z as EOF in files opened in text mode.
+ * Therefore, we open files in binary mode on Win32 so we can read
+ * literal control-Z. The other affect is that we see CRLF, but
+ * that is OK because we can already handle those cleanly.
+ */
+#if defined(WIN32) || defined(__CYGWIN__)
+#define PG_BINARY O_BINARY
+#define PG_BINARY_A "ab"
+#define PG_BINARY_R "rb"
+#define PG_BINARY_W "wb"
+#else
+#define PG_BINARY 0
+#define PG_BINARY_A "a"
+#define PG_BINARY_R "r"
+#define PG_BINARY_W "w"
+#endif
+
+/*
+ * Provide prototypes for routines not present in a particular machine's
+ * standard C library.
+ */
+
+#if !HAVE_DECL_FDATASYNC
+extern int fdatasync(int fildes);
+#endif
+
+/*
+ * Thin wrappers that convert strings to exactly 64-bit integers, matching our
+ * definition of int64. (For the naming, compare that POSIX has
+ * strtoimax()/strtoumax() which return intmax_t/uintmax_t.)
+ */
+#ifdef HAVE_LONG_INT_64
+#define strtoi64(str, endptr, base) ((int64) strtol(str, endptr, base))
+#define strtou64(str, endptr, base) ((uint64) strtoul(str, endptr, base))
+#else
+#define strtoi64(str, endptr, base) ((int64) strtoll(str, endptr, base))
+#define strtou64(str, endptr, base) ((uint64) strtoull(str, endptr, base))
+#endif
+
+/*
+ * Similarly, wrappers around labs()/llabs() matching our int64.
+ */
+#ifdef HAVE_LONG_INT_64
+#define i64abs(i) labs(i)
+#else
+#define i64abs(i) llabs(i)
+#endif
+
+/*
+ * Use "extern PGDLLIMPORT ..." to declare variables that are defined
+ * in the core backend and need to be accessible by loadable modules.
+ * No special marking is required on most ports.
+ */
+#ifndef PGDLLIMPORT
+#define PGDLLIMPORT
+#endif
+
+/*
+ * Use "extern PGDLLEXPORT ..." to declare functions that are defined in
+ * loadable modules and need to be callable by the core backend or other
+ * loadable modules.
+ * If the compiler knows __attribute__((visibility("*"))), we use that,
+ * unless we already have a platform-specific definition. Otherwise,
+ * no special marking is required.
+ */
+#ifndef PGDLLEXPORT
+#ifdef HAVE_VISIBILITY_ATTRIBUTE
+#define PGDLLEXPORT __attribute__((visibility("default")))
+#else
+#define PGDLLEXPORT
+#endif
+#endif
+
+/*
+ * The following is used as the arg list for signal handlers. Any ports
+ * that take something other than an int argument should override this in
+ * their pg_config_os.h file. Note that variable names are required
+ * because it is used in both the prototypes as well as the definitions.
+ * Note also the long name. We expect that this won't collide with
+ * other names causing compiler warnings.
+ */
+
+#ifndef SIGNAL_ARGS
+#define SIGNAL_ARGS int postgres_signal_arg
+#endif
+
+/*
+ * When there is no sigsetjmp, its functionality is provided by plain
+ * setjmp. We now support the case only on Windows. However, it seems
+ * that MinGW-64 has some longstanding issues in its setjmp support,
+ * so on that toolchain we cheat and use gcc's builtins.
+ */
+#ifdef WIN32
+#ifdef __MINGW64__
+typedef intptr_t sigjmp_buf[5];
+#define sigsetjmp(x,y) __builtin_setjmp(x)
+#define siglongjmp __builtin_longjmp
+#else /* !__MINGW64__ */
+#define sigjmp_buf jmp_buf
+#define sigsetjmp(x,y) setjmp(x)
+#define siglongjmp longjmp
+#endif /* __MINGW64__ */
+#endif /* WIN32 */
+
+/* /port compatibility functions */
+#include "port.h"
+
+#endif /* C_H */
diff --git a/contrib/libs/libpq/src/include/catalog/catversion.h b/contrib/libs/libpq/src/include/catalog/catversion.h
new file mode 100644
index 0000000000..cc1de6e65a
--- /dev/null
+++ b/contrib/libs/libpq/src/include/catalog/catversion.h
@@ -0,0 +1,62 @@
+/*-------------------------------------------------------------------------
+ *
+ * catversion.h
+ * "Catalog version number" for PostgreSQL.
+ *
+ * The catalog version number is used to flag incompatible changes in
+ * the PostgreSQL system catalogs. Whenever anyone changes the format of
+ * a system catalog relation, or adds, deletes, or modifies standard
+ * catalog entries in such a way that an updated backend wouldn't work
+ * with an old database (or vice versa), the catalog version number
+ * should be changed. The version number stored in pg_control by initdb
+ * is checked against the version number compiled into the backend at
+ * startup time, so that a backend can refuse to run in an incompatible
+ * database.
+ *
+ * The point of this feature is to provide a finer grain of compatibility
+ * checking than is possible from looking at the major version number
+ * stored in PG_VERSION. It shouldn't matter to end users, but during
+ * development cycles we usually make quite a few incompatible changes
+ * to the contents of the system catalogs, and we don't want to bump the
+ * major version number for each one. What we can do instead is bump
+ * this internal version number. This should save some grief for
+ * developers who might otherwise waste time tracking down "bugs" that
+ * are really just code-vs-database incompatibilities.
+ *
+ * The rule for developers is: if you commit a change that requires
+ * an initdb, you should update the catalog version number (as well as
+ * notifying the pgsql-hackers mailing list, which has been the
+ * informal practice for a long time).
+ *
+ * The catalog version number is placed here since modifying files in
+ * include/catalog is the most common kind of initdb-forcing change.
+ * But it could be used to protect any kind of incompatible change in
+ * database contents or layout, such as altering tuple headers.
+ * Another common reason for a catversion update is a change in parsetree
+ * external representation, since serialized parsetrees appear in stored
+ * rules and new-style SQL functions. Almost any change in primnodes.h or
+ * parsenodes.h will warrant a catversion update.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/catversion.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef CATVERSION_H
+#define CATVERSION_H
+
+/*
+ * We could use anything we wanted for version numbers, but I recommend
+ * following the "YYYYMMDDN" style often used for DNS zone serial numbers.
+ * YYYYMMDD are the date of the change, and N is the number of the change
+ * on that day. (Hopefully we'll never commit ten independent sets of
+ * catalog changes on the same day...)
+ */
+
+/* yyyymmddN */
+#define CATALOG_VERSION_NO 202307071
+
+#endif
diff --git a/contrib/libs/libpq/src/include/catalog/pg_control.h b/contrib/libs/libpq/src/include/catalog/pg_control.h
new file mode 100644
index 0000000000..dc953977c5
--- /dev/null
+++ b/contrib/libs/libpq/src/include/catalog/pg_control.h
@@ -0,0 +1,258 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_control.h
+ * The system control file "pg_control" is not a heap relation.
+ * However, we define it here so that the format is documented.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_control.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_CONTROL_H
+#define PG_CONTROL_H
+
+#include "access/transam.h"
+#include "access/xlogdefs.h"
+#include "pgtime.h" /* for pg_time_t */
+#include "port/pg_crc32c.h"
+
+
+/* Version identifier for this pg_control format */
+#define PG_CONTROL_VERSION 1300
+
+/* Nonce key length, see below */
+#define MOCK_AUTH_NONCE_LEN 32
+
+/*
+ * Body of CheckPoint XLOG records. This is declared here because we keep
+ * a copy of the latest one in pg_control for possible disaster recovery.
+ * Changing this struct requires a PG_CONTROL_VERSION bump.
+ */
+typedef struct CheckPoint
+{
+ XLogRecPtr redo; /* next RecPtr available when we began to
+ * create CheckPoint (i.e. REDO start point) */
+ TimeLineID ThisTimeLineID; /* current TLI */
+ TimeLineID PrevTimeLineID; /* previous TLI, if this record begins a new
+ * timeline (equals ThisTimeLineID otherwise) */
+ bool fullPageWrites; /* current full_page_writes */
+ FullTransactionId nextXid; /* next free transaction ID */
+ Oid nextOid; /* next free OID */
+ MultiXactId nextMulti; /* next free MultiXactId */
+ MultiXactOffset nextMultiOffset; /* next free MultiXact offset */
+ TransactionId oldestXid; /* cluster-wide minimum datfrozenxid */
+ Oid oldestXidDB; /* database with minimum datfrozenxid */
+ MultiXactId oldestMulti; /* cluster-wide minimum datminmxid */
+ Oid oldestMultiDB; /* database with minimum datminmxid */
+ pg_time_t time; /* time stamp of checkpoint */
+ TransactionId oldestCommitTsXid; /* oldest Xid with valid commit
+ * timestamp */
+ TransactionId newestCommitTsXid; /* newest Xid with valid commit
+ * timestamp */
+
+ /*
+ * Oldest XID still running. This is only needed to initialize hot standby
+ * mode from an online checkpoint, so we only bother calculating this for
+ * online checkpoints and only when wal_level is replica. Otherwise it's
+ * set to InvalidTransactionId.
+ */
+ TransactionId oldestActiveXid;
+} CheckPoint;
+
+/* XLOG info values for XLOG rmgr */
+#define XLOG_CHECKPOINT_SHUTDOWN 0x00
+#define XLOG_CHECKPOINT_ONLINE 0x10
+#define XLOG_NOOP 0x20
+#define XLOG_NEXTOID 0x30
+#define XLOG_SWITCH 0x40
+#define XLOG_BACKUP_END 0x50
+#define XLOG_PARAMETER_CHANGE 0x60
+#define XLOG_RESTORE_POINT 0x70
+#define XLOG_FPW_CHANGE 0x80
+#define XLOG_END_OF_RECOVERY 0x90
+#define XLOG_FPI_FOR_HINT 0xA0
+#define XLOG_FPI 0xB0
+/* 0xC0 is used in Postgres 9.5-11 */
+#define XLOG_OVERWRITE_CONTRECORD 0xD0
+
+
+/*
+ * System status indicator. Note this is stored in pg_control; if you change
+ * it, you must bump PG_CONTROL_VERSION
+ */
+typedef enum DBState
+{
+ DB_STARTUP = 0,
+ DB_SHUTDOWNED,
+ DB_SHUTDOWNED_IN_RECOVERY,
+ DB_SHUTDOWNING,
+ DB_IN_CRASH_RECOVERY,
+ DB_IN_ARCHIVE_RECOVERY,
+ DB_IN_PRODUCTION
+} DBState;
+
+/*
+ * Contents of pg_control.
+ */
+
+typedef struct ControlFileData
+{
+ /*
+ * Unique system identifier --- to ensure we match up xlog files with the
+ * installation that produced them.
+ */
+ uint64 system_identifier;
+
+ /*
+ * Version identifier information. Keep these fields at the same offset,
+ * especially pg_control_version; they won't be real useful if they move
+ * around. (For historical reasons they must be 8 bytes into the file
+ * rather than immediately at the front.)
+ *
+ * pg_control_version identifies the format of pg_control itself.
+ * catalog_version_no identifies the format of the system catalogs.
+ *
+ * There are additional version identifiers in individual files; for
+ * example, WAL logs contain per-page magic numbers that can serve as
+ * version cues for the WAL log.
+ */
+ uint32 pg_control_version; /* PG_CONTROL_VERSION */
+ uint32 catalog_version_no; /* see catversion.h */
+
+ /*
+ * System status data
+ */
+ DBState state; /* see enum above */
+ pg_time_t time; /* time stamp of last pg_control update */
+ XLogRecPtr checkPoint; /* last check point record ptr */
+
+ CheckPoint checkPointCopy; /* copy of last check point record */
+
+ XLogRecPtr unloggedLSN; /* current fake LSN value, for unlogged rels */
+
+ /*
+ * These two values determine the minimum point we must recover up to
+ * before starting up:
+ *
+ * minRecoveryPoint is updated to the latest replayed LSN whenever we
+ * flush a data change during archive recovery. That guards against
+ * starting archive recovery, aborting it, and restarting with an earlier
+ * stop location. If we've already flushed data changes from WAL record X
+ * to disk, we mustn't start up until we reach X again. Zero when not
+ * doing archive recovery.
+ *
+ * backupStartPoint is the redo pointer of the backup start checkpoint, if
+ * we are recovering from an online backup and haven't reached the end of
+ * backup yet. It is reset to zero when the end of backup is reached, and
+ * we mustn't start up before that. A boolean would suffice otherwise, but
+ * we use the redo pointer as a cross-check when we see an end-of-backup
+ * record, to make sure the end-of-backup record corresponds the base
+ * backup we're recovering from.
+ *
+ * backupEndPoint is the backup end location, if we are recovering from an
+ * online backup which was taken from the standby and haven't reached the
+ * end of backup yet. It is initialized to the minimum recovery point in
+ * pg_control which was backed up last. It is reset to zero when the end
+ * of backup is reached, and we mustn't start up before that.
+ *
+ * If backupEndRequired is true, we know for sure that we're restoring
+ * from a backup, and must see a backup-end record before we can safely
+ * start up.
+ */
+ XLogRecPtr minRecoveryPoint;
+ TimeLineID minRecoveryPointTLI;
+ XLogRecPtr backupStartPoint;
+ XLogRecPtr backupEndPoint;
+ bool backupEndRequired;
+
+ /*
+ * Parameter settings that determine if the WAL can be used for archival
+ * or hot standby.
+ */
+ int wal_level;
+ bool wal_log_hints;
+ int MaxConnections;
+ int max_worker_processes;
+ int max_wal_senders;
+ int max_prepared_xacts;
+ int max_locks_per_xact;
+ bool track_commit_timestamp;
+
+ /*
+ * This data is used to check for hardware-architecture compatibility of
+ * the database and the backend executable. We need not check endianness
+ * explicitly, since the pg_control version will surely look wrong to a
+ * machine of different endianness, but we do need to worry about MAXALIGN
+ * and floating-point format. (Note: storage layout nominally also
+ * depends on SHORTALIGN and INTALIGN, but in practice these are the same
+ * on all architectures of interest.)
+ *
+ * Testing just one double value is not a very bulletproof test for
+ * floating-point compatibility, but it will catch most cases.
+ */
+ uint32 maxAlign; /* alignment requirement for tuples */
+ double floatFormat; /* constant 1234567.0 */
+#define FLOATFORMAT_VALUE 1234567.0
+
+ /*
+ * This data is used to make sure that configuration of this database is
+ * compatible with the backend executable.
+ */
+ uint32 blcksz; /* data block size for this DB */
+ uint32 relseg_size; /* blocks per segment of large relation */
+
+ uint32 xlog_blcksz; /* block size within WAL files */
+ uint32 xlog_seg_size; /* size of each WAL segment */
+
+ uint32 nameDataLen; /* catalog name field width */
+ uint32 indexMaxKeys; /* max number of columns in an index */
+
+ uint32 toast_max_chunk_size; /* chunk size in TOAST tables */
+ uint32 loblksize; /* chunk size in pg_largeobject */
+
+ bool float8ByVal; /* float8, int8, etc pass-by-value? */
+
+ /* Are data pages protected by checksums? Zero if no checksum version */
+ uint32 data_checksum_version;
+
+ /*
+ * Random nonce, used in authentication requests that need to proceed
+ * based on values that are cluster-unique, like a SASL exchange that
+ * failed at an early stage.
+ */
+ char mock_authentication_nonce[MOCK_AUTH_NONCE_LEN];
+
+ /* CRC of all above ... MUST BE LAST! */
+ pg_crc32c crc;
+} ControlFileData;
+
+/*
+ * Maximum safe value of sizeof(ControlFileData). For reliability's sake,
+ * it's critical that pg_control updates be atomic writes. That generally
+ * means the active data can't be more than one disk sector, which is 512
+ * bytes on common hardware. Be very careful about raising this limit.
+ */
+#define PG_CONTROL_MAX_SAFE_SIZE 512
+
+/*
+ * Physical size of the pg_control file. Note that this is considerably
+ * bigger than the actually used size (ie, sizeof(ControlFileData)).
+ * The idea is to keep the physical size constant independent of format
+ * changes, so that ReadControlFile will deliver a suitable wrong-version
+ * message instead of a read error if it's looking at an incompatible file.
+ */
+#define PG_CONTROL_FILE_SIZE 8192
+
+/*
+ * Ensure that the size of the pg_control data structure is sane.
+ */
+StaticAssertDecl(sizeof(ControlFileData) <= PG_CONTROL_MAX_SAFE_SIZE,
+ "pg_control is too large for atomic disk writes");
+StaticAssertDecl(sizeof(ControlFileData) <= PG_CONTROL_FILE_SIZE,
+ "sizeof(ControlFileData) exceeds PG_CONTROL_FILE_SIZE");
+
+#endif /* PG_CONTROL_H */
diff --git a/contrib/libs/libpq/src/include/common/archive.h b/contrib/libs/libpq/src/include/common/archive.h
new file mode 100644
index 0000000000..95196772c9
--- /dev/null
+++ b/contrib/libs/libpq/src/include/common/archive.h
@@ -0,0 +1,21 @@
+/*-------------------------------------------------------------------------
+ *
+ * archive.h
+ * Common WAL archive routines
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/common/archive.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef ARCHIVE_H
+#define ARCHIVE_H
+
+extern char *BuildRestoreCommand(const char *restoreCommand,
+ const char *xlogpath, /* %p */
+ const char *xlogfname, /* %f */
+ const char *lastRestartPointFname); /* %r */
+
+#endif /* ARCHIVE_H */
diff --git a/contrib/libs/libpq/src/include/common/base64.h b/contrib/libs/libpq/src/include/common/base64.h
new file mode 100644
index 0000000000..5bd8186c79
--- /dev/null
+++ b/contrib/libs/libpq/src/include/common/base64.h
@@ -0,0 +1,19 @@
+/*
+ * base64.h
+ * Encoding and decoding routines for base64 without whitespace
+ * support.
+ *
+ * Portions Copyright (c) 2001-2023, PostgreSQL Global Development Group
+ *
+ * src/include/common/base64.h
+ */
+#ifndef BASE64_H
+#define BASE64_H
+
+/* base 64 */
+extern int pg_b64_encode(const char *src, int len, char *dst, int dstlen);
+extern int pg_b64_decode(const char *src, int len, char *dst, int dstlen);
+extern int pg_b64_enc_len(int srclen);
+extern int pg_b64_dec_len(int srclen);
+
+#endif /* BASE64_H */
diff --git a/contrib/libs/libpq/src/include/common/checksum_helper.h b/contrib/libs/libpq/src/include/common/checksum_helper.h
new file mode 100644
index 0000000000..a74deef67b
--- /dev/null
+++ b/contrib/libs/libpq/src/include/common/checksum_helper.h
@@ -0,0 +1,72 @@
+/*-------------------------------------------------------------------------
+ *
+ * checksum_helper.h
+ * Compute a checksum of any of various types using common routines
+ *
+ * Portions Copyright (c) 2016-2023, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/include/common/checksum_helper.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef CHECKSUM_HELPER_H
+#define CHECKSUM_HELPER_H
+
+#include "common/cryptohash.h"
+#include "common/sha2.h"
+#include "port/pg_crc32c.h"
+
+/*
+ * Supported checksum types. It's not necessarily the case that code using
+ * these functions needs a cryptographically strong checksum; it may only
+ * need to detect accidental modification. That's why we include CRC-32C: it's
+ * much faster than any of the other algorithms. On the other hand, we omit
+ * MD5 here because any new that does need a cryptographically strong checksum
+ * should use something better.
+ */
+typedef enum pg_checksum_type
+{
+ CHECKSUM_TYPE_NONE,
+ CHECKSUM_TYPE_CRC32C,
+ CHECKSUM_TYPE_SHA224,
+ CHECKSUM_TYPE_SHA256,
+ CHECKSUM_TYPE_SHA384,
+ CHECKSUM_TYPE_SHA512
+} pg_checksum_type;
+
+/*
+ * This is just a union of all applicable context types.
+ */
+typedef union pg_checksum_raw_context
+{
+ pg_crc32c c_crc32c;
+ pg_cryptohash_ctx *c_sha2;
+} pg_checksum_raw_context;
+
+/*
+ * This structure provides a convenient way to pass the checksum type and the
+ * checksum context around together.
+ */
+typedef struct pg_checksum_context
+{
+ pg_checksum_type type;
+ pg_checksum_raw_context raw_context;
+} pg_checksum_context;
+
+/*
+ * This is the longest possible output for any checksum algorithm supported
+ * by this file.
+ */
+#define PG_CHECKSUM_MAX_LENGTH PG_SHA512_DIGEST_LENGTH
+
+extern bool pg_checksum_parse_type(char *name, pg_checksum_type *);
+extern char *pg_checksum_type_name(pg_checksum_type);
+
+extern int pg_checksum_init(pg_checksum_context *, pg_checksum_type);
+extern int pg_checksum_update(pg_checksum_context *, const uint8 *input,
+ size_t len);
+extern int pg_checksum_final(pg_checksum_context *, uint8 *output);
+
+#endif
diff --git a/contrib/libs/libpq/src/include/common/compression.h b/contrib/libs/libpq/src/include/common/compression.h
new file mode 100644
index 0000000000..38aae9dd87
--- /dev/null
+++ b/contrib/libs/libpq/src/include/common/compression.h
@@ -0,0 +1,53 @@
+/*-------------------------------------------------------------------------
+ *
+ * compression.h
+ *
+ * Shared definitions for compression methods and specifications.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/include/common/compression.h
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef PG_COMPRESSION_H
+#define PG_COMPRESSION_H
+
+/*
+ * These values are stored in disk, for example in files generated by pg_dump.
+ * Create the necessary backwards compatibility layers if their order changes.
+ */
+typedef enum pg_compress_algorithm
+{
+ PG_COMPRESSION_NONE,
+ PG_COMPRESSION_GZIP,
+ PG_COMPRESSION_LZ4,
+ PG_COMPRESSION_ZSTD
+} pg_compress_algorithm;
+
+#define PG_COMPRESSION_OPTION_WORKERS (1 << 0)
+#define PG_COMPRESSION_OPTION_LONG_DISTANCE (1 << 1)
+
+typedef struct pg_compress_specification
+{
+ pg_compress_algorithm algorithm;
+ unsigned options; /* OR of PG_COMPRESSION_OPTION constants */
+ int level;
+ int workers;
+ bool long_distance;
+ char *parse_error; /* NULL if parsing was OK, else message */
+} pg_compress_specification;
+
+extern void parse_compress_options(const char *option, char **algorithm,
+ char **detail);
+extern bool parse_compress_algorithm(char *name, pg_compress_algorithm *algorithm);
+extern const char *get_compress_algorithm_name(pg_compress_algorithm algorithm);
+
+extern void parse_compress_specification(pg_compress_algorithm algorithm,
+ char *specification,
+ pg_compress_specification *result);
+
+extern char *validate_compress_specification(pg_compress_specification *);
+
+#endif
diff --git a/contrib/libs/libpq/src/include/common/config_info.h b/contrib/libs/libpq/src/include/common/config_info.h
new file mode 100644
index 0000000000..a6d076d5e9
--- /dev/null
+++ b/contrib/libs/libpq/src/include/common/config_info.h
@@ -0,0 +1,21 @@
+/*
+ * config_info.h
+ * Common code for pg_config output
+ *
+ * Copyright (c) 2016-2023, PostgreSQL Global Development Group
+ *
+ * src/include/common/config_info.h
+ */
+#ifndef COMMON_CONFIG_INFO_H
+#define COMMON_CONFIG_INFO_H
+
+typedef struct ConfigData
+{
+ char *name;
+ char *setting;
+} ConfigData;
+
+extern ConfigData *get_configdata(const char *my_exec_path,
+ size_t *configdata_len);
+
+#endif /* COMMON_CONFIG_INFO_H */
diff --git a/contrib/libs/libpq/src/include/common/controldata_utils.h b/contrib/libs/libpq/src/include/common/controldata_utils.h
new file mode 100644
index 0000000000..49e7c52d31
--- /dev/null
+++ b/contrib/libs/libpq/src/include/common/controldata_utils.h
@@ -0,0 +1,19 @@
+/*
+ * controldata_utils.h
+ * Common code for pg_controldata output
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/common/controldata_utils.h
+ */
+#ifndef COMMON_CONTROLDATA_UTILS_H
+#define COMMON_CONTROLDATA_UTILS_H
+
+#include "catalog/pg_control.h"
+
+extern ControlFileData *get_controlfile(const char *DataDir, bool *crc_ok_p);
+extern void update_controlfile(const char *DataDir,
+ ControlFileData *ControlFile, bool do_sync);
+
+#endif /* COMMON_CONTROLDATA_UTILS_H */
diff --git a/contrib/libs/libpq/src/include/common/cryptohash.h b/contrib/libs/libpq/src/include/common/cryptohash.h
new file mode 100644
index 0000000000..24b6dbebbd
--- /dev/null
+++ b/contrib/libs/libpq/src/include/common/cryptohash.h
@@ -0,0 +1,39 @@
+/*-------------------------------------------------------------------------
+ *
+ * cryptohash.h
+ * Generic headers for cryptographic hash functions.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/include/common/cryptohash.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef PG_CRYPTOHASH_H
+#define PG_CRYPTOHASH_H
+
+/* Context Structures for each hash function */
+typedef enum
+{
+ PG_MD5 = 0,
+ PG_SHA1,
+ PG_SHA224,
+ PG_SHA256,
+ PG_SHA384,
+ PG_SHA512
+} pg_cryptohash_type;
+
+/* opaque context, private to each cryptohash implementation */
+typedef struct pg_cryptohash_ctx pg_cryptohash_ctx;
+
+extern pg_cryptohash_ctx *pg_cryptohash_create(pg_cryptohash_type type);
+extern int pg_cryptohash_init(pg_cryptohash_ctx *ctx);
+extern int pg_cryptohash_update(pg_cryptohash_ctx *ctx, const uint8 *data, size_t len);
+extern int pg_cryptohash_final(pg_cryptohash_ctx *ctx, uint8 *dest, size_t len);
+extern void pg_cryptohash_free(pg_cryptohash_ctx *ctx);
+extern const char *pg_cryptohash_error(pg_cryptohash_ctx *ctx);
+
+#endif /* PG_CRYPTOHASH_H */
diff --git a/contrib/libs/libpq/src/include/common/fe_memutils.h b/contrib/libs/libpq/src/include/common/fe_memutils.h
new file mode 100644
index 0000000000..89601cc778
--- /dev/null
+++ b/contrib/libs/libpq/src/include/common/fe_memutils.h
@@ -0,0 +1,73 @@
+/*
+ * fe_memutils.h
+ * memory management support for frontend code
+ *
+ * Copyright (c) 2003-2023, PostgreSQL Global Development Group
+ *
+ * src/include/common/fe_memutils.h
+ */
+#ifndef FE_MEMUTILS_H
+#define FE_MEMUTILS_H
+
+/*
+ * Flags for pg_malloc_extended and palloc_extended, deliberately named
+ * the same as the backend flags.
+ */
+#define MCXT_ALLOC_HUGE 0x01 /* allow huge allocation (> 1 GB) not
+ * actually used for frontends */
+#define MCXT_ALLOC_NO_OOM 0x02 /* no failure if out-of-memory */
+#define MCXT_ALLOC_ZERO 0x04 /* zero allocated memory */
+
+/*
+ * "Safe" memory allocation functions --- these exit(1) on failure
+ * (except pg_malloc_extended with MCXT_ALLOC_NO_OOM)
+ */
+extern char *pg_strdup(const char *in);
+extern void *pg_malloc(size_t size);
+extern void *pg_malloc0(size_t size);
+extern void *pg_malloc_extended(size_t size, int flags);
+extern void *pg_realloc(void *ptr, size_t size);
+extern void pg_free(void *ptr);
+
+/*
+ * Variants with easier notation and more type safety
+ */
+
+/*
+ * Allocate space for one object of type "type"
+ */
+#define pg_malloc_object(type) ((type *) pg_malloc(sizeof(type)))
+#define pg_malloc0_object(type) ((type *) pg_malloc0(sizeof(type)))
+
+/*
+ * Allocate space for "count" objects of type "type"
+ */
+#define pg_malloc_array(type, count) ((type *) pg_malloc(sizeof(type) * (count)))
+#define pg_malloc0_array(type, count) ((type *) pg_malloc0(sizeof(type) * (count)))
+
+/*
+ * Change size of allocation pointed to by "pointer" to have space for "count"
+ * objects of type "type"
+ */
+#define pg_realloc_array(pointer, type, count) ((type *) pg_realloc(pointer, sizeof(type) * (count)))
+
+/* Equivalent functions, deliberately named the same as backend functions */
+extern char *pstrdup(const char *in);
+extern char *pnstrdup(const char *in, Size size);
+extern void *palloc(Size size);
+extern void *palloc0(Size size);
+extern void *palloc_extended(Size size, int flags);
+extern void *repalloc(void *pointer, Size size);
+extern void pfree(void *pointer);
+
+#define palloc_object(type) ((type *) palloc(sizeof(type)))
+#define palloc0_object(type) ((type *) palloc0(sizeof(type)))
+#define palloc_array(type, count) ((type *) palloc(sizeof(type) * (count)))
+#define palloc0_array(type, count) ((type *) palloc0(sizeof(type) * (count)))
+#define repalloc_array(pointer, type, count) ((type *) repalloc(pointer, sizeof(type) * (count)))
+
+/* sprintf into a palloc'd buffer --- these are in psprintf.c */
+extern char *psprintf(const char *fmt,...) pg_attribute_printf(1, 2);
+extern size_t pvsnprintf(char *buf, size_t len, const char *fmt, va_list args) pg_attribute_printf(3, 0);
+
+#endif /* FE_MEMUTILS_H */
diff --git a/contrib/libs/libpq/src/include/common/file_perm.h b/contrib/libs/libpq/src/include/common/file_perm.h
new file mode 100644
index 0000000000..978c0d072f
--- /dev/null
+++ b/contrib/libs/libpq/src/include/common/file_perm.h
@@ -0,0 +1,56 @@
+/*-------------------------------------------------------------------------
+ *
+ * File and directory permission definitions
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/common/file_perm.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef FILE_PERM_H
+#define FILE_PERM_H
+
+#include <sys/stat.h>
+
+/*
+ * Mode mask for data directory permissions that only allows the owner to
+ * read/write directories and files.
+ *
+ * This is the default.
+ */
+#define PG_MODE_MASK_OWNER (S_IRWXG | S_IRWXO)
+
+/*
+ * Mode mask for data directory permissions that also allows group read/execute.
+ */
+#define PG_MODE_MASK_GROUP (S_IWGRP | S_IRWXO)
+
+/* Default mode for creating directories */
+#define PG_DIR_MODE_OWNER S_IRWXU
+
+/* Mode for creating directories that allows group read/execute */
+#define PG_DIR_MODE_GROUP (S_IRWXU | S_IRGRP | S_IXGRP)
+
+/* Default mode for creating files */
+#define PG_FILE_MODE_OWNER (S_IRUSR | S_IWUSR)
+
+/* Mode for creating files that allows group read */
+#define PG_FILE_MODE_GROUP (S_IRUSR | S_IWUSR | S_IRGRP)
+
+/* Modes for creating directories and files in the data directory */
+extern PGDLLIMPORT int pg_dir_create_mode;
+extern PGDLLIMPORT int pg_file_create_mode;
+
+/* Mode mask to pass to umask() */
+extern PGDLLIMPORT int pg_mode_mask;
+
+/* Set permissions and mask based on the provided mode */
+extern void SetDataDirectoryCreatePerm(int dataDirMode);
+
+/* Set permissions and mask based on the mode of the data directory */
+extern bool GetDataDirectoryCreatePerm(const char *dataDir);
+
+#endif /* FILE_PERM_H */
diff --git a/contrib/libs/libpq/src/include/common/file_utils.h b/contrib/libs/libpq/src/include/common/file_utils.h
new file mode 100644
index 0000000000..b7efa1226d
--- /dev/null
+++ b/contrib/libs/libpq/src/include/common/file_utils.h
@@ -0,0 +1,49 @@
+/*-------------------------------------------------------------------------
+ *
+ * Assorted utility functions to work on files.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/common/file_utils.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef FILE_UTILS_H
+#define FILE_UTILS_H
+
+#include <dirent.h>
+
+typedef enum PGFileType
+{
+ PGFILETYPE_ERROR,
+ PGFILETYPE_UNKNOWN,
+ PGFILETYPE_REG,
+ PGFILETYPE_DIR,
+ PGFILETYPE_LNK
+} PGFileType;
+
+struct iovec; /* avoid including port/pg_iovec.h here */
+
+#ifdef FRONTEND
+extern int fsync_fname(const char *fname, bool isdir);
+extern void fsync_pgdata(const char *pg_data, int serverVersion);
+extern void fsync_dir_recurse(const char *dir);
+extern int durable_rename(const char *oldfile, const char *newfile);
+extern int fsync_parent_path(const char *fname);
+#endif
+
+extern PGFileType get_dirent_type(const char *path,
+ const struct dirent *de,
+ bool look_through_symlinks,
+ int elevel);
+
+extern ssize_t pg_pwritev_with_retry(int fd,
+ const struct iovec *iov,
+ int iovcnt,
+ off_t offset);
+
+extern ssize_t pg_pwrite_zeros(int fd, size_t size, off_t offset);
+
+#endif /* FILE_UTILS_H */
diff --git a/contrib/libs/libpq/src/include/common/hashfn.h b/contrib/libs/libpq/src/include/common/hashfn.h
new file mode 100644
index 0000000000..5e89aef987
--- /dev/null
+++ b/contrib/libs/libpq/src/include/common/hashfn.h
@@ -0,0 +1,104 @@
+/*
+ * Utilities for working with hash values.
+ *
+ * Portions Copyright (c) 2017-2023, PostgreSQL Global Development Group
+ */
+
+#ifndef HASHFN_H
+#define HASHFN_H
+
+
+/*
+ * Rotate the high 32 bits and the low 32 bits separately. The standard
+ * hash function sometimes rotates the low 32 bits by one bit when
+ * combining elements. We want extended hash functions to be compatible with
+ * that algorithm when the seed is 0, so we can't just do a normal rotation.
+ * This works, though.
+ */
+#define ROTATE_HIGH_AND_LOW_32BITS(v) \
+ ((((v) << 1) & UINT64CONST(0xfffffffefffffffe)) | \
+ (((v) >> 31) & UINT64CONST(0x100000001)))
+
+
+extern uint32 hash_bytes(const unsigned char *k, int keylen);
+extern uint64 hash_bytes_extended(const unsigned char *k,
+ int keylen, uint64 seed);
+extern uint32 hash_bytes_uint32(uint32 k);
+extern uint64 hash_bytes_uint32_extended(uint32 k, uint64 seed);
+
+#ifndef FRONTEND
+static inline Datum
+hash_any(const unsigned char *k, int keylen)
+{
+ return UInt32GetDatum(hash_bytes(k, keylen));
+}
+
+static inline Datum
+hash_any_extended(const unsigned char *k, int keylen, uint64 seed)
+{
+ return UInt64GetDatum(hash_bytes_extended(k, keylen, seed));
+}
+
+static inline Datum
+hash_uint32(uint32 k)
+{
+ return UInt32GetDatum(hash_bytes_uint32(k));
+}
+
+static inline Datum
+hash_uint32_extended(uint32 k, uint64 seed)
+{
+ return UInt64GetDatum(hash_bytes_uint32_extended(k, seed));
+}
+#endif
+
+extern uint32 string_hash(const void *key, Size keysize);
+extern uint32 tag_hash(const void *key, Size keysize);
+extern uint32 uint32_hash(const void *key, Size keysize);
+
+#define oid_hash uint32_hash /* Remove me eventually */
+
+/*
+ * Combine two 32-bit hash values, resulting in another hash value, with
+ * decent bit mixing.
+ *
+ * Similar to boost's hash_combine().
+ */
+static inline uint32
+hash_combine(uint32 a, uint32 b)
+{
+ a ^= b + 0x9e3779b9 + (a << 6) + (a >> 2);
+ return a;
+}
+
+/*
+ * Combine two 64-bit hash values, resulting in another hash value, using the
+ * same kind of technique as hash_combine(). Testing shows that this also
+ * produces good bit mixing.
+ */
+static inline uint64
+hash_combine64(uint64 a, uint64 b)
+{
+ /* 0x49a0f4dd15e5a8e3 is 64bit random data */
+ a ^= b + UINT64CONST(0x49a0f4dd15e5a8e3) + (a << 54) + (a >> 7);
+ return a;
+}
+
+/*
+ * Simple inline murmur hash implementation hashing a 32 bit integer, for
+ * performance.
+ */
+static inline uint32
+murmurhash32(uint32 data)
+{
+ uint32 h = data;
+
+ h ^= h >> 16;
+ h *= 0x85ebca6b;
+ h ^= h >> 13;
+ h *= 0xc2b2ae35;
+ h ^= h >> 16;
+ return h;
+}
+
+#endif /* HASHFN_H */
diff --git a/contrib/libs/libpq/src/include/common/hmac.h b/contrib/libs/libpq/src/include/common/hmac.h
new file mode 100644
index 0000000000..e0b2ed2024
--- /dev/null
+++ b/contrib/libs/libpq/src/include/common/hmac.h
@@ -0,0 +1,30 @@
+/*-------------------------------------------------------------------------
+ *
+ * hmac.h
+ * Generic headers for HMAC
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/include/common/hmac.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef PG_HMAC_H
+#define PG_HMAC_H
+
+#include "common/cryptohash.h"
+
+/* opaque context, private to each HMAC implementation */
+typedef struct pg_hmac_ctx pg_hmac_ctx;
+
+extern pg_hmac_ctx *pg_hmac_create(pg_cryptohash_type type);
+extern int pg_hmac_init(pg_hmac_ctx *ctx, const uint8 *key, size_t len);
+extern int pg_hmac_update(pg_hmac_ctx *ctx, const uint8 *data, size_t len);
+extern int pg_hmac_final(pg_hmac_ctx *ctx, uint8 *dest, size_t len);
+extern void pg_hmac_free(pg_hmac_ctx *ctx);
+extern const char *pg_hmac_error(pg_hmac_ctx *ctx);
+
+#endif /* PG_HMAC_H */
diff --git a/contrib/libs/libpq/src/include/common/ip.h b/contrib/libs/libpq/src/include/common/ip.h
new file mode 100644
index 0000000000..9f2ed5fe0a
--- /dev/null
+++ b/contrib/libs/libpq/src/include/common/ip.h
@@ -0,0 +1,33 @@
+/*-------------------------------------------------------------------------
+ *
+ * ip.h
+ * Definitions for IPv6-aware network access.
+ *
+ * These definitions are used by both frontend and backend code.
+ *
+ * Copyright (c) 2003-2023, PostgreSQL Global Development Group
+ *
+ * src/include/common/ip.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef IP_H
+#define IP_H
+
+#include <netdb.h>
+#include <sys/socket.h>
+
+#include "libpq/pqcomm.h" /* pgrminclude ignore */
+
+
+extern int pg_getaddrinfo_all(const char *hostname, const char *servname,
+ const struct addrinfo *hintp,
+ struct addrinfo **result);
+extern void pg_freeaddrinfo_all(int hint_ai_family, struct addrinfo *ai);
+
+extern int pg_getnameinfo_all(const struct sockaddr_storage *addr, int salen,
+ char *node, int nodelen,
+ char *service, int servicelen,
+ int flags);
+
+#endif /* IP_H */
diff --git a/contrib/libs/libpq/src/include/common/jsonapi.h b/contrib/libs/libpq/src/include/common/jsonapi.h
new file mode 100644
index 0000000000..4310084b2b
--- /dev/null
+++ b/contrib/libs/libpq/src/include/common/jsonapi.h
@@ -0,0 +1,177 @@
+/*-------------------------------------------------------------------------
+ *
+ * jsonapi.h
+ * Declarations for JSON API support.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/common/jsonapi.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef JSONAPI_H
+#define JSONAPI_H
+
+#include "lib/stringinfo.h"
+
+typedef enum JsonTokenType
+{
+ JSON_TOKEN_INVALID,
+ JSON_TOKEN_STRING,
+ JSON_TOKEN_NUMBER,
+ JSON_TOKEN_OBJECT_START,
+ JSON_TOKEN_OBJECT_END,
+ JSON_TOKEN_ARRAY_START,
+ JSON_TOKEN_ARRAY_END,
+ JSON_TOKEN_COMMA,
+ JSON_TOKEN_COLON,
+ JSON_TOKEN_TRUE,
+ JSON_TOKEN_FALSE,
+ JSON_TOKEN_NULL,
+ JSON_TOKEN_END
+} JsonTokenType;
+
+typedef enum JsonParseErrorType
+{
+ JSON_SUCCESS,
+ JSON_ESCAPING_INVALID,
+ JSON_ESCAPING_REQUIRED,
+ JSON_EXPECTED_ARRAY_FIRST,
+ JSON_EXPECTED_ARRAY_NEXT,
+ JSON_EXPECTED_COLON,
+ JSON_EXPECTED_END,
+ JSON_EXPECTED_JSON,
+ JSON_EXPECTED_MORE,
+ JSON_EXPECTED_OBJECT_FIRST,
+ JSON_EXPECTED_OBJECT_NEXT,
+ JSON_EXPECTED_STRING,
+ JSON_INVALID_TOKEN,
+ JSON_UNICODE_CODE_POINT_ZERO,
+ JSON_UNICODE_ESCAPE_FORMAT,
+ JSON_UNICODE_HIGH_ESCAPE,
+ JSON_UNICODE_UNTRANSLATABLE,
+ JSON_UNICODE_HIGH_SURROGATE,
+ JSON_UNICODE_LOW_SURROGATE,
+ JSON_SEM_ACTION_FAILED /* error should already be reported */
+} JsonParseErrorType;
+
+
+/*
+ * All the fields in this structure should be treated as read-only.
+ *
+ * If strval is not null, then it should contain the de-escaped value
+ * of the lexeme if it's a string. Otherwise most of these field names
+ * should be self-explanatory.
+ *
+ * line_number and line_start are principally for use by the parser's
+ * error reporting routines.
+ * token_terminator and prev_token_terminator point to the character
+ * AFTER the end of the token, i.e. where there would be a nul byte
+ * if we were using nul-terminated strings.
+ */
+typedef struct JsonLexContext
+{
+ char *input;
+ int input_length;
+ int input_encoding;
+ char *token_start;
+ char *token_terminator;
+ char *prev_token_terminator;
+ JsonTokenType token_type;
+ int lex_level;
+ int line_number; /* line number, starting from 1 */
+ char *line_start; /* where that line starts within input */
+ StringInfo strval;
+} JsonLexContext;
+
+typedef JsonParseErrorType (*json_struct_action) (void *state);
+typedef JsonParseErrorType (*json_ofield_action) (void *state, char *fname, bool isnull);
+typedef JsonParseErrorType (*json_aelem_action) (void *state, bool isnull);
+typedef JsonParseErrorType (*json_scalar_action) (void *state, char *token, JsonTokenType tokentype);
+
+
+/*
+ * Semantic Action structure for use in parsing json.
+ *
+ * Any of these actions can be NULL, in which case nothing is done at that
+ * point, Likewise, semstate can be NULL. Using an all-NULL structure amounts
+ * to doing a pure parse with no side-effects, and is therefore exactly
+ * what the json input routines do.
+ *
+ * The 'fname' and 'token' strings passed to these actions are palloc'd.
+ * They are not free'd or used further by the parser, so the action function
+ * is free to do what it wishes with them.
+ *
+ * All action functions return JsonParseErrorType. If the result isn't
+ * JSON_SUCCESS, the parse is abandoned and that error code is returned.
+ * If it is JSON_SEM_ACTION_FAILED, the action function is responsible
+ * for having reported the error in some appropriate way.
+ */
+typedef struct JsonSemAction
+{
+ void *semstate;
+ json_struct_action object_start;
+ json_struct_action object_end;
+ json_struct_action array_start;
+ json_struct_action array_end;
+ json_ofield_action object_field_start;
+ json_ofield_action object_field_end;
+ json_aelem_action array_element_start;
+ json_aelem_action array_element_end;
+ json_scalar_action scalar;
+} JsonSemAction;
+
+/*
+ * pg_parse_json will parse the string in the lex calling the
+ * action functions in sem at the appropriate points. It is
+ * up to them to keep what state they need in semstate. If they
+ * need access to the state of the lexer, then its pointer
+ * should be passed to them as a member of whatever semstate
+ * points to. If the action pointers are NULL the parser
+ * does nothing and just continues.
+ */
+extern JsonParseErrorType pg_parse_json(JsonLexContext *lex,
+ JsonSemAction *sem);
+
+/* the null action object used for pure validation */
+extern PGDLLIMPORT JsonSemAction nullSemAction;
+
+/*
+ * json_count_array_elements performs a fast secondary parse to determine the
+ * number of elements in passed array lex context. It should be called from an
+ * array_start action.
+ *
+ * The return value indicates whether any error occurred, while the number
+ * of elements is stored into *elements (but only if the return value is
+ * JSON_SUCCESS).
+ */
+extern JsonParseErrorType json_count_array_elements(JsonLexContext *lex,
+ int *elements);
+
+/*
+ * constructor for JsonLexContext, with or without strval element.
+ * If supplied, the strval element will contain a de-escaped version of
+ * the lexeme. However, doing this imposes a performance penalty, so
+ * it should be avoided if the de-escaped lexeme is not required.
+ */
+extern JsonLexContext *makeJsonLexContextCstringLen(char *json,
+ int len,
+ int encoding,
+ bool need_escapes);
+
+/* lex one token */
+extern JsonParseErrorType json_lex(JsonLexContext *lex);
+
+/* construct an error detail string for a json error */
+extern char *json_errdetail(JsonParseErrorType error, JsonLexContext *lex);
+
+/*
+ * Utility function to check if a string is a valid JSON number.
+ *
+ * str argument does not need to be nul-terminated.
+ */
+extern bool IsValidJsonNumber(const char *str, int len);
+
+#endif /* JSONAPI_H */
diff --git a/contrib/libs/libpq/src/include/common/keywords.h b/contrib/libs/libpq/src/include/common/keywords.h
new file mode 100644
index 0000000000..6bb12d8edb
--- /dev/null
+++ b/contrib/libs/libpq/src/include/common/keywords.h
@@ -0,0 +1,29 @@
+/*-------------------------------------------------------------------------
+ *
+ * keywords.h
+ * PostgreSQL's list of SQL keywords
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/common/keywords.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef KEYWORDS_H
+#define KEYWORDS_H
+
+#include "common/kwlookup.h"
+
+/* Keyword categories --- should match lists in gram.y */
+#define UNRESERVED_KEYWORD 0
+#define COL_NAME_KEYWORD 1
+#define TYPE_FUNC_NAME_KEYWORD 2
+#define RESERVED_KEYWORD 3
+
+extern PGDLLIMPORT const ScanKeywordList ScanKeywords;
+extern PGDLLIMPORT const uint8 ScanKeywordCategories[];
+extern PGDLLIMPORT const bool ScanKeywordBareLabel[];
+
+#endif /* KEYWORDS_H */
diff --git a/contrib/libs/libpq/src/include/common/kwlookup.h b/contrib/libs/libpq/src/include/common/kwlookup.h
new file mode 100644
index 0000000000..3fc3faa043
--- /dev/null
+++ b/contrib/libs/libpq/src/include/common/kwlookup.h
@@ -0,0 +1,44 @@
+/*-------------------------------------------------------------------------
+ *
+ * kwlookup.h
+ * Key word lookup for PostgreSQL
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/common/kwlookup.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef KWLOOKUP_H
+#define KWLOOKUP_H
+
+/* Hash function used by ScanKeywordLookup */
+typedef int (*ScanKeywordHashFunc) (const void *key, size_t keylen);
+
+/*
+ * This struct contains the data needed by ScanKeywordLookup to perform a
+ * search within a set of keywords. The contents are typically generated by
+ * src/tools/gen_keywordlist.pl from a header containing PG_KEYWORD macros.
+ */
+typedef struct ScanKeywordList
+{
+ const char *kw_string; /* all keywords in order, separated by \0 */
+ const uint16 *kw_offsets; /* offsets to the start of each keyword */
+ ScanKeywordHashFunc hash; /* perfect hash function for keywords */
+ int num_keywords; /* number of keywords */
+ int max_kw_len; /* length of longest keyword */
+} ScanKeywordList;
+
+
+extern int ScanKeywordLookup(const char *str, const ScanKeywordList *keywords);
+
+/* Code that wants to retrieve the text of the N'th keyword should use this. */
+static inline const char *
+GetScanKeyword(int n, const ScanKeywordList *keywords)
+{
+ return keywords->kw_string + keywords->kw_offsets[n];
+}
+
+#endif /* KWLOOKUP_H */
diff --git a/contrib/libs/libpq/src/include/common/link-canary.h b/contrib/libs/libpq/src/include/common/link-canary.h
new file mode 100644
index 0000000000..178d123b1a
--- /dev/null
+++ b/contrib/libs/libpq/src/include/common/link-canary.h
@@ -0,0 +1,17 @@
+/*-------------------------------------------------------------------------
+ *
+ * link-canary.h
+ * Detect whether src/common functions came from frontend or backend.
+ *
+ * Copyright (c) 2018-2023, PostgreSQL Global Development Group
+ *
+ * src/include/common/link-canary.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef LINK_CANARY_H
+#define LINK_CANARY_H
+
+extern bool pg_link_canary_is_frontend(void);
+
+#endif /* LINK_CANARY_H */
diff --git a/contrib/libs/libpq/src/include/common/logging.h b/contrib/libs/libpq/src/include/common/logging.h
new file mode 100644
index 0000000000..99e888af93
--- /dev/null
+++ b/contrib/libs/libpq/src/include/common/logging.h
@@ -0,0 +1,156 @@
+/*-------------------------------------------------------------------------
+ * Logging framework for frontend programs
+ *
+ * Copyright (c) 2018-2023, PostgreSQL Global Development Group
+ *
+ * src/include/common/logging.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef COMMON_LOGGING_H
+#define COMMON_LOGGING_H
+
+/*
+ * Log levels are informational only. They do not affect program flow.
+ */
+enum pg_log_level
+{
+ /*
+ * Not initialized yet (not to be used as an actual message log level).
+ */
+ PG_LOG_NOTSET = 0,
+
+ /*
+ * Low level messages that are normally off by default.
+ */
+ PG_LOG_DEBUG,
+
+ /*
+ * Any program messages that go to stderr, shown by default. (The
+ * program's normal output should go to stdout and not use the logging
+ * system.)
+ */
+ PG_LOG_INFO,
+
+ /*
+ * Warnings and "almost" errors, depends on the program
+ */
+ PG_LOG_WARNING,
+
+ /*
+ * Errors
+ */
+ PG_LOG_ERROR,
+
+ /*
+ * Turn all logging off (not to be used as an actual message log level).
+ */
+ PG_LOG_OFF,
+};
+
+/*
+ * __pg_log_level is the minimum log level that will actually be shown.
+ */
+extern enum pg_log_level __pg_log_level;
+
+/*
+ * A log message can have several parts. The primary message is required,
+ * others are optional. When emitting multiple parts, do so in the order of
+ * this enum, for consistency.
+ */
+enum pg_log_part
+{
+ /*
+ * The primary message. Try to keep it to one line; follow the backend's
+ * style guideline for primary messages.
+ */
+ PG_LOG_PRIMARY,
+
+ /*
+ * Additional detail. Follow the backend's style guideline for detail
+ * messages.
+ */
+ PG_LOG_DETAIL,
+
+ /*
+ * Hint (not guaranteed correct) about how to fix the problem. Follow the
+ * backend's style guideline for hint messages.
+ */
+ PG_LOG_HINT,
+};
+
+/*
+ * Kind of a hack to be able to produce the psql output exactly as required by
+ * the regression tests.
+ */
+#define PG_LOG_FLAG_TERSE 1
+
+void pg_logging_init(const char *argv0);
+void pg_logging_config(int new_flags);
+void pg_logging_set_level(enum pg_log_level new_level);
+void pg_logging_increase_verbosity(void);
+void pg_logging_set_pre_callback(void (*cb) (void));
+void pg_logging_set_locus_callback(void (*cb) (const char **filename, uint64 *lineno));
+
+void pg_log_generic(enum pg_log_level level, enum pg_log_part part,
+ const char *pg_restrict fmt,...)
+ pg_attribute_printf(3, 4);
+void pg_log_generic_v(enum pg_log_level level, enum pg_log_part part,
+ const char *pg_restrict fmt, va_list ap)
+ pg_attribute_printf(3, 0);
+
+/*
+ * Preferred style is to use these macros to perform logging; don't call
+ * pg_log_generic[_v] directly, except perhaps in error interface code.
+ */
+#define pg_log_error(...) \
+ pg_log_generic(PG_LOG_ERROR, PG_LOG_PRIMARY, __VA_ARGS__)
+
+#define pg_log_error_detail(...) \
+ pg_log_generic(PG_LOG_ERROR, PG_LOG_DETAIL, __VA_ARGS__)
+
+#define pg_log_error_hint(...) \
+ pg_log_generic(PG_LOG_ERROR, PG_LOG_HINT, __VA_ARGS__)
+
+#define pg_log_warning(...) \
+ pg_log_generic(PG_LOG_WARNING, PG_LOG_PRIMARY, __VA_ARGS__)
+
+#define pg_log_warning_detail(...) \
+ pg_log_generic(PG_LOG_WARNING, PG_LOG_DETAIL, __VA_ARGS__)
+
+#define pg_log_warning_hint(...) \
+ pg_log_generic(PG_LOG_WARNING, PG_LOG_HINT, __VA_ARGS__)
+
+#define pg_log_info(...) \
+ pg_log_generic(PG_LOG_INFO, PG_LOG_PRIMARY, __VA_ARGS__)
+
+#define pg_log_info_detail(...) \
+ pg_log_generic(PG_LOG_INFO, PG_LOG_DETAIL, __VA_ARGS__)
+
+#define pg_log_info_hint(...) \
+ pg_log_generic(PG_LOG_INFO, PG_LOG_HINT, __VA_ARGS__)
+
+#define pg_log_debug(...) do { \
+ if (unlikely(__pg_log_level <= PG_LOG_DEBUG)) \
+ pg_log_generic(PG_LOG_DEBUG, PG_LOG_PRIMARY, __VA_ARGS__); \
+ } while(0)
+
+#define pg_log_debug_detail(...) do { \
+ if (unlikely(__pg_log_level <= PG_LOG_DEBUG)) \
+ pg_log_generic(PG_LOG_DEBUG, PG_LOG_DETAIL, __VA_ARGS__); \
+ } while(0)
+
+#define pg_log_debug_hint(...) do { \
+ if (unlikely(__pg_log_level <= PG_LOG_DEBUG)) \
+ pg_log_generic(PG_LOG_DEBUG, PG_LOG_HINT, __VA_ARGS__); \
+ } while(0)
+
+/*
+ * A common shortcut: pg_log_error() and immediately exit(1).
+ */
+#define pg_fatal(...) do { \
+ pg_log_generic(PG_LOG_ERROR, PG_LOG_PRIMARY, __VA_ARGS__); \
+ exit(1); \
+ } while(0)
+
+#endif /* COMMON_LOGGING_H */
diff --git a/contrib/libs/libpq/src/include/common/md5.h b/contrib/libs/libpq/src/include/common/md5.h
new file mode 100644
index 0000000000..b6089bacff
--- /dev/null
+++ b/contrib/libs/libpq/src/include/common/md5.h
@@ -0,0 +1,37 @@
+/*-------------------------------------------------------------------------
+ *
+ * md5.h
+ * Constants and common utilities related to MD5.
+ *
+ * These definitions are needed by both frontend and backend code to work
+ * with MD5-encrypted passwords.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/common/md5.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_MD5_H
+#define PG_MD5_H
+
+/* Size of result generated by MD5 computation */
+#define MD5_DIGEST_LENGTH 16
+/* Block size for MD5 */
+#define MD5_BLOCK_SIZE 64
+
+/* password-related data */
+#define MD5_PASSWD_CHARSET "0123456789abcdef"
+#define MD5_PASSWD_LEN 35
+
+/* Utilities common to all the MD5 implementations, as of md5_common.c */
+extern bool pg_md5_hash(const void *buff, size_t len, char *hexsum,
+ const char **errstr);
+extern bool pg_md5_binary(const void *buff, size_t len, void *outbuf,
+ const char **errstr);
+extern bool pg_md5_encrypt(const char *passwd, const char *salt,
+ size_t salt_len, char *buf,
+ const char **errstr);
+
+#endif /* PG_MD5_H */
diff --git a/contrib/libs/libpq/src/include/common/openssl.h b/contrib/libs/libpq/src/include/common/openssl.h
new file mode 100644
index 0000000000..060675ab33
--- /dev/null
+++ b/contrib/libs/libpq/src/include/common/openssl.h
@@ -0,0 +1,49 @@
+/*-------------------------------------------------------------------------
+ *
+ * openssl.h
+ * OpenSSL supporting functionality shared between frontend and backend
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/include/common/openssl.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef COMMON_OPENSSL_H
+#define COMMON_OPENSSL_H
+
+#ifdef USE_OPENSSL
+#include <openssl/ssl.h>
+
+/*
+ * OpenSSL doesn't provide any very nice way to identify the min/max
+ * protocol versions the library supports, so we fake it as best we can.
+ * Note in particular that this doesn't account for restrictions that
+ * might be specified in the installation's openssl.cnf.
+ *
+ * We disable SSLv3 and older in library setup, so TLSv1 is the oldest
+ * protocol version of interest.
+ */
+#define MIN_OPENSSL_TLS_VERSION "TLSv1"
+
+#if defined(TLS1_3_VERSION)
+#define MAX_OPENSSL_TLS_VERSION "TLSv1.3"
+#elif defined(TLS1_2_VERSION)
+#define MAX_OPENSSL_TLS_VERSION "TLSv1.2"
+#elif defined(TLS1_1_VERSION)
+#define MAX_OPENSSL_TLS_VERSION "TLSv1.1"
+#else
+#define MAX_OPENSSL_TLS_VERSION "TLSv1"
+#endif
+
+/* src/common/protocol_openssl.c */
+#ifndef SSL_CTX_set_min_proto_version
+extern int SSL_CTX_set_min_proto_version(SSL_CTX *ctx, int version);
+extern int SSL_CTX_set_max_proto_version(SSL_CTX *ctx, int version);
+#endif
+
+#endif /* USE_OPENSSL */
+
+#endif /* COMMON_OPENSSL_H */
diff --git a/contrib/libs/libpq/src/include/common/percentrepl.h b/contrib/libs/libpq/src/include/common/percentrepl.h
new file mode 100644
index 0000000000..0efb6ecb5b
--- /dev/null
+++ b/contrib/libs/libpq/src/include/common/percentrepl.h
@@ -0,0 +1,18 @@
+/*-------------------------------------------------------------------------
+ *
+ * percentrepl.h
+ * Common routines to replace percent placeholders in strings
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/common/percentrepl.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PERCENTREPL_H
+#define PERCENTREPL_H
+
+extern char *replace_percent_placeholders(const char *instr, const char *param_name, const char *letters,...);
+
+#endif /* PERCENTREPL_H */
diff --git a/contrib/libs/libpq/src/include/common/pg_lzcompress.h b/contrib/libs/libpq/src/include/common/pg_lzcompress.h
new file mode 100644
index 0000000000..2a12b33a00
--- /dev/null
+++ b/contrib/libs/libpq/src/include/common/pg_lzcompress.h
@@ -0,0 +1,93 @@
+/* ----------
+ * pg_lzcompress.h -
+ *
+ * Definitions for the builtin LZ compressor
+ *
+ * src/include/common/pg_lzcompress.h
+ * ----------
+ */
+
+#ifndef _PG_LZCOMPRESS_H_
+#define _PG_LZCOMPRESS_H_
+
+
+/* ----------
+ * PGLZ_MAX_OUTPUT -
+ *
+ * Macro to compute the buffer size required by pglz_compress().
+ * We allow 4 bytes for overrun before detecting compression failure.
+ * ----------
+ */
+#define PGLZ_MAX_OUTPUT(_dlen) ((_dlen) + 4)
+
+
+/* ----------
+ * PGLZ_Strategy -
+ *
+ * Some values that control the compression algorithm.
+ *
+ * min_input_size Minimum input data size to consider compression.
+ *
+ * max_input_size Maximum input data size to consider compression.
+ *
+ * min_comp_rate Minimum compression rate (0-99%) to require.
+ * Regardless of min_comp_rate, the output must be
+ * smaller than the input, else we don't store
+ * compressed.
+ *
+ * first_success_by Abandon compression if we find no compressible
+ * data within the first this-many bytes.
+ *
+ * match_size_good The initial GOOD match size when starting history
+ * lookup. When looking up the history to find a
+ * match that could be expressed as a tag, the
+ * algorithm does not always walk back entirely.
+ * A good match fast is usually better than the
+ * best possible one very late. For each iteration
+ * in the lookup, this value is lowered so the
+ * longer the lookup takes, the smaller matches
+ * are considered good.
+ *
+ * match_size_drop The percentage by which match_size_good is lowered
+ * after each history check. Allowed values are
+ * 0 (no change until end) to 100 (only check
+ * latest history entry at all).
+ * ----------
+ */
+typedef struct PGLZ_Strategy
+{
+ int32 min_input_size;
+ int32 max_input_size;
+ int32 min_comp_rate;
+ int32 first_success_by;
+ int32 match_size_good;
+ int32 match_size_drop;
+} PGLZ_Strategy;
+
+
+/* ----------
+ * The standard strategies
+ *
+ * PGLZ_strategy_default Recommended default strategy for TOAST.
+ *
+ * PGLZ_strategy_always Try to compress inputs of any length.
+ * Fallback to uncompressed storage only if
+ * output would be larger than input.
+ * ----------
+ */
+extern PGDLLIMPORT const PGLZ_Strategy *const PGLZ_strategy_default;
+extern PGDLLIMPORT const PGLZ_Strategy *const PGLZ_strategy_always;
+
+
+/* ----------
+ * Global function declarations
+ * ----------
+ */
+extern int32 pglz_compress(const char *source, int32 slen, char *dest,
+ const PGLZ_Strategy *strategy);
+extern int32 pglz_decompress(const char *source, int32 slen, char *dest,
+ int32 rawsize, bool check_complete);
+extern int32 pglz_maximum_compressed_size(int32 rawsize,
+ int32 total_compressed_size);
+
+#endif /* _PG_LZCOMPRESS_H_ */
diff --git a/contrib/libs/libpq/src/include/common/pg_prng.h b/contrib/libs/libpq/src/include/common/pg_prng.h
new file mode 100644
index 0000000000..b5c0b8d288
--- /dev/null
+++ b/contrib/libs/libpq/src/include/common/pg_prng.h
@@ -0,0 +1,61 @@
+/*-------------------------------------------------------------------------
+ *
+ * Pseudo-Random Number Generator
+ *
+ * Copyright (c) 2021-2023, PostgreSQL Global Development Group
+ *
+ * src/include/common/pg_prng.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_PRNG_H
+#define PG_PRNG_H
+
+/*
+ * State vector for PRNG generation. Callers should treat this as an
+ * opaque typedef, but we expose its definition to allow it to be
+ * embedded in other structs.
+ */
+typedef struct pg_prng_state
+{
+ uint64 s0,
+ s1;
+} pg_prng_state;
+
+/*
+ * Callers not needing local PRNG series may use this global state vector,
+ * after initializing it with one of the pg_prng_...seed functions.
+ */
+extern PGDLLIMPORT pg_prng_state pg_global_prng_state;
+
+extern void pg_prng_seed(pg_prng_state *state, uint64 seed);
+extern void pg_prng_fseed(pg_prng_state *state, double fseed);
+extern bool pg_prng_seed_check(pg_prng_state *state);
+
+/*
+ * Initialize the PRNG state from the pg_strong_random source,
+ * taking care that we don't produce all-zeroes. If this returns false,
+ * caller should initialize the PRNG state from some other random seed,
+ * using pg_prng_[f]seed.
+ *
+ * We implement this as a macro, so that the pg_strong_random() call is
+ * in the caller. If it were in pg_prng.c, programs using pg_prng.c
+ * but not needing strong seeding would nonetheless be forced to pull in
+ * pg_strong_random.c and thence OpenSSL.
+ */
+#define pg_prng_strong_seed(state) \
+ (pg_strong_random((void *) (state), sizeof(pg_prng_state)) ? \
+ pg_prng_seed_check(state) : false)
+
+extern uint64 pg_prng_uint64(pg_prng_state *state);
+extern uint64 pg_prng_uint64_range(pg_prng_state *state, uint64 rmin, uint64 rmax);
+extern int64 pg_prng_int64(pg_prng_state *state);
+extern int64 pg_prng_int64p(pg_prng_state *state);
+extern uint32 pg_prng_uint32(pg_prng_state *state);
+extern int32 pg_prng_int32(pg_prng_state *state);
+extern int32 pg_prng_int32p(pg_prng_state *state);
+extern double pg_prng_double(pg_prng_state *state);
+extern double pg_prng_double_normal(pg_prng_state *state);
+extern bool pg_prng_bool(pg_prng_state *state);
+
+#endif /* PG_PRNG_H */
diff --git a/contrib/libs/libpq/src/include/common/relpath.h b/contrib/libs/libpq/src/include/common/relpath.h
new file mode 100644
index 0000000000..511c21682e
--- /dev/null
+++ b/contrib/libs/libpq/src/include/common/relpath.h
@@ -0,0 +1,97 @@
+/*-------------------------------------------------------------------------
+ *
+ * relpath.h
+ * Declarations for GetRelationPath() and friends
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/common/relpath.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef RELPATH_H
+#define RELPATH_H
+
+/*
+ * 'pgrminclude ignore' needed here because CppAsString2() does not throw
+ * an error if the symbol is not defined.
+ */
+#include "catalog/catversion.h" /* pgrminclude ignore */
+
+/*
+ * RelFileNumber data type identifies the specific relation file name.
+ */
+typedef Oid RelFileNumber;
+#define InvalidRelFileNumber ((RelFileNumber) InvalidOid)
+#define RelFileNumberIsValid(relnumber) \
+ ((bool) ((relnumber) != InvalidRelFileNumber))
+
+/*
+ * Name of major-version-specific tablespace subdirectories
+ */
+#define TABLESPACE_VERSION_DIRECTORY "PG_" PG_MAJORVERSION "_" \
+ CppAsString2(CATALOG_VERSION_NO)
+
+/* Characters to allow for an OID in a relation path */
+#define OIDCHARS 10 /* max chars printed by %u */
+
+/*
+ * Stuff for fork names.
+ *
+ * The physical storage of a relation consists of one or more forks.
+ * The main fork is always created, but in addition to that there can be
+ * additional forks for storing various metadata. ForkNumber is used when
+ * we need to refer to a specific fork in a relation.
+ */
+typedef enum ForkNumber
+{
+ InvalidForkNumber = -1,
+ MAIN_FORKNUM = 0,
+ FSM_FORKNUM,
+ VISIBILITYMAP_FORKNUM,
+ INIT_FORKNUM
+
+ /*
+ * NOTE: if you add a new fork, change MAX_FORKNUM and possibly
+ * FORKNAMECHARS below, and update the forkNames array in
+ * src/common/relpath.c
+ */
+} ForkNumber;
+
+#define MAX_FORKNUM INIT_FORKNUM
+
+#define FORKNAMECHARS 4 /* max chars for a fork name */
+
+extern PGDLLIMPORT const char *const forkNames[];
+
+extern ForkNumber forkname_to_number(const char *forkName);
+extern int forkname_chars(const char *str, ForkNumber *fork);
+
+/*
+ * Stuff for computing filesystem pathnames for relations.
+ */
+extern char *GetDatabasePath(Oid dbOid, Oid spcOid);
+
+extern char *GetRelationPath(Oid dbOid, Oid spcOid, RelFileNumber relNumber,
+ int backendId, ForkNumber forkNumber);
+
+/*
+ * Wrapper macros for GetRelationPath. Beware of multiple
+ * evaluation of the RelFileLocator or RelFileLocatorBackend argument!
+ */
+
+/* First argument is a RelFileLocator */
+#define relpathbackend(rlocator, backend, forknum) \
+ GetRelationPath((rlocator).dbOid, (rlocator).spcOid, (rlocator).relNumber, \
+ backend, forknum)
+
+/* First argument is a RelFileLocator */
+#define relpathperm(rlocator, forknum) \
+ relpathbackend(rlocator, InvalidBackendId, forknum)
+
+/* First argument is a RelFileLocatorBackend */
+#define relpath(rlocator, forknum) \
+ relpathbackend((rlocator).locator, (rlocator).backend, forknum)
+
+#endif /* RELPATH_H */
diff --git a/contrib/libs/libpq/src/include/common/restricted_token.h b/contrib/libs/libpq/src/include/common/restricted_token.h
new file mode 100644
index 0000000000..d4077c7661
--- /dev/null
+++ b/contrib/libs/libpq/src/include/common/restricted_token.h
@@ -0,0 +1,24 @@
+/*
+ * restricted_token.h
+ * helper routine to ensure restricted token on Windows
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/common/restricted_token.h
+ */
+#ifndef COMMON_RESTRICTED_TOKEN_H
+#define COMMON_RESTRICTED_TOKEN_H
+
+/*
+ * On Windows make sure that we are running with a restricted token,
+ * On other platforms do nothing.
+ */
+void get_restricted_token(void);
+
+#ifdef WIN32
+/* Create a restricted token and execute the specified process with it. */
+HANDLE CreateRestrictedProcess(char *cmd, PROCESS_INFORMATION *processInfo);
+#endif
+
+#endif /* COMMON_RESTRICTED_TOKEN_H */
diff --git a/contrib/libs/libpq/src/include/common/saslprep.h b/contrib/libs/libpq/src/include/common/saslprep.h
new file mode 100644
index 0000000000..f622db962f
--- /dev/null
+++ b/contrib/libs/libpq/src/include/common/saslprep.h
@@ -0,0 +1,30 @@
+/*-------------------------------------------------------------------------
+ *
+ * saslprep.h
+ * SASLprep normalization, for SCRAM authentication
+ *
+ * These definitions are used by both frontend and backend code.
+ *
+ * Copyright (c) 2017-2023, PostgreSQL Global Development Group
+ *
+ * src/include/common/saslprep.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SASLPREP_H
+#define SASLPREP_H
+
+/*
+ * Return codes for pg_saslprep() function.
+ */
+typedef enum
+{
+ SASLPREP_SUCCESS = 0,
+ SASLPREP_OOM = -1, /* out of memory (only in frontend) */
+ SASLPREP_INVALID_UTF8 = -2, /* input is not a valid UTF-8 string */
+ SASLPREP_PROHIBITED = -3 /* output would contain prohibited characters */
+} pg_saslprep_rc;
+
+extern pg_saslprep_rc pg_saslprep(const char *input, char **output);
+
+#endif /* SASLPREP_H */
diff --git a/contrib/libs/libpq/src/include/common/scram-common.h b/contrib/libs/libpq/src/include/common/scram-common.h
new file mode 100644
index 0000000000..5ccff96ece
--- /dev/null
+++ b/contrib/libs/libpq/src/include/common/scram-common.h
@@ -0,0 +1,70 @@
+/*-------------------------------------------------------------------------
+ *
+ * scram-common.h
+ * Declarations for helper functions used for SCRAM authentication
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/common/scram-common.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SCRAM_COMMON_H
+#define SCRAM_COMMON_H
+
+#include "common/cryptohash.h"
+#include "common/sha2.h"
+
+/* Name of SCRAM mechanisms per IANA */
+#define SCRAM_SHA_256_NAME "SCRAM-SHA-256"
+#define SCRAM_SHA_256_PLUS_NAME "SCRAM-SHA-256-PLUS" /* with channel binding */
+
+/* Length of SCRAM keys (client and server) */
+#define SCRAM_SHA_256_KEY_LEN PG_SHA256_DIGEST_LENGTH
+
+/*
+ * Size of buffers used internally by SCRAM routines, that should be the
+ * maximum of SCRAM_SHA_*_KEY_LEN among the hash methods supported.
+ */
+#define SCRAM_MAX_KEY_LEN SCRAM_SHA_256_KEY_LEN
+
+/*
+ * Size of random nonce generated in the authentication exchange. This
+ * is in "raw" number of bytes, the actual nonces sent over the wire are
+ * encoded using only ASCII-printable characters.
+ */
+#define SCRAM_RAW_NONCE_LEN 18
+
+/*
+ * Length of salt when generating new secrets, in bytes. (It will be stored
+ * and sent over the wire encoded in Base64.) 16 bytes is what the example in
+ * RFC 7677 uses.
+ */
+#define SCRAM_DEFAULT_SALT_LEN 16
+
+/*
+ * Default number of iterations when generating secret. Should be at least
+ * 4096 per RFC 7677.
+ */
+#define SCRAM_SHA_256_DEFAULT_ITERATIONS 4096
+
+extern int scram_SaltedPassword(const char *password,
+ pg_cryptohash_type hash_type, int key_length,
+ const char *salt, int saltlen, int iterations,
+ uint8 *result, const char **errstr);
+extern int scram_H(const uint8 *input, pg_cryptohash_type hash_type,
+ int key_length, uint8 *result,
+ const char **errstr);
+extern int scram_ClientKey(const uint8 *salted_password,
+ pg_cryptohash_type hash_type, int key_length,
+ uint8 *result, const char **errstr);
+extern int scram_ServerKey(const uint8 *salted_password,
+ pg_cryptohash_type hash_type, int key_length,
+ uint8 *result, const char **errstr);
+
+extern char *scram_build_secret(pg_cryptohash_type hash_type, int key_length,
+ const char *salt, int saltlen, int iterations,
+ const char *password, const char **errstr);
+
+#endif /* SCRAM_COMMON_H */
diff --git a/contrib/libs/libpq/src/include/common/sha1.h b/contrib/libs/libpq/src/include/common/sha1.h
new file mode 100644
index 0000000000..e6933d96bb
--- /dev/null
+++ b/contrib/libs/libpq/src/include/common/sha1.h
@@ -0,0 +1,21 @@
+/*-------------------------------------------------------------------------
+ *
+ * sha1.h
+ * Constants related to SHA1.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/common/sha1.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_SHA1_H
+#define PG_SHA1_H
+
+/* Size of result generated by SHA1 computation */
+#define SHA1_DIGEST_LENGTH 20
+/* Block size for SHA1 */
+#define SHA1_BLOCK_SIZE 64
+
+#endif /* PG_SHA1_H */
diff --git a/contrib/libs/libpq/src/include/common/sha2.h b/contrib/libs/libpq/src/include/common/sha2.h
new file mode 100644
index 0000000000..9b46cd1a37
--- /dev/null
+++ b/contrib/libs/libpq/src/include/common/sha2.h
@@ -0,0 +1,32 @@
+/*-------------------------------------------------------------------------
+ *
+ * sha2.h
+ * Constants related to SHA224, 256, 384 AND 512.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/include/common/sha2.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef _PG_SHA2_H_
+#define _PG_SHA2_H_
+
+/*** SHA224/256/384/512 Various Length Definitions ***********************/
+#define PG_SHA224_BLOCK_LENGTH 64
+#define PG_SHA224_DIGEST_LENGTH 28
+#define PG_SHA224_DIGEST_STRING_LENGTH (PG_SHA224_DIGEST_LENGTH * 2 + 1)
+#define PG_SHA256_BLOCK_LENGTH 64
+#define PG_SHA256_DIGEST_LENGTH 32
+#define PG_SHA256_DIGEST_STRING_LENGTH (PG_SHA256_DIGEST_LENGTH * 2 + 1)
+#define PG_SHA384_BLOCK_LENGTH 128
+#define PG_SHA384_DIGEST_LENGTH 48
+#define PG_SHA384_DIGEST_STRING_LENGTH (PG_SHA384_DIGEST_LENGTH * 2 + 1)
+#define PG_SHA512_BLOCK_LENGTH 128
+#define PG_SHA512_DIGEST_LENGTH 64
+#define PG_SHA512_DIGEST_STRING_LENGTH (PG_SHA512_DIGEST_LENGTH * 2 + 1)
+
+#endif /* _PG_SHA2_H_ */
diff --git a/contrib/libs/libpq/src/include/common/shortest_dec.h b/contrib/libs/libpq/src/include/common/shortest_dec.h
new file mode 100644
index 0000000000..8479b98575
--- /dev/null
+++ b/contrib/libs/libpq/src/include/common/shortest_dec.h
@@ -0,0 +1,63 @@
+/*---------------------------------------------------------------------------
+ *
+ * Ryu floating-point output.
+ *
+ * Portions Copyright (c) 2018-2023, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/include/common/shortest_dec.h
+ *
+ * This is a modification of code taken from github.com/ulfjack/ryu under the
+ * terms of the Boost license (not the Apache license). The original copyright
+ * notice follows:
+ *
+ * Copyright 2018 Ulf Adams
+ *
+ * The contents of this file may be used under the terms of the Apache
+ * License, Version 2.0.
+ *
+ * (See accompanying file LICENSE-Apache or copy at
+ * http://www.apache.org/licenses/LICENSE-2.0)
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * Boost Software License, Version 1.0.
+ *
+ * (See accompanying file LICENSE-Boost or copy at
+ * https://www.boost.org/LICENSE_1_0.txt)
+ *
+ * Unless required by applicable law or agreed to in writing, this software is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.
+ *
+ *---------------------------------------------------------------------------
+ */
+#ifndef SHORTEST_DEC_H
+#define SHORTEST_DEC_H
+
+/*----
+ * The length of 25 comes from:
+ *
+ * Case 1: -9.9999999999999999e-299 = 24 bytes, plus 1 for null
+ *
+ * Case 2: -0.00099999999999999999 = 23 bytes, plus 1 for null
+ */
+#define DOUBLE_SHORTEST_DECIMAL_LEN 25
+
+int double_to_shortest_decimal_bufn(double f, char *result);
+int double_to_shortest_decimal_buf(double f, char *result);
+char *double_to_shortest_decimal(double f);
+
+/*
+ * The length of 16 comes from:
+ *
+ * Case 1: -9.99999999e+29 = 15 bytes, plus 1 for null
+ *
+ * Case 2: -0.000999999999 = 15 bytes, plus 1 for null
+ */
+#define FLOAT_SHORTEST_DECIMAL_LEN 16
+
+int float_to_shortest_decimal_bufn(float f, char *result);
+int float_to_shortest_decimal_buf(float f, char *result);
+char *float_to_shortest_decimal(float f);
+
+#endif /* SHORTEST_DEC_H */
diff --git a/contrib/libs/libpq/src/include/common/string.h b/contrib/libs/libpq/src/include/common/string.h
new file mode 100644
index 0000000000..977ef327d0
--- /dev/null
+++ b/contrib/libs/libpq/src/include/common/string.h
@@ -0,0 +1,44 @@
+/*
+ * string.h
+ * string handling helpers
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/common/string.h
+ */
+#ifndef COMMON_STRING_H
+#define COMMON_STRING_H
+
+#include <signal.h>
+
+struct StringInfoData; /* avoid including stringinfo.h here */
+
+typedef struct PromptInterruptContext
+{
+ /* To avoid including <setjmp.h> here, jmpbuf is declared "void *" */
+ void *jmpbuf; /* existing longjmp buffer */
+ volatile sig_atomic_t *enabled; /* flag that enables longjmp-on-interrupt */
+ bool canceled; /* indicates whether cancellation occurred */
+} PromptInterruptContext;
+
+/* functions in src/common/string.c */
+extern bool pg_str_endswith(const char *str, const char *end);
+extern int strtoint(const char *pg_restrict str, char **pg_restrict endptr,
+ int base);
+extern char *pg_clean_ascii(const char *str, int alloc_flags);
+extern int pg_strip_crlf(char *str);
+extern bool pg_is_ascii(const char *str);
+
+/* functions in src/common/pg_get_line.c */
+extern char *pg_get_line(FILE *stream, PromptInterruptContext *prompt_ctx);
+extern bool pg_get_line_buf(FILE *stream, struct StringInfoData *buf);
+extern bool pg_get_line_append(FILE *stream, struct StringInfoData *buf,
+ PromptInterruptContext *prompt_ctx);
+
+/* functions in src/common/sprompt.c */
+extern char *simple_prompt(const char *prompt, bool echo);
+extern char *simple_prompt_extended(const char *prompt, bool echo,
+ PromptInterruptContext *prompt_ctx);
+
+#endif /* COMMON_STRING_H */
diff --git a/contrib/libs/libpq/src/include/common/unicode_east_asian_fw_table.h b/contrib/libs/libpq/src/include/common/unicode_east_asian_fw_table.h
new file mode 100644
index 0000000000..f77e6dfd42
--- /dev/null
+++ b/contrib/libs/libpq/src/include/common/unicode_east_asian_fw_table.h
@@ -0,0 +1,125 @@
+/* generated by src/common/unicode/generate-unicode_east_asian_fw_table.pl, do not edit */
+
+static const struct mbinterval east_asian_fw[] = {
+ {0x1100, 0x115F},
+ {0x231A, 0x231B},
+ {0x2329, 0x232A},
+ {0x23E9, 0x23EC},
+ {0x23F0, 0x23F0},
+ {0x23F3, 0x23F3},
+ {0x25FD, 0x25FE},
+ {0x2614, 0x2615},
+ {0x2648, 0x2653},
+ {0x267F, 0x267F},
+ {0x2693, 0x2693},
+ {0x26A1, 0x26A1},
+ {0x26AA, 0x26AB},
+ {0x26BD, 0x26BE},
+ {0x26C4, 0x26C5},
+ {0x26CE, 0x26CE},
+ {0x26D4, 0x26D4},
+ {0x26EA, 0x26EA},
+ {0x26F2, 0x26F3},
+ {0x26F5, 0x26F5},
+ {0x26FA, 0x26FA},
+ {0x26FD, 0x26FD},
+ {0x2705, 0x2705},
+ {0x270A, 0x270B},
+ {0x2728, 0x2728},
+ {0x274C, 0x274C},
+ {0x274E, 0x274E},
+ {0x2753, 0x2755},
+ {0x2757, 0x2757},
+ {0x2795, 0x2797},
+ {0x27B0, 0x27B0},
+ {0x27BF, 0x27BF},
+ {0x2B1B, 0x2B1C},
+ {0x2B50, 0x2B50},
+ {0x2B55, 0x2B55},
+ {0x2E80, 0x2E99},
+ {0x2E9B, 0x2EF3},
+ {0x2F00, 0x2FD5},
+ {0x2FF0, 0x2FFB},
+ {0x3000, 0x303E},
+ {0x3041, 0x3096},
+ {0x3099, 0x30FF},
+ {0x3105, 0x312F},
+ {0x3131, 0x318E},
+ {0x3190, 0x31E3},
+ {0x31F0, 0x321E},
+ {0x3220, 0x3247},
+ {0x3250, 0x4DBF},
+ {0x4E00, 0xA48C},
+ {0xA490, 0xA4C6},
+ {0xA960, 0xA97C},
+ {0xAC00, 0xD7A3},
+ {0xF900, 0xFAFF},
+ {0xFE10, 0xFE19},
+ {0xFE30, 0xFE52},
+ {0xFE54, 0xFE66},
+ {0xFE68, 0xFE6B},
+ {0xFF01, 0xFF60},
+ {0xFFE0, 0xFFE6},
+ {0x16FE0, 0x16FE4},
+ {0x16FF0, 0x16FF1},
+ {0x17000, 0x187F7},
+ {0x18800, 0x18CD5},
+ {0x18D00, 0x18D08},
+ {0x1AFF0, 0x1AFF3},
+ {0x1AFF5, 0x1AFFB},
+ {0x1AFFD, 0x1AFFE},
+ {0x1B000, 0x1B122},
+ {0x1B132, 0x1B132},
+ {0x1B150, 0x1B152},
+ {0x1B155, 0x1B155},
+ {0x1B164, 0x1B167},
+ {0x1B170, 0x1B2FB},
+ {0x1F004, 0x1F004},
+ {0x1F0CF, 0x1F0CF},
+ {0x1F18E, 0x1F18E},
+ {0x1F191, 0x1F19A},
+ {0x1F200, 0x1F202},
+ {0x1F210, 0x1F23B},
+ {0x1F240, 0x1F248},
+ {0x1F250, 0x1F251},
+ {0x1F260, 0x1F265},
+ {0x1F300, 0x1F320},
+ {0x1F32D, 0x1F335},
+ {0x1F337, 0x1F37C},
+ {0x1F37E, 0x1F393},
+ {0x1F3A0, 0x1F3CA},
+ {0x1F3CF, 0x1F3D3},
+ {0x1F3E0, 0x1F3F0},
+ {0x1F3F4, 0x1F3F4},
+ {0x1F3F8, 0x1F43E},
+ {0x1F440, 0x1F440},
+ {0x1F442, 0x1F4FC},
+ {0x1F4FF, 0x1F53D},
+ {0x1F54B, 0x1F54E},
+ {0x1F550, 0x1F567},
+ {0x1F57A, 0x1F57A},
+ {0x1F595, 0x1F596},
+ {0x1F5A4, 0x1F5A4},
+ {0x1F5FB, 0x1F64F},
+ {0x1F680, 0x1F6C5},
+ {0x1F6CC, 0x1F6CC},
+ {0x1F6D0, 0x1F6D2},
+ {0x1F6D5, 0x1F6D7},
+ {0x1F6DC, 0x1F6DF},
+ {0x1F6EB, 0x1F6EC},
+ {0x1F6F4, 0x1F6FC},
+ {0x1F7E0, 0x1F7EB},
+ {0x1F7F0, 0x1F7F0},
+ {0x1F90C, 0x1F93A},
+ {0x1F93C, 0x1F945},
+ {0x1F947, 0x1F9FF},
+ {0x1FA70, 0x1FA7C},
+ {0x1FA80, 0x1FA88},
+ {0x1FA90, 0x1FABD},
+ {0x1FABF, 0x1FAC5},
+ {0x1FACE, 0x1FADB},
+ {0x1FAE0, 0x1FAE8},
+ {0x1FAF0, 0x1FAF8},
+ {0x20000, 0x2FFFD},
+ {0x30000, 0x3FFFD},
+};
diff --git a/contrib/libs/libpq/src/include/common/unicode_nonspacing_table.h b/contrib/libs/libpq/src/include/common/unicode_nonspacing_table.h
new file mode 100644
index 0000000000..8d00e127fc
--- /dev/null
+++ b/contrib/libs/libpq/src/include/common/unicode_nonspacing_table.h
@@ -0,0 +1,326 @@
+/* generated by src/common/unicode/generate-unicode_nonspacing_table.pl, do not edit */
+
+static const struct mbinterval nonspacing[] = {
+ {0x00AD, 0x00AD},
+ {0x0300, 0x036F},
+ {0x0483, 0x0489},
+ {0x0591, 0x05BD},
+ {0x05BF, 0x05BF},
+ {0x05C1, 0x05C2},
+ {0x05C4, 0x05C5},
+ {0x05C7, 0x05C7},
+ {0x0600, 0x0605},
+ {0x0610, 0x061A},
+ {0x061C, 0x061C},
+ {0x064B, 0x065F},
+ {0x0670, 0x0670},
+ {0x06D6, 0x06DD},
+ {0x06DF, 0x06E4},
+ {0x06E7, 0x06E8},
+ {0x06EA, 0x06ED},
+ {0x070F, 0x070F},
+ {0x0711, 0x0711},
+ {0x0730, 0x074A},
+ {0x07A6, 0x07B0},
+ {0x07EB, 0x07F3},
+ {0x07FD, 0x07FD},
+ {0x0816, 0x0819},
+ {0x081B, 0x0823},
+ {0x0825, 0x0827},
+ {0x0829, 0x082D},
+ {0x0859, 0x085B},
+ {0x0890, 0x089F},
+ {0x08CA, 0x0902},
+ {0x093A, 0x093A},
+ {0x093C, 0x093C},
+ {0x0941, 0x0948},
+ {0x094D, 0x094D},
+ {0x0951, 0x0957},
+ {0x0962, 0x0963},
+ {0x0981, 0x0981},
+ {0x09BC, 0x09BC},
+ {0x09C1, 0x09C4},
+ {0x09CD, 0x09CD},
+ {0x09E2, 0x09E3},
+ {0x09FE, 0x0A02},
+ {0x0A3C, 0x0A3C},
+ {0x0A41, 0x0A51},
+ {0x0A70, 0x0A71},
+ {0x0A75, 0x0A75},
+ {0x0A81, 0x0A82},
+ {0x0ABC, 0x0ABC},
+ {0x0AC1, 0x0AC8},
+ {0x0ACD, 0x0ACD},
+ {0x0AE2, 0x0AE3},
+ {0x0AFA, 0x0B01},
+ {0x0B3C, 0x0B3C},
+ {0x0B3F, 0x0B3F},
+ {0x0B41, 0x0B44},
+ {0x0B4D, 0x0B56},
+ {0x0B62, 0x0B63},
+ {0x0B82, 0x0B82},
+ {0x0BC0, 0x0BC0},
+ {0x0BCD, 0x0BCD},
+ {0x0C00, 0x0C00},
+ {0x0C04, 0x0C04},
+ {0x0C3C, 0x0C3C},
+ {0x0C3E, 0x0C40},
+ {0x0C46, 0x0C56},
+ {0x0C62, 0x0C63},
+ {0x0C81, 0x0C81},
+ {0x0CBC, 0x0CBC},
+ {0x0CBF, 0x0CBF},
+ {0x0CC6, 0x0CC6},
+ {0x0CCC, 0x0CCD},
+ {0x0CE2, 0x0CE3},
+ {0x0D00, 0x0D01},
+ {0x0D3B, 0x0D3C},
+ {0x0D41, 0x0D44},
+ {0x0D4D, 0x0D4D},
+ {0x0D62, 0x0D63},
+ {0x0D81, 0x0D81},
+ {0x0DCA, 0x0DCA},
+ {0x0DD2, 0x0DD6},
+ {0x0E31, 0x0E31},
+ {0x0E34, 0x0E3A},
+ {0x0E47, 0x0E4E},
+ {0x0EB1, 0x0EB1},
+ {0x0EB4, 0x0EBC},
+ {0x0EC8, 0x0ECE},
+ {0x0F18, 0x0F19},
+ {0x0F35, 0x0F35},
+ {0x0F37, 0x0F37},
+ {0x0F39, 0x0F39},
+ {0x0F71, 0x0F7E},
+ {0x0F80, 0x0F84},
+ {0x0F86, 0x0F87},
+ {0x0F8D, 0x0FBC},
+ {0x0FC6, 0x0FC6},
+ {0x102D, 0x1030},
+ {0x1032, 0x1037},
+ {0x1039, 0x103A},
+ {0x103D, 0x103E},
+ {0x1058, 0x1059},
+ {0x105E, 0x1060},
+ {0x1071, 0x1074},
+ {0x1082, 0x1082},
+ {0x1085, 0x1086},
+ {0x108D, 0x108D},
+ {0x109D, 0x109D},
+ {0x135D, 0x135F},
+ {0x1712, 0x1714},
+ {0x1732, 0x1733},
+ {0x1752, 0x1753},
+ {0x1772, 0x1773},
+ {0x17B4, 0x17B5},
+ {0x17B7, 0x17BD},
+ {0x17C6, 0x17C6},
+ {0x17C9, 0x17D3},
+ {0x17DD, 0x17DD},
+ {0x180B, 0x180F},
+ {0x1885, 0x1886},
+ {0x18A9, 0x18A9},
+ {0x1920, 0x1922},
+ {0x1927, 0x1928},
+ {0x1932, 0x1932},
+ {0x1939, 0x193B},
+ {0x1A17, 0x1A18},
+ {0x1A1B, 0x1A1B},
+ {0x1A56, 0x1A56},
+ {0x1A58, 0x1A60},
+ {0x1A62, 0x1A62},
+ {0x1A65, 0x1A6C},
+ {0x1A73, 0x1A7F},
+ {0x1AB0, 0x1B03},
+ {0x1B34, 0x1B34},
+ {0x1B36, 0x1B3A},
+ {0x1B3C, 0x1B3C},
+ {0x1B42, 0x1B42},
+ {0x1B6B, 0x1B73},
+ {0x1B80, 0x1B81},
+ {0x1BA2, 0x1BA5},
+ {0x1BA8, 0x1BA9},
+ {0x1BAB, 0x1BAD},
+ {0x1BE6, 0x1BE6},
+ {0x1BE8, 0x1BE9},
+ {0x1BED, 0x1BED},
+ {0x1BEF, 0x1BF1},
+ {0x1C2C, 0x1C33},
+ {0x1C36, 0x1C37},
+ {0x1CD0, 0x1CD2},
+ {0x1CD4, 0x1CE0},
+ {0x1CE2, 0x1CE8},
+ {0x1CED, 0x1CED},
+ {0x1CF4, 0x1CF4},
+ {0x1CF8, 0x1CF9},
+ {0x1DC0, 0x1DFF},
+ {0x200B, 0x200F},
+ {0x202A, 0x202E},
+ {0x2060, 0x206F},
+ {0x20D0, 0x20F0},
+ {0x2CEF, 0x2CF1},
+ {0x2D7F, 0x2D7F},
+ {0x2DE0, 0x2DFF},
+ {0x302A, 0x302D},
+ {0x3099, 0x309A},
+ {0xA66F, 0xA672},
+ {0xA674, 0xA67D},
+ {0xA69E, 0xA69F},
+ {0xA6F0, 0xA6F1},
+ {0xA802, 0xA802},
+ {0xA806, 0xA806},
+ {0xA80B, 0xA80B},
+ {0xA825, 0xA826},
+ {0xA82C, 0xA82C},
+ {0xA8C4, 0xA8C5},
+ {0xA8E0, 0xA8F1},
+ {0xA8FF, 0xA8FF},
+ {0xA926, 0xA92D},
+ {0xA947, 0xA951},
+ {0xA980, 0xA982},
+ {0xA9B3, 0xA9B3},
+ {0xA9B6, 0xA9B9},
+ {0xA9BC, 0xA9BD},
+ {0xA9E5, 0xA9E5},
+ {0xAA29, 0xAA2E},
+ {0xAA31, 0xAA32},
+ {0xAA35, 0xAA36},
+ {0xAA43, 0xAA43},
+ {0xAA4C, 0xAA4C},
+ {0xAA7C, 0xAA7C},
+ {0xAAB0, 0xAAB0},
+ {0xAAB2, 0xAAB4},
+ {0xAAB7, 0xAAB8},
+ {0xAABE, 0xAABF},
+ {0xAAC1, 0xAAC1},
+ {0xAAEC, 0xAAED},
+ {0xAAF6, 0xAAF6},
+ {0xABE5, 0xABE5},
+ {0xABE8, 0xABE8},
+ {0xABED, 0xABED},
+ {0xFB1E, 0xFB1E},
+ {0xFE00, 0xFE0F},
+ {0xFE20, 0xFE2F},
+ {0xFEFF, 0xFEFF},
+ {0xFFF9, 0xFFFB},
+ {0x101FD, 0x101FD},
+ {0x102E0, 0x102E0},
+ {0x10376, 0x1037A},
+ {0x10A01, 0x10A0F},
+ {0x10A38, 0x10A3F},
+ {0x10AE5, 0x10AE6},
+ {0x10D24, 0x10D27},
+ {0x10EAB, 0x10EAC},
+ {0x10EFD, 0x10EFF},
+ {0x10F46, 0x10F50},
+ {0x10F82, 0x10F85},
+ {0x11001, 0x11001},
+ {0x11038, 0x11046},
+ {0x11070, 0x11070},
+ {0x11073, 0x11074},
+ {0x1107F, 0x11081},
+ {0x110B3, 0x110B6},
+ {0x110B9, 0x110BA},
+ {0x110BD, 0x110BD},
+ {0x110C2, 0x110CD},
+ {0x11100, 0x11102},
+ {0x11127, 0x1112B},
+ {0x1112D, 0x11134},
+ {0x11173, 0x11173},
+ {0x11180, 0x11181},
+ {0x111B6, 0x111BE},
+ {0x111C9, 0x111CC},
+ {0x111CF, 0x111CF},
+ {0x1122F, 0x11231},
+ {0x11234, 0x11234},
+ {0x11236, 0x11237},
+ {0x1123E, 0x1123E},
+ {0x11241, 0x11241},
+ {0x112DF, 0x112DF},
+ {0x112E3, 0x112EA},
+ {0x11300, 0x11301},
+ {0x1133B, 0x1133C},
+ {0x11340, 0x11340},
+ {0x11366, 0x11374},
+ {0x11438, 0x1143F},
+ {0x11442, 0x11444},
+ {0x11446, 0x11446},
+ {0x1145E, 0x1145E},
+ {0x114B3, 0x114B8},
+ {0x114BA, 0x114BA},
+ {0x114BF, 0x114C0},
+ {0x114C2, 0x114C3},
+ {0x115B2, 0x115B5},
+ {0x115BC, 0x115BD},
+ {0x115BF, 0x115C0},
+ {0x115DC, 0x115DD},
+ {0x11633, 0x1163A},
+ {0x1163D, 0x1163D},
+ {0x1163F, 0x11640},
+ {0x116AB, 0x116AB},
+ {0x116AD, 0x116AD},
+ {0x116B0, 0x116B5},
+ {0x116B7, 0x116B7},
+ {0x1171D, 0x1171F},
+ {0x11722, 0x11725},
+ {0x11727, 0x1172B},
+ {0x1182F, 0x11837},
+ {0x11839, 0x1183A},
+ {0x1193B, 0x1193C},
+ {0x1193E, 0x1193E},
+ {0x11943, 0x11943},
+ {0x119D4, 0x119DB},
+ {0x119E0, 0x119E0},
+ {0x11A01, 0x11A0A},
+ {0x11A33, 0x11A38},
+ {0x11A3B, 0x11A3E},
+ {0x11A47, 0x11A47},
+ {0x11A51, 0x11A56},
+ {0x11A59, 0x11A5B},
+ {0x11A8A, 0x11A96},
+ {0x11A98, 0x11A99},
+ {0x11C30, 0x11C3D},
+ {0x11C3F, 0x11C3F},
+ {0x11C92, 0x11CA7},
+ {0x11CAA, 0x11CB0},
+ {0x11CB2, 0x11CB3},
+ {0x11CB5, 0x11CB6},
+ {0x11D31, 0x11D45},
+ {0x11D47, 0x11D47},
+ {0x11D90, 0x11D91},
+ {0x11D95, 0x11D95},
+ {0x11D97, 0x11D97},
+ {0x11EF3, 0x11EF4},
+ {0x11F00, 0x11F01},
+ {0x11F36, 0x11F3A},
+ {0x11F40, 0x11F40},
+ {0x11F42, 0x11F42},
+ {0x13430, 0x13440},
+ {0x13447, 0x13455},
+ {0x16AF0, 0x16AF4},
+ {0x16B30, 0x16B36},
+ {0x16F4F, 0x16F4F},
+ {0x16F8F, 0x16F92},
+ {0x16FE4, 0x16FE4},
+ {0x1BC9D, 0x1BC9E},
+ {0x1BCA0, 0x1CF46},
+ {0x1D167, 0x1D169},
+ {0x1D173, 0x1D182},
+ {0x1D185, 0x1D18B},
+ {0x1D1AA, 0x1D1AD},
+ {0x1D242, 0x1D244},
+ {0x1DA00, 0x1DA36},
+ {0x1DA3B, 0x1DA6C},
+ {0x1DA75, 0x1DA75},
+ {0x1DA84, 0x1DA84},
+ {0x1DA9B, 0x1DAAF},
+ {0x1E000, 0x1E02A},
+ {0x1E08F, 0x1E08F},
+ {0x1E130, 0x1E136},
+ {0x1E2AE, 0x1E2AE},
+ {0x1E2EC, 0x1E2EF},
+ {0x1E4EC, 0x1E4EF},
+ {0x1E8D0, 0x1E8D6},
+ {0x1E944, 0x1E94A},
+ {0xE0001, 0xE01EF},
+};
diff --git a/contrib/libs/libpq/src/include/common/unicode_norm.h b/contrib/libs/libpq/src/include/common/unicode_norm.h
new file mode 100644
index 0000000000..c6627aeb7c
--- /dev/null
+++ b/contrib/libs/libpq/src/include/common/unicode_norm.h
@@ -0,0 +1,39 @@
+/*-------------------------------------------------------------------------
+ *
+ * unicode_norm.h
+ * Routines for normalizing Unicode strings
+ *
+ * These definitions are used by both frontend and backend code.
+ *
+ * Copyright (c) 2017-2023, PostgreSQL Global Development Group
+ *
+ * src/include/common/unicode_norm.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef UNICODE_NORM_H
+#define UNICODE_NORM_H
+
+#include "mb/pg_wchar.h"
+
+typedef enum
+{
+ UNICODE_NFC = 0,
+ UNICODE_NFD = 1,
+ UNICODE_NFKC = 2,
+ UNICODE_NFKD = 3,
+} UnicodeNormalizationForm;
+
+/* see UAX #15 */
+typedef enum
+{
+ UNICODE_NORM_QC_NO = 0,
+ UNICODE_NORM_QC_YES = 1,
+ UNICODE_NORM_QC_MAYBE = -1,
+} UnicodeNormalizationQC;
+
+extern pg_wchar *unicode_normalize(UnicodeNormalizationForm form, const pg_wchar *input);
+
+extern UnicodeNormalizationQC unicode_is_normalized_quickcheck(UnicodeNormalizationForm form, const pg_wchar *input);
+
+#endif /* UNICODE_NORM_H */
diff --git a/contrib/libs/libpq/src/include/common/unicode_norm_table.h b/contrib/libs/libpq/src/include/common/unicode_norm_table.h
new file mode 100644
index 0000000000..36b6ca4044
--- /dev/null
+++ b/contrib/libs/libpq/src/include/common/unicode_norm_table.h
@@ -0,0 +1,9114 @@
+/*-------------------------------------------------------------------------
+ *
+ * unicode_norm_table.h
+ * Composition table used for Unicode normalization
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/common/unicode_norm_table.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/*
+ * File auto-generated by src/common/unicode/generate-unicode_norm_table.pl,
+ * do not edit. There is deliberately not an #ifndef PG_UNICODE_NORM_TABLE_H
+ * here.
+ */
+typedef struct
+{
+ uint32 codepoint; /* Unicode codepoint */
+ uint8 comb_class; /* combining class of character */
+ uint8 dec_size_flags; /* size and flags of decomposition code list */
+ uint16 dec_index; /* index into UnicodeDecomp_codepoints, or the
+ * decomposition itself if DECOMP_INLINE */
+} pg_unicode_decomposition;
+
+#define DECOMP_NO_COMPOSE 0x80 /* don't use for re-composition */
+#define DECOMP_INLINE 0x40 /* decomposition is stored inline in
+ * dec_index */
+#define DECOMP_COMPAT 0x20 /* compatibility mapping */
+
+#define DECOMPOSITION_SIZE(x) ((x)->dec_size_flags & 0x1F)
+#define DECOMPOSITION_NO_COMPOSE(x) (((x)->dec_size_flags & (DECOMP_NO_COMPOSE | DECOMP_COMPAT)) != 0)
+#define DECOMPOSITION_IS_INLINE(x) (((x)->dec_size_flags & DECOMP_INLINE) != 0)
+#define DECOMPOSITION_IS_COMPAT(x) (((x)->dec_size_flags & DECOMP_COMPAT) != 0)
+
+/* Table of Unicode codepoints and their decompositions */
+static const pg_unicode_decomposition UnicodeDecompMain[6775] =
+{
+ {0x00A0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0020},
+ {0x00A8, 0, 2 | DECOMP_COMPAT, 0},
+ {0x00AA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0061},
+ {0x00AF, 0, 2 | DECOMP_COMPAT, 2},
+ {0x00B2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0032},
+ {0x00B3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0033},
+ {0x00B4, 0, 2 | DECOMP_COMPAT, 4},
+ {0x00B5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BC},
+ {0x00B8, 0, 2 | DECOMP_COMPAT, 6},
+ {0x00B9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0031},
+ {0x00BA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006F},
+ {0x00BC, 0, 3 | DECOMP_COMPAT, 8},
+ {0x00BD, 0, 3 | DECOMP_COMPAT, 11},
+ {0x00BE, 0, 3 | DECOMP_COMPAT, 14},
+ {0x00C0, 0, 2, 17},
+ {0x00C1, 0, 2, 19},
+ {0x00C2, 0, 2, 21},
+ {0x00C3, 0, 2, 23},
+ {0x00C4, 0, 2, 25},
+ {0x00C5, 0, 2, 27},
+ {0x00C7, 0, 2, 29},
+ {0x00C8, 0, 2, 31},
+ {0x00C9, 0, 2, 33},
+ {0x00CA, 0, 2, 35},
+ {0x00CB, 0, 2, 37},
+ {0x00CC, 0, 2, 39},
+ {0x00CD, 0, 2, 41},
+ {0x00CE, 0, 2, 43},
+ {0x00CF, 0, 2, 45},
+ {0x00D1, 0, 2, 47},
+ {0x00D2, 0, 2, 49},
+ {0x00D3, 0, 2, 51},
+ {0x00D4, 0, 2, 53},
+ {0x00D5, 0, 2, 55},
+ {0x00D6, 0, 2, 57},
+ {0x00D9, 0, 2, 59},
+ {0x00DA, 0, 2, 61},
+ {0x00DB, 0, 2, 63},
+ {0x00DC, 0, 2, 65},
+ {0x00DD, 0, 2, 67},
+ {0x00E0, 0, 2, 69},
+ {0x00E1, 0, 2, 71},
+ {0x00E2, 0, 2, 73},
+ {0x00E3, 0, 2, 75},
+ {0x00E4, 0, 2, 77},
+ {0x00E5, 0, 2, 79},
+ {0x00E7, 0, 2, 81},
+ {0x00E8, 0, 2, 83},
+ {0x00E9, 0, 2, 85},
+ {0x00EA, 0, 2, 87},
+ {0x00EB, 0, 2, 89},
+ {0x00EC, 0, 2, 91},
+ {0x00ED, 0, 2, 93},
+ {0x00EE, 0, 2, 95},
+ {0x00EF, 0, 2, 97},
+ {0x00F1, 0, 2, 99},
+ {0x00F2, 0, 2, 101},
+ {0x00F3, 0, 2, 103},
+ {0x00F4, 0, 2, 105},
+ {0x00F5, 0, 2, 107},
+ {0x00F6, 0, 2, 109},
+ {0x00F9, 0, 2, 111},
+ {0x00FA, 0, 2, 113},
+ {0x00FB, 0, 2, 115},
+ {0x00FC, 0, 2, 117},
+ {0x00FD, 0, 2, 119},
+ {0x00FF, 0, 2, 121},
+ {0x0100, 0, 2, 123},
+ {0x0101, 0, 2, 125},
+ {0x0102, 0, 2, 127},
+ {0x0103, 0, 2, 129},
+ {0x0104, 0, 2, 131},
+ {0x0105, 0, 2, 133},
+ {0x0106, 0, 2, 135},
+ {0x0107, 0, 2, 137},
+ {0x0108, 0, 2, 139},
+ {0x0109, 0, 2, 141},
+ {0x010A, 0, 2, 143},
+ {0x010B, 0, 2, 145},
+ {0x010C, 0, 2, 147},
+ {0x010D, 0, 2, 149},
+ {0x010E, 0, 2, 151},
+ {0x010F, 0, 2, 153},
+ {0x0112, 0, 2, 155},
+ {0x0113, 0, 2, 157},
+ {0x0114, 0, 2, 159},
+ {0x0115, 0, 2, 161},
+ {0x0116, 0, 2, 163},
+ {0x0117, 0, 2, 165},
+ {0x0118, 0, 2, 167},
+ {0x0119, 0, 2, 169},
+ {0x011A, 0, 2, 171},
+ {0x011B, 0, 2, 173},
+ {0x011C, 0, 2, 175},
+ {0x011D, 0, 2, 177},
+ {0x011E, 0, 2, 179},
+ {0x011F, 0, 2, 181},
+ {0x0120, 0, 2, 183},
+ {0x0121, 0, 2, 185},
+ {0x0122, 0, 2, 187},
+ {0x0123, 0, 2, 189},
+ {0x0124, 0, 2, 191},
+ {0x0125, 0, 2, 193},
+ {0x0128, 0, 2, 195},
+ {0x0129, 0, 2, 197},
+ {0x012A, 0, 2, 199},
+ {0x012B, 0, 2, 201},
+ {0x012C, 0, 2, 203},
+ {0x012D, 0, 2, 205},
+ {0x012E, 0, 2, 207},
+ {0x012F, 0, 2, 209},
+ {0x0130, 0, 2, 211},
+ {0x0132, 0, 2 | DECOMP_COMPAT, 213},
+ {0x0133, 0, 2 | DECOMP_COMPAT, 215},
+ {0x0134, 0, 2, 217},
+ {0x0135, 0, 2, 219},
+ {0x0136, 0, 2, 221},
+ {0x0137, 0, 2, 223},
+ {0x0139, 0, 2, 225},
+ {0x013A, 0, 2, 227},
+ {0x013B, 0, 2, 229},
+ {0x013C, 0, 2, 231},
+ {0x013D, 0, 2, 233},
+ {0x013E, 0, 2, 235},
+ {0x013F, 0, 2 | DECOMP_COMPAT, 237},
+ {0x0140, 0, 2 | DECOMP_COMPAT, 239},
+ {0x0143, 0, 2, 241},
+ {0x0144, 0, 2, 243},
+ {0x0145, 0, 2, 245},
+ {0x0146, 0, 2, 247},
+ {0x0147, 0, 2, 249},
+ {0x0148, 0, 2, 251},
+ {0x0149, 0, 2 | DECOMP_COMPAT, 253},
+ {0x014C, 0, 2, 255},
+ {0x014D, 0, 2, 257},
+ {0x014E, 0, 2, 259},
+ {0x014F, 0, 2, 261},
+ {0x0150, 0, 2, 263},
+ {0x0151, 0, 2, 265},
+ {0x0154, 0, 2, 267},
+ {0x0155, 0, 2, 269},
+ {0x0156, 0, 2, 271},
+ {0x0157, 0, 2, 273},
+ {0x0158, 0, 2, 275},
+ {0x0159, 0, 2, 277},
+ {0x015A, 0, 2, 279},
+ {0x015B, 0, 2, 281},
+ {0x015C, 0, 2, 283},
+ {0x015D, 0, 2, 285},
+ {0x015E, 0, 2, 287},
+ {0x015F, 0, 2, 289},
+ {0x0160, 0, 2, 291},
+ {0x0161, 0, 2, 293},
+ {0x0162, 0, 2, 295},
+ {0x0163, 0, 2, 297},
+ {0x0164, 0, 2, 299},
+ {0x0165, 0, 2, 301},
+ {0x0168, 0, 2, 303},
+ {0x0169, 0, 2, 305},
+ {0x016A, 0, 2, 307},
+ {0x016B, 0, 2, 309},
+ {0x016C, 0, 2, 311},
+ {0x016D, 0, 2, 313},
+ {0x016E, 0, 2, 315},
+ {0x016F, 0, 2, 317},
+ {0x0170, 0, 2, 319},
+ {0x0171, 0, 2, 321},
+ {0x0172, 0, 2, 323},
+ {0x0173, 0, 2, 325},
+ {0x0174, 0, 2, 327},
+ {0x0175, 0, 2, 329},
+ {0x0176, 0, 2, 331},
+ {0x0177, 0, 2, 333},
+ {0x0178, 0, 2, 335},
+ {0x0179, 0, 2, 337},
+ {0x017A, 0, 2, 339},
+ {0x017B, 0, 2, 341},
+ {0x017C, 0, 2, 343},
+ {0x017D, 0, 2, 345},
+ {0x017E, 0, 2, 347},
+ {0x017F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0073},
+ {0x01A0, 0, 2, 349},
+ {0x01A1, 0, 2, 351},
+ {0x01AF, 0, 2, 353},
+ {0x01B0, 0, 2, 355},
+ {0x01C4, 0, 2 | DECOMP_COMPAT, 357},
+ {0x01C5, 0, 2 | DECOMP_COMPAT, 359},
+ {0x01C6, 0, 2 | DECOMP_COMPAT, 361},
+ {0x01C7, 0, 2 | DECOMP_COMPAT, 363},
+ {0x01C8, 0, 2 | DECOMP_COMPAT, 365},
+ {0x01C9, 0, 2 | DECOMP_COMPAT, 367},
+ {0x01CA, 0, 2 | DECOMP_COMPAT, 369},
+ {0x01CB, 0, 2 | DECOMP_COMPAT, 371},
+ {0x01CC, 0, 2 | DECOMP_COMPAT, 373},
+ {0x01CD, 0, 2, 375},
+ {0x01CE, 0, 2, 377},
+ {0x01CF, 0, 2, 379},
+ {0x01D0, 0, 2, 381},
+ {0x01D1, 0, 2, 383},
+ {0x01D2, 0, 2, 385},
+ {0x01D3, 0, 2, 387},
+ {0x01D4, 0, 2, 389},
+ {0x01D5, 0, 2, 391},
+ {0x01D6, 0, 2, 393},
+ {0x01D7, 0, 2, 395},
+ {0x01D8, 0, 2, 397},
+ {0x01D9, 0, 2, 399},
+ {0x01DA, 0, 2, 401},
+ {0x01DB, 0, 2, 403},
+ {0x01DC, 0, 2, 405},
+ {0x01DE, 0, 2, 407},
+ {0x01DF, 0, 2, 409},
+ {0x01E0, 0, 2, 411},
+ {0x01E1, 0, 2, 413},
+ {0x01E2, 0, 2, 415},
+ {0x01E3, 0, 2, 417},
+ {0x01E6, 0, 2, 419},
+ {0x01E7, 0, 2, 421},
+ {0x01E8, 0, 2, 423},
+ {0x01E9, 0, 2, 425},
+ {0x01EA, 0, 2, 427},
+ {0x01EB, 0, 2, 429},
+ {0x01EC, 0, 2, 431},
+ {0x01ED, 0, 2, 433},
+ {0x01EE, 0, 2, 435},
+ {0x01EF, 0, 2, 437},
+ {0x01F0, 0, 2, 439},
+ {0x01F1, 0, 2 | DECOMP_COMPAT, 441},
+ {0x01F2, 0, 2 | DECOMP_COMPAT, 443},
+ {0x01F3, 0, 2 | DECOMP_COMPAT, 445},
+ {0x01F4, 0, 2, 447},
+ {0x01F5, 0, 2, 449},
+ {0x01F8, 0, 2, 451},
+ {0x01F9, 0, 2, 453},
+ {0x01FA, 0, 2, 455},
+ {0x01FB, 0, 2, 457},
+ {0x01FC, 0, 2, 459},
+ {0x01FD, 0, 2, 461},
+ {0x01FE, 0, 2, 463},
+ {0x01FF, 0, 2, 465},
+ {0x0200, 0, 2, 467},
+ {0x0201, 0, 2, 469},
+ {0x0202, 0, 2, 471},
+ {0x0203, 0, 2, 473},
+ {0x0204, 0, 2, 475},
+ {0x0205, 0, 2, 477},
+ {0x0206, 0, 2, 479},
+ {0x0207, 0, 2, 481},
+ {0x0208, 0, 2, 483},
+ {0x0209, 0, 2, 485},
+ {0x020A, 0, 2, 487},
+ {0x020B, 0, 2, 489},
+ {0x020C, 0, 2, 491},
+ {0x020D, 0, 2, 493},
+ {0x020E, 0, 2, 495},
+ {0x020F, 0, 2, 497},
+ {0x0210, 0, 2, 499},
+ {0x0211, 0, 2, 501},
+ {0x0212, 0, 2, 503},
+ {0x0213, 0, 2, 505},
+ {0x0214, 0, 2, 507},
+ {0x0215, 0, 2, 509},
+ {0x0216, 0, 2, 511},
+ {0x0217, 0, 2, 513},
+ {0x0218, 0, 2, 515},
+ {0x0219, 0, 2, 517},
+ {0x021A, 0, 2, 519},
+ {0x021B, 0, 2, 521},
+ {0x021E, 0, 2, 523},
+ {0x021F, 0, 2, 525},
+ {0x0226, 0, 2, 527},
+ {0x0227, 0, 2, 529},
+ {0x0228, 0, 2, 531},
+ {0x0229, 0, 2, 533},
+ {0x022A, 0, 2, 535},
+ {0x022B, 0, 2, 537},
+ {0x022C, 0, 2, 539},
+ {0x022D, 0, 2, 541},
+ {0x022E, 0, 2, 543},
+ {0x022F, 0, 2, 545},
+ {0x0230, 0, 2, 547},
+ {0x0231, 0, 2, 549},
+ {0x0232, 0, 2, 551},
+ {0x0233, 0, 2, 553},
+ {0x02B0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0068},
+ {0x02B1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0266},
+ {0x02B2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006A},
+ {0x02B3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0072},
+ {0x02B4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0279},
+ {0x02B5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x027B},
+ {0x02B6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0281},
+ {0x02B7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0077},
+ {0x02B8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0079},
+ {0x02D8, 0, 2 | DECOMP_COMPAT, 555},
+ {0x02D9, 0, 2 | DECOMP_COMPAT, 557},
+ {0x02DA, 0, 2 | DECOMP_COMPAT, 559},
+ {0x02DB, 0, 2 | DECOMP_COMPAT, 561},
+ {0x02DC, 0, 2 | DECOMP_COMPAT, 563},
+ {0x02DD, 0, 2 | DECOMP_COMPAT, 565},
+ {0x02E0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0263},
+ {0x02E1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006C},
+ {0x02E2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0073},
+ {0x02E3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0078},
+ {0x02E4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0295},
+ {0x0300, 230, 0, 0},
+ {0x0301, 230, 0, 0},
+ {0x0302, 230, 0, 0},
+ {0x0303, 230, 0, 0},
+ {0x0304, 230, 0, 0},
+ {0x0305, 230, 0, 0},
+ {0x0306, 230, 0, 0},
+ {0x0307, 230, 0, 0},
+ {0x0308, 230, 0, 0},
+ {0x0309, 230, 0, 0},
+ {0x030A, 230, 0, 0},
+ {0x030B, 230, 0, 0},
+ {0x030C, 230, 0, 0},
+ {0x030D, 230, 0, 0},
+ {0x030E, 230, 0, 0},
+ {0x030F, 230, 0, 0},
+ {0x0310, 230, 0, 0},
+ {0x0311, 230, 0, 0},
+ {0x0312, 230, 0, 0},
+ {0x0313, 230, 0, 0},
+ {0x0314, 230, 0, 0},
+ {0x0315, 232, 0, 0},
+ {0x0316, 220, 0, 0},
+ {0x0317, 220, 0, 0},
+ {0x0318, 220, 0, 0},
+ {0x0319, 220, 0, 0},
+ {0x031A, 232, 0, 0},
+ {0x031B, 216, 0, 0},
+ {0x031C, 220, 0, 0},
+ {0x031D, 220, 0, 0},
+ {0x031E, 220, 0, 0},
+ {0x031F, 220, 0, 0},
+ {0x0320, 220, 0, 0},
+ {0x0321, 202, 0, 0},
+ {0x0322, 202, 0, 0},
+ {0x0323, 220, 0, 0},
+ {0x0324, 220, 0, 0},
+ {0x0325, 220, 0, 0},
+ {0x0326, 220, 0, 0},
+ {0x0327, 202, 0, 0},
+ {0x0328, 202, 0, 0},
+ {0x0329, 220, 0, 0},
+ {0x032A, 220, 0, 0},
+ {0x032B, 220, 0, 0},
+ {0x032C, 220, 0, 0},
+ {0x032D, 220, 0, 0},
+ {0x032E, 220, 0, 0},
+ {0x032F, 220, 0, 0},
+ {0x0330, 220, 0, 0},
+ {0x0331, 220, 0, 0},
+ {0x0332, 220, 0, 0},
+ {0x0333, 220, 0, 0},
+ {0x0334, 1, 0, 0},
+ {0x0335, 1, 0, 0},
+ {0x0336, 1, 0, 0},
+ {0x0337, 1, 0, 0},
+ {0x0338, 1, 0, 0},
+ {0x0339, 220, 0, 0},
+ {0x033A, 220, 0, 0},
+ {0x033B, 220, 0, 0},
+ {0x033C, 220, 0, 0},
+ {0x033D, 230, 0, 0},
+ {0x033E, 230, 0, 0},
+ {0x033F, 230, 0, 0},
+ {0x0340, 230, 1 | DECOMP_INLINE, 0x0300},
+ {0x0341, 230, 1 | DECOMP_INLINE, 0x0301},
+ {0x0342, 230, 0, 0},
+ {0x0343, 230, 1 | DECOMP_INLINE, 0x0313},
+ {0x0344, 230, 2 | DECOMP_NO_COMPOSE, 567}, /* non-starter decomposition */
+ {0x0345, 240, 0, 0},
+ {0x0346, 230, 0, 0},
+ {0x0347, 220, 0, 0},
+ {0x0348, 220, 0, 0},
+ {0x0349, 220, 0, 0},
+ {0x034A, 230, 0, 0},
+ {0x034B, 230, 0, 0},
+ {0x034C, 230, 0, 0},
+ {0x034D, 220, 0, 0},
+ {0x034E, 220, 0, 0},
+ {0x0350, 230, 0, 0},
+ {0x0351, 230, 0, 0},
+ {0x0352, 230, 0, 0},
+ {0x0353, 220, 0, 0},
+ {0x0354, 220, 0, 0},
+ {0x0355, 220, 0, 0},
+ {0x0356, 220, 0, 0},
+ {0x0357, 230, 0, 0},
+ {0x0358, 232, 0, 0},
+ {0x0359, 220, 0, 0},
+ {0x035A, 220, 0, 0},
+ {0x035B, 230, 0, 0},
+ {0x035C, 233, 0, 0},
+ {0x035D, 234, 0, 0},
+ {0x035E, 234, 0, 0},
+ {0x035F, 233, 0, 0},
+ {0x0360, 234, 0, 0},
+ {0x0361, 234, 0, 0},
+ {0x0362, 233, 0, 0},
+ {0x0363, 230, 0, 0},
+ {0x0364, 230, 0, 0},
+ {0x0365, 230, 0, 0},
+ {0x0366, 230, 0, 0},
+ {0x0367, 230, 0, 0},
+ {0x0368, 230, 0, 0},
+ {0x0369, 230, 0, 0},
+ {0x036A, 230, 0, 0},
+ {0x036B, 230, 0, 0},
+ {0x036C, 230, 0, 0},
+ {0x036D, 230, 0, 0},
+ {0x036E, 230, 0, 0},
+ {0x036F, 230, 0, 0},
+ {0x0374, 0, 1 | DECOMP_INLINE, 0x02B9},
+ {0x037A, 0, 2 | DECOMP_COMPAT, 569},
+ {0x037E, 0, 1 | DECOMP_INLINE, 0x003B},
+ {0x0384, 0, 2 | DECOMP_COMPAT, 571},
+ {0x0385, 0, 2, 573},
+ {0x0386, 0, 2, 575},
+ {0x0387, 0, 1 | DECOMP_INLINE, 0x00B7},
+ {0x0388, 0, 2, 577},
+ {0x0389, 0, 2, 579},
+ {0x038A, 0, 2, 581},
+ {0x038C, 0, 2, 583},
+ {0x038E, 0, 2, 585},
+ {0x038F, 0, 2, 587},
+ {0x0390, 0, 2, 589},
+ {0x03AA, 0, 2, 591},
+ {0x03AB, 0, 2, 593},
+ {0x03AC, 0, 2, 595},
+ {0x03AD, 0, 2, 597},
+ {0x03AE, 0, 2, 599},
+ {0x03AF, 0, 2, 601},
+ {0x03B0, 0, 2, 603},
+ {0x03CA, 0, 2, 605},
+ {0x03CB, 0, 2, 607},
+ {0x03CC, 0, 2, 609},
+ {0x03CD, 0, 2, 611},
+ {0x03CE, 0, 2, 613},
+ {0x03D0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B2},
+ {0x03D1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B8},
+ {0x03D2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A5},
+ {0x03D3, 0, 2, 615},
+ {0x03D4, 0, 2, 617},
+ {0x03D5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C6},
+ {0x03D6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C0},
+ {0x03F0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BA},
+ {0x03F1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C1},
+ {0x03F2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C2},
+ {0x03F4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0398},
+ {0x03F5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B5},
+ {0x03F9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A3},
+ {0x0400, 0, 2, 619},
+ {0x0401, 0, 2, 621},
+ {0x0403, 0, 2, 623},
+ {0x0407, 0, 2, 625},
+ {0x040C, 0, 2, 627},
+ {0x040D, 0, 2, 629},
+ {0x040E, 0, 2, 631},
+ {0x0419, 0, 2, 633},
+ {0x0439, 0, 2, 635},
+ {0x0450, 0, 2, 637},
+ {0x0451, 0, 2, 639},
+ {0x0453, 0, 2, 641},
+ {0x0457, 0, 2, 643},
+ {0x045C, 0, 2, 645},
+ {0x045D, 0, 2, 647},
+ {0x045E, 0, 2, 649},
+ {0x0476, 0, 2, 651},
+ {0x0477, 0, 2, 653},
+ {0x0483, 230, 0, 0},
+ {0x0484, 230, 0, 0},
+ {0x0485, 230, 0, 0},
+ {0x0486, 230, 0, 0},
+ {0x0487, 230, 0, 0},
+ {0x04C1, 0, 2, 655},
+ {0x04C2, 0, 2, 657},
+ {0x04D0, 0, 2, 659},
+ {0x04D1, 0, 2, 661},
+ {0x04D2, 0, 2, 663},
+ {0x04D3, 0, 2, 665},
+ {0x04D6, 0, 2, 667},
+ {0x04D7, 0, 2, 669},
+ {0x04DA, 0, 2, 671},
+ {0x04DB, 0, 2, 673},
+ {0x04DC, 0, 2, 675},
+ {0x04DD, 0, 2, 677},
+ {0x04DE, 0, 2, 679},
+ {0x04DF, 0, 2, 681},
+ {0x04E2, 0, 2, 683},
+ {0x04E3, 0, 2, 685},
+ {0x04E4, 0, 2, 687},
+ {0x04E5, 0, 2, 689},
+ {0x04E6, 0, 2, 691},
+ {0x04E7, 0, 2, 693},
+ {0x04EA, 0, 2, 695},
+ {0x04EB, 0, 2, 697},
+ {0x04EC, 0, 2, 699},
+ {0x04ED, 0, 2, 701},
+ {0x04EE, 0, 2, 703},
+ {0x04EF, 0, 2, 705},
+ {0x04F0, 0, 2, 707},
+ {0x04F1, 0, 2, 709},
+ {0x04F2, 0, 2, 711},
+ {0x04F3, 0, 2, 713},
+ {0x04F4, 0, 2, 715},
+ {0x04F5, 0, 2, 717},
+ {0x04F8, 0, 2, 719},
+ {0x04F9, 0, 2, 721},
+ {0x0587, 0, 2 | DECOMP_COMPAT, 723},
+ {0x0591, 220, 0, 0},
+ {0x0592, 230, 0, 0},
+ {0x0593, 230, 0, 0},
+ {0x0594, 230, 0, 0},
+ {0x0595, 230, 0, 0},
+ {0x0596, 220, 0, 0},
+ {0x0597, 230, 0, 0},
+ {0x0598, 230, 0, 0},
+ {0x0599, 230, 0, 0},
+ {0x059A, 222, 0, 0},
+ {0x059B, 220, 0, 0},
+ {0x059C, 230, 0, 0},
+ {0x059D, 230, 0, 0},
+ {0x059E, 230, 0, 0},
+ {0x059F, 230, 0, 0},
+ {0x05A0, 230, 0, 0},
+ {0x05A1, 230, 0, 0},
+ {0x05A2, 220, 0, 0},
+ {0x05A3, 220, 0, 0},
+ {0x05A4, 220, 0, 0},
+ {0x05A5, 220, 0, 0},
+ {0x05A6, 220, 0, 0},
+ {0x05A7, 220, 0, 0},
+ {0x05A8, 230, 0, 0},
+ {0x05A9, 230, 0, 0},
+ {0x05AA, 220, 0, 0},
+ {0x05AB, 230, 0, 0},
+ {0x05AC, 230, 0, 0},
+ {0x05AD, 222, 0, 0},
+ {0x05AE, 228, 0, 0},
+ {0x05AF, 230, 0, 0},
+ {0x05B0, 10, 0, 0},
+ {0x05B1, 11, 0, 0},
+ {0x05B2, 12, 0, 0},
+ {0x05B3, 13, 0, 0},
+ {0x05B4, 14, 0, 0},
+ {0x05B5, 15, 0, 0},
+ {0x05B6, 16, 0, 0},
+ {0x05B7, 17, 0, 0},
+ {0x05B8, 18, 0, 0},
+ {0x05B9, 19, 0, 0},
+ {0x05BA, 19, 0, 0},
+ {0x05BB, 20, 0, 0},
+ {0x05BC, 21, 0, 0},
+ {0x05BD, 22, 0, 0},
+ {0x05BF, 23, 0, 0},
+ {0x05C1, 24, 0, 0},
+ {0x05C2, 25, 0, 0},
+ {0x05C4, 230, 0, 0},
+ {0x05C5, 220, 0, 0},
+ {0x05C7, 18, 0, 0},
+ {0x0610, 230, 0, 0},
+ {0x0611, 230, 0, 0},
+ {0x0612, 230, 0, 0},
+ {0x0613, 230, 0, 0},
+ {0x0614, 230, 0, 0},
+ {0x0615, 230, 0, 0},
+ {0x0616, 230, 0, 0},
+ {0x0617, 230, 0, 0},
+ {0x0618, 30, 0, 0},
+ {0x0619, 31, 0, 0},
+ {0x061A, 32, 0, 0},
+ {0x0622, 0, 2, 725},
+ {0x0623, 0, 2, 727},
+ {0x0624, 0, 2, 729},
+ {0x0625, 0, 2, 731},
+ {0x0626, 0, 2, 733},
+ {0x064B, 27, 0, 0},
+ {0x064C, 28, 0, 0},
+ {0x064D, 29, 0, 0},
+ {0x064E, 30, 0, 0},
+ {0x064F, 31, 0, 0},
+ {0x0650, 32, 0, 0},
+ {0x0651, 33, 0, 0},
+ {0x0652, 34, 0, 0},
+ {0x0653, 230, 0, 0},
+ {0x0654, 230, 0, 0},
+ {0x0655, 220, 0, 0},
+ {0x0656, 220, 0, 0},
+ {0x0657, 230, 0, 0},
+ {0x0658, 230, 0, 0},
+ {0x0659, 230, 0, 0},
+ {0x065A, 230, 0, 0},
+ {0x065B, 230, 0, 0},
+ {0x065C, 220, 0, 0},
+ {0x065D, 230, 0, 0},
+ {0x065E, 230, 0, 0},
+ {0x065F, 220, 0, 0},
+ {0x0670, 35, 0, 0},
+ {0x0675, 0, 2 | DECOMP_COMPAT, 735},
+ {0x0676, 0, 2 | DECOMP_COMPAT, 737},
+ {0x0677, 0, 2 | DECOMP_COMPAT, 739},
+ {0x0678, 0, 2 | DECOMP_COMPAT, 741},
+ {0x06C0, 0, 2, 743},
+ {0x06C2, 0, 2, 745},
+ {0x06D3, 0, 2, 747},
+ {0x06D6, 230, 0, 0},
+ {0x06D7, 230, 0, 0},
+ {0x06D8, 230, 0, 0},
+ {0x06D9, 230, 0, 0},
+ {0x06DA, 230, 0, 0},
+ {0x06DB, 230, 0, 0},
+ {0x06DC, 230, 0, 0},
+ {0x06DF, 230, 0, 0},
+ {0x06E0, 230, 0, 0},
+ {0x06E1, 230, 0, 0},
+ {0x06E2, 230, 0, 0},
+ {0x06E3, 220, 0, 0},
+ {0x06E4, 230, 0, 0},
+ {0x06E7, 230, 0, 0},
+ {0x06E8, 230, 0, 0},
+ {0x06EA, 220, 0, 0},
+ {0x06EB, 230, 0, 0},
+ {0x06EC, 230, 0, 0},
+ {0x06ED, 220, 0, 0},
+ {0x0711, 36, 0, 0},
+ {0x0730, 230, 0, 0},
+ {0x0731, 220, 0, 0},
+ {0x0732, 230, 0, 0},
+ {0x0733, 230, 0, 0},
+ {0x0734, 220, 0, 0},
+ {0x0735, 230, 0, 0},
+ {0x0736, 230, 0, 0},
+ {0x0737, 220, 0, 0},
+ {0x0738, 220, 0, 0},
+ {0x0739, 220, 0, 0},
+ {0x073A, 230, 0, 0},
+ {0x073B, 220, 0, 0},
+ {0x073C, 220, 0, 0},
+ {0x073D, 230, 0, 0},
+ {0x073E, 220, 0, 0},
+ {0x073F, 230, 0, 0},
+ {0x0740, 230, 0, 0},
+ {0x0741, 230, 0, 0},
+ {0x0742, 220, 0, 0},
+ {0x0743, 230, 0, 0},
+ {0x0744, 220, 0, 0},
+ {0x0745, 230, 0, 0},
+ {0x0746, 220, 0, 0},
+ {0x0747, 230, 0, 0},
+ {0x0748, 220, 0, 0},
+ {0x0749, 230, 0, 0},
+ {0x074A, 230, 0, 0},
+ {0x07EB, 230, 0, 0},
+ {0x07EC, 230, 0, 0},
+ {0x07ED, 230, 0, 0},
+ {0x07EE, 230, 0, 0},
+ {0x07EF, 230, 0, 0},
+ {0x07F0, 230, 0, 0},
+ {0x07F1, 230, 0, 0},
+ {0x07F2, 220, 0, 0},
+ {0x07F3, 230, 0, 0},
+ {0x07FD, 220, 0, 0},
+ {0x0816, 230, 0, 0},
+ {0x0817, 230, 0, 0},
+ {0x0818, 230, 0, 0},
+ {0x0819, 230, 0, 0},
+ {0x081B, 230, 0, 0},
+ {0x081C, 230, 0, 0},
+ {0x081D, 230, 0, 0},
+ {0x081E, 230, 0, 0},
+ {0x081F, 230, 0, 0},
+ {0x0820, 230, 0, 0},
+ {0x0821, 230, 0, 0},
+ {0x0822, 230, 0, 0},
+ {0x0823, 230, 0, 0},
+ {0x0825, 230, 0, 0},
+ {0x0826, 230, 0, 0},
+ {0x0827, 230, 0, 0},
+ {0x0829, 230, 0, 0},
+ {0x082A, 230, 0, 0},
+ {0x082B, 230, 0, 0},
+ {0x082C, 230, 0, 0},
+ {0x082D, 230, 0, 0},
+ {0x0859, 220, 0, 0},
+ {0x085A, 220, 0, 0},
+ {0x085B, 220, 0, 0},
+ {0x0898, 230, 0, 0},
+ {0x0899, 220, 0, 0},
+ {0x089A, 220, 0, 0},
+ {0x089B, 220, 0, 0},
+ {0x089C, 230, 0, 0},
+ {0x089D, 230, 0, 0},
+ {0x089E, 230, 0, 0},
+ {0x089F, 230, 0, 0},
+ {0x08CA, 230, 0, 0},
+ {0x08CB, 230, 0, 0},
+ {0x08CC, 230, 0, 0},
+ {0x08CD, 230, 0, 0},
+ {0x08CE, 230, 0, 0},
+ {0x08CF, 220, 0, 0},
+ {0x08D0, 220, 0, 0},
+ {0x08D1, 220, 0, 0},
+ {0x08D2, 220, 0, 0},
+ {0x08D3, 220, 0, 0},
+ {0x08D4, 230, 0, 0},
+ {0x08D5, 230, 0, 0},
+ {0x08D6, 230, 0, 0},
+ {0x08D7, 230, 0, 0},
+ {0x08D8, 230, 0, 0},
+ {0x08D9, 230, 0, 0},
+ {0x08DA, 230, 0, 0},
+ {0x08DB, 230, 0, 0},
+ {0x08DC, 230, 0, 0},
+ {0x08DD, 230, 0, 0},
+ {0x08DE, 230, 0, 0},
+ {0x08DF, 230, 0, 0},
+ {0x08E0, 230, 0, 0},
+ {0x08E1, 230, 0, 0},
+ {0x08E3, 220, 0, 0},
+ {0x08E4, 230, 0, 0},
+ {0x08E5, 230, 0, 0},
+ {0x08E6, 220, 0, 0},
+ {0x08E7, 230, 0, 0},
+ {0x08E8, 230, 0, 0},
+ {0x08E9, 220, 0, 0},
+ {0x08EA, 230, 0, 0},
+ {0x08EB, 230, 0, 0},
+ {0x08EC, 230, 0, 0},
+ {0x08ED, 220, 0, 0},
+ {0x08EE, 220, 0, 0},
+ {0x08EF, 220, 0, 0},
+ {0x08F0, 27, 0, 0},
+ {0x08F1, 28, 0, 0},
+ {0x08F2, 29, 0, 0},
+ {0x08F3, 230, 0, 0},
+ {0x08F4, 230, 0, 0},
+ {0x08F5, 230, 0, 0},
+ {0x08F6, 220, 0, 0},
+ {0x08F7, 230, 0, 0},
+ {0x08F8, 230, 0, 0},
+ {0x08F9, 220, 0, 0},
+ {0x08FA, 220, 0, 0},
+ {0x08FB, 230, 0, 0},
+ {0x08FC, 230, 0, 0},
+ {0x08FD, 230, 0, 0},
+ {0x08FE, 230, 0, 0},
+ {0x08FF, 230, 0, 0},
+ {0x0929, 0, 2, 749},
+ {0x0931, 0, 2, 751},
+ {0x0934, 0, 2, 753},
+ {0x093C, 7, 0, 0},
+ {0x094D, 9, 0, 0},
+ {0x0951, 230, 0, 0},
+ {0x0952, 220, 0, 0},
+ {0x0953, 230, 0, 0},
+ {0x0954, 230, 0, 0},
+ {0x0958, 0, 2 | DECOMP_NO_COMPOSE, 755}, /* in exclusion list */
+ {0x0959, 0, 2 | DECOMP_NO_COMPOSE, 757}, /* in exclusion list */
+ {0x095A, 0, 2 | DECOMP_NO_COMPOSE, 759}, /* in exclusion list */
+ {0x095B, 0, 2 | DECOMP_NO_COMPOSE, 761}, /* in exclusion list */
+ {0x095C, 0, 2 | DECOMP_NO_COMPOSE, 763}, /* in exclusion list */
+ {0x095D, 0, 2 | DECOMP_NO_COMPOSE, 765}, /* in exclusion list */
+ {0x095E, 0, 2 | DECOMP_NO_COMPOSE, 767}, /* in exclusion list */
+ {0x095F, 0, 2 | DECOMP_NO_COMPOSE, 769}, /* in exclusion list */
+ {0x09BC, 7, 0, 0},
+ {0x09CB, 0, 2, 771},
+ {0x09CC, 0, 2, 773},
+ {0x09CD, 9, 0, 0},
+ {0x09DC, 0, 2 | DECOMP_NO_COMPOSE, 775}, /* in exclusion list */
+ {0x09DD, 0, 2 | DECOMP_NO_COMPOSE, 777}, /* in exclusion list */
+ {0x09DF, 0, 2 | DECOMP_NO_COMPOSE, 779}, /* in exclusion list */
+ {0x09FE, 230, 0, 0},
+ {0x0A33, 0, 2 | DECOMP_NO_COMPOSE, 781}, /* in exclusion list */
+ {0x0A36, 0, 2 | DECOMP_NO_COMPOSE, 783}, /* in exclusion list */
+ {0x0A3C, 7, 0, 0},
+ {0x0A4D, 9, 0, 0},
+ {0x0A59, 0, 2 | DECOMP_NO_COMPOSE, 785}, /* in exclusion list */
+ {0x0A5A, 0, 2 | DECOMP_NO_COMPOSE, 787}, /* in exclusion list */
+ {0x0A5B, 0, 2 | DECOMP_NO_COMPOSE, 789}, /* in exclusion list */
+ {0x0A5E, 0, 2 | DECOMP_NO_COMPOSE, 791}, /* in exclusion list */
+ {0x0ABC, 7, 0, 0},
+ {0x0ACD, 9, 0, 0},
+ {0x0B3C, 7, 0, 0},
+ {0x0B48, 0, 2, 793},
+ {0x0B4B, 0, 2, 795},
+ {0x0B4C, 0, 2, 797},
+ {0x0B4D, 9, 0, 0},
+ {0x0B5C, 0, 2 | DECOMP_NO_COMPOSE, 799}, /* in exclusion list */
+ {0x0B5D, 0, 2 | DECOMP_NO_COMPOSE, 801}, /* in exclusion list */
+ {0x0B94, 0, 2, 803},
+ {0x0BCA, 0, 2, 805},
+ {0x0BCB, 0, 2, 807},
+ {0x0BCC, 0, 2, 809},
+ {0x0BCD, 9, 0, 0},
+ {0x0C3C, 7, 0, 0},
+ {0x0C48, 0, 2, 811},
+ {0x0C4D, 9, 0, 0},
+ {0x0C55, 84, 0, 0},
+ {0x0C56, 91, 0, 0},
+ {0x0CBC, 7, 0, 0},
+ {0x0CC0, 0, 2, 813},
+ {0x0CC7, 0, 2, 815},
+ {0x0CC8, 0, 2, 817},
+ {0x0CCA, 0, 2, 819},
+ {0x0CCB, 0, 2, 821},
+ {0x0CCD, 9, 0, 0},
+ {0x0D3B, 9, 0, 0},
+ {0x0D3C, 9, 0, 0},
+ {0x0D4A, 0, 2, 823},
+ {0x0D4B, 0, 2, 825},
+ {0x0D4C, 0, 2, 827},
+ {0x0D4D, 9, 0, 0},
+ {0x0DCA, 9, 0, 0},
+ {0x0DDA, 0, 2, 829},
+ {0x0DDC, 0, 2, 831},
+ {0x0DDD, 0, 2, 833},
+ {0x0DDE, 0, 2, 835},
+ {0x0E33, 0, 2 | DECOMP_COMPAT, 837},
+ {0x0E38, 103, 0, 0},
+ {0x0E39, 103, 0, 0},
+ {0x0E3A, 9, 0, 0},
+ {0x0E48, 107, 0, 0},
+ {0x0E49, 107, 0, 0},
+ {0x0E4A, 107, 0, 0},
+ {0x0E4B, 107, 0, 0},
+ {0x0EB3, 0, 2 | DECOMP_COMPAT, 839},
+ {0x0EB8, 118, 0, 0},
+ {0x0EB9, 118, 0, 0},
+ {0x0EBA, 9, 0, 0},
+ {0x0EC8, 122, 0, 0},
+ {0x0EC9, 122, 0, 0},
+ {0x0ECA, 122, 0, 0},
+ {0x0ECB, 122, 0, 0},
+ {0x0EDC, 0, 2 | DECOMP_COMPAT, 841},
+ {0x0EDD, 0, 2 | DECOMP_COMPAT, 843},
+ {0x0F0C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0F0B},
+ {0x0F18, 220, 0, 0},
+ {0x0F19, 220, 0, 0},
+ {0x0F35, 220, 0, 0},
+ {0x0F37, 220, 0, 0},
+ {0x0F39, 216, 0, 0},
+ {0x0F43, 0, 2 | DECOMP_NO_COMPOSE, 845}, /* in exclusion list */
+ {0x0F4D, 0, 2 | DECOMP_NO_COMPOSE, 847}, /* in exclusion list */
+ {0x0F52, 0, 2 | DECOMP_NO_COMPOSE, 849}, /* in exclusion list */
+ {0x0F57, 0, 2 | DECOMP_NO_COMPOSE, 851}, /* in exclusion list */
+ {0x0F5C, 0, 2 | DECOMP_NO_COMPOSE, 853}, /* in exclusion list */
+ {0x0F69, 0, 2 | DECOMP_NO_COMPOSE, 855}, /* in exclusion list */
+ {0x0F71, 129, 0, 0},
+ {0x0F72, 130, 0, 0},
+ {0x0F73, 0, 2 | DECOMP_NO_COMPOSE, 857}, /* non-starter decomposition */
+ {0x0F74, 132, 0, 0},
+ {0x0F75, 0, 2 | DECOMP_NO_COMPOSE, 859}, /* non-starter decomposition */
+ {0x0F76, 0, 2 | DECOMP_NO_COMPOSE, 861}, /* in exclusion list */
+ {0x0F77, 0, 2 | DECOMP_COMPAT, 863},
+ {0x0F78, 0, 2 | DECOMP_NO_COMPOSE, 865}, /* in exclusion list */
+ {0x0F79, 0, 2 | DECOMP_COMPAT, 867},
+ {0x0F7A, 130, 0, 0},
+ {0x0F7B, 130, 0, 0},
+ {0x0F7C, 130, 0, 0},
+ {0x0F7D, 130, 0, 0},
+ {0x0F80, 130, 0, 0},
+ {0x0F81, 0, 2 | DECOMP_NO_COMPOSE, 869}, /* non-starter decomposition */
+ {0x0F82, 230, 0, 0},
+ {0x0F83, 230, 0, 0},
+ {0x0F84, 9, 0, 0},
+ {0x0F86, 230, 0, 0},
+ {0x0F87, 230, 0, 0},
+ {0x0F93, 0, 2 | DECOMP_NO_COMPOSE, 871}, /* in exclusion list */
+ {0x0F9D, 0, 2 | DECOMP_NO_COMPOSE, 873}, /* in exclusion list */
+ {0x0FA2, 0, 2 | DECOMP_NO_COMPOSE, 875}, /* in exclusion list */
+ {0x0FA7, 0, 2 | DECOMP_NO_COMPOSE, 877}, /* in exclusion list */
+ {0x0FAC, 0, 2 | DECOMP_NO_COMPOSE, 879}, /* in exclusion list */
+ {0x0FB9, 0, 2 | DECOMP_NO_COMPOSE, 881}, /* in exclusion list */
+ {0x0FC6, 220, 0, 0},
+ {0x1026, 0, 2, 883},
+ {0x1037, 7, 0, 0},
+ {0x1039, 9, 0, 0},
+ {0x103A, 9, 0, 0},
+ {0x108D, 220, 0, 0},
+ {0x10FC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x10DC},
+ {0x135D, 230, 0, 0},
+ {0x135E, 230, 0, 0},
+ {0x135F, 230, 0, 0},
+ {0x1714, 9, 0, 0},
+ {0x1715, 9, 0, 0},
+ {0x1734, 9, 0, 0},
+ {0x17D2, 9, 0, 0},
+ {0x17DD, 230, 0, 0},
+ {0x18A9, 228, 0, 0},
+ {0x1939, 222, 0, 0},
+ {0x193A, 230, 0, 0},
+ {0x193B, 220, 0, 0},
+ {0x1A17, 230, 0, 0},
+ {0x1A18, 220, 0, 0},
+ {0x1A60, 9, 0, 0},
+ {0x1A75, 230, 0, 0},
+ {0x1A76, 230, 0, 0},
+ {0x1A77, 230, 0, 0},
+ {0x1A78, 230, 0, 0},
+ {0x1A79, 230, 0, 0},
+ {0x1A7A, 230, 0, 0},
+ {0x1A7B, 230, 0, 0},
+ {0x1A7C, 230, 0, 0},
+ {0x1A7F, 220, 0, 0},
+ {0x1AB0, 230, 0, 0},
+ {0x1AB1, 230, 0, 0},
+ {0x1AB2, 230, 0, 0},
+ {0x1AB3, 230, 0, 0},
+ {0x1AB4, 230, 0, 0},
+ {0x1AB5, 220, 0, 0},
+ {0x1AB6, 220, 0, 0},
+ {0x1AB7, 220, 0, 0},
+ {0x1AB8, 220, 0, 0},
+ {0x1AB9, 220, 0, 0},
+ {0x1ABA, 220, 0, 0},
+ {0x1ABB, 230, 0, 0},
+ {0x1ABC, 230, 0, 0},
+ {0x1ABD, 220, 0, 0},
+ {0x1ABF, 220, 0, 0},
+ {0x1AC0, 220, 0, 0},
+ {0x1AC1, 230, 0, 0},
+ {0x1AC2, 230, 0, 0},
+ {0x1AC3, 220, 0, 0},
+ {0x1AC4, 220, 0, 0},
+ {0x1AC5, 230, 0, 0},
+ {0x1AC6, 230, 0, 0},
+ {0x1AC7, 230, 0, 0},
+ {0x1AC8, 230, 0, 0},
+ {0x1AC9, 230, 0, 0},
+ {0x1ACA, 220, 0, 0},
+ {0x1ACB, 230, 0, 0},
+ {0x1ACC, 230, 0, 0},
+ {0x1ACD, 230, 0, 0},
+ {0x1ACE, 230, 0, 0},
+ {0x1B06, 0, 2, 885},
+ {0x1B08, 0, 2, 887},
+ {0x1B0A, 0, 2, 889},
+ {0x1B0C, 0, 2, 891},
+ {0x1B0E, 0, 2, 893},
+ {0x1B12, 0, 2, 895},
+ {0x1B34, 7, 0, 0},
+ {0x1B3B, 0, 2, 897},
+ {0x1B3D, 0, 2, 899},
+ {0x1B40, 0, 2, 901},
+ {0x1B41, 0, 2, 903},
+ {0x1B43, 0, 2, 905},
+ {0x1B44, 9, 0, 0},
+ {0x1B6B, 230, 0, 0},
+ {0x1B6C, 220, 0, 0},
+ {0x1B6D, 230, 0, 0},
+ {0x1B6E, 230, 0, 0},
+ {0x1B6F, 230, 0, 0},
+ {0x1B70, 230, 0, 0},
+ {0x1B71, 230, 0, 0},
+ {0x1B72, 230, 0, 0},
+ {0x1B73, 230, 0, 0},
+ {0x1BAA, 9, 0, 0},
+ {0x1BAB, 9, 0, 0},
+ {0x1BE6, 7, 0, 0},
+ {0x1BF2, 9, 0, 0},
+ {0x1BF3, 9, 0, 0},
+ {0x1C37, 7, 0, 0},
+ {0x1CD0, 230, 0, 0},
+ {0x1CD1, 230, 0, 0},
+ {0x1CD2, 230, 0, 0},
+ {0x1CD4, 1, 0, 0},
+ {0x1CD5, 220, 0, 0},
+ {0x1CD6, 220, 0, 0},
+ {0x1CD7, 220, 0, 0},
+ {0x1CD8, 220, 0, 0},
+ {0x1CD9, 220, 0, 0},
+ {0x1CDA, 230, 0, 0},
+ {0x1CDB, 230, 0, 0},
+ {0x1CDC, 220, 0, 0},
+ {0x1CDD, 220, 0, 0},
+ {0x1CDE, 220, 0, 0},
+ {0x1CDF, 220, 0, 0},
+ {0x1CE0, 230, 0, 0},
+ {0x1CE2, 1, 0, 0},
+ {0x1CE3, 1, 0, 0},
+ {0x1CE4, 1, 0, 0},
+ {0x1CE5, 1, 0, 0},
+ {0x1CE6, 1, 0, 0},
+ {0x1CE7, 1, 0, 0},
+ {0x1CE8, 1, 0, 0},
+ {0x1CED, 220, 0, 0},
+ {0x1CF4, 230, 0, 0},
+ {0x1CF8, 230, 0, 0},
+ {0x1CF9, 230, 0, 0},
+ {0x1D2C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0041},
+ {0x1D2D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x00C6},
+ {0x1D2E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0042},
+ {0x1D30, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0044},
+ {0x1D31, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0045},
+ {0x1D32, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x018E},
+ {0x1D33, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0047},
+ {0x1D34, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0048},
+ {0x1D35, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0049},
+ {0x1D36, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004A},
+ {0x1D37, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004B},
+ {0x1D38, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004C},
+ {0x1D39, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004D},
+ {0x1D3A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004E},
+ {0x1D3C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004F},
+ {0x1D3D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0222},
+ {0x1D3E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0050},
+ {0x1D3F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0052},
+ {0x1D40, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0054},
+ {0x1D41, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0055},
+ {0x1D42, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0057},
+ {0x1D43, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0061},
+ {0x1D44, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0250},
+ {0x1D45, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0251},
+ {0x1D46, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1D02},
+ {0x1D47, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0062},
+ {0x1D48, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0064},
+ {0x1D49, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0065},
+ {0x1D4A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0259},
+ {0x1D4B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x025B},
+ {0x1D4C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x025C},
+ {0x1D4D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0067},
+ {0x1D4F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006B},
+ {0x1D50, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006D},
+ {0x1D51, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x014B},
+ {0x1D52, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006F},
+ {0x1D53, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0254},
+ {0x1D54, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1D16},
+ {0x1D55, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1D17},
+ {0x1D56, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0070},
+ {0x1D57, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0074},
+ {0x1D58, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0075},
+ {0x1D59, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1D1D},
+ {0x1D5A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x026F},
+ {0x1D5B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0076},
+ {0x1D5C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1D25},
+ {0x1D5D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B2},
+ {0x1D5E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B3},
+ {0x1D5F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B4},
+ {0x1D60, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C6},
+ {0x1D61, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C7},
+ {0x1D62, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0069},
+ {0x1D63, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0072},
+ {0x1D64, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0075},
+ {0x1D65, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0076},
+ {0x1D66, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B2},
+ {0x1D67, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B3},
+ {0x1D68, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C1},
+ {0x1D69, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C6},
+ {0x1D6A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C7},
+ {0x1D78, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x043D},
+ {0x1D9B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0252},
+ {0x1D9C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0063},
+ {0x1D9D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0255},
+ {0x1D9E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x00F0},
+ {0x1D9F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x025C},
+ {0x1DA0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0066},
+ {0x1DA1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x025F},
+ {0x1DA2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0261},
+ {0x1DA3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0265},
+ {0x1DA4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0268},
+ {0x1DA5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0269},
+ {0x1DA6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x026A},
+ {0x1DA7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1D7B},
+ {0x1DA8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x029D},
+ {0x1DA9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x026D},
+ {0x1DAA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1D85},
+ {0x1DAB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x029F},
+ {0x1DAC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0271},
+ {0x1DAD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0270},
+ {0x1DAE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0272},
+ {0x1DAF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0273},
+ {0x1DB0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0274},
+ {0x1DB1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0275},
+ {0x1DB2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0278},
+ {0x1DB3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0282},
+ {0x1DB4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0283},
+ {0x1DB5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x01AB},
+ {0x1DB6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0289},
+ {0x1DB7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x028A},
+ {0x1DB8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1D1C},
+ {0x1DB9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x028B},
+ {0x1DBA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x028C},
+ {0x1DBB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007A},
+ {0x1DBC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0290},
+ {0x1DBD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0291},
+ {0x1DBE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0292},
+ {0x1DBF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B8},
+ {0x1DC0, 230, 0, 0},
+ {0x1DC1, 230, 0, 0},
+ {0x1DC2, 220, 0, 0},
+ {0x1DC3, 230, 0, 0},
+ {0x1DC4, 230, 0, 0},
+ {0x1DC5, 230, 0, 0},
+ {0x1DC6, 230, 0, 0},
+ {0x1DC7, 230, 0, 0},
+ {0x1DC8, 230, 0, 0},
+ {0x1DC9, 230, 0, 0},
+ {0x1DCA, 220, 0, 0},
+ {0x1DCB, 230, 0, 0},
+ {0x1DCC, 230, 0, 0},
+ {0x1DCD, 234, 0, 0},
+ {0x1DCE, 214, 0, 0},
+ {0x1DCF, 220, 0, 0},
+ {0x1DD0, 202, 0, 0},
+ {0x1DD1, 230, 0, 0},
+ {0x1DD2, 230, 0, 0},
+ {0x1DD3, 230, 0, 0},
+ {0x1DD4, 230, 0, 0},
+ {0x1DD5, 230, 0, 0},
+ {0x1DD6, 230, 0, 0},
+ {0x1DD7, 230, 0, 0},
+ {0x1DD8, 230, 0, 0},
+ {0x1DD9, 230, 0, 0},
+ {0x1DDA, 230, 0, 0},
+ {0x1DDB, 230, 0, 0},
+ {0x1DDC, 230, 0, 0},
+ {0x1DDD, 230, 0, 0},
+ {0x1DDE, 230, 0, 0},
+ {0x1DDF, 230, 0, 0},
+ {0x1DE0, 230, 0, 0},
+ {0x1DE1, 230, 0, 0},
+ {0x1DE2, 230, 0, 0},
+ {0x1DE3, 230, 0, 0},
+ {0x1DE4, 230, 0, 0},
+ {0x1DE5, 230, 0, 0},
+ {0x1DE6, 230, 0, 0},
+ {0x1DE7, 230, 0, 0},
+ {0x1DE8, 230, 0, 0},
+ {0x1DE9, 230, 0, 0},
+ {0x1DEA, 230, 0, 0},
+ {0x1DEB, 230, 0, 0},
+ {0x1DEC, 230, 0, 0},
+ {0x1DED, 230, 0, 0},
+ {0x1DEE, 230, 0, 0},
+ {0x1DEF, 230, 0, 0},
+ {0x1DF0, 230, 0, 0},
+ {0x1DF1, 230, 0, 0},
+ {0x1DF2, 230, 0, 0},
+ {0x1DF3, 230, 0, 0},
+ {0x1DF4, 230, 0, 0},
+ {0x1DF5, 230, 0, 0},
+ {0x1DF6, 232, 0, 0},
+ {0x1DF7, 228, 0, 0},
+ {0x1DF8, 228, 0, 0},
+ {0x1DF9, 220, 0, 0},
+ {0x1DFA, 218, 0, 0},
+ {0x1DFB, 230, 0, 0},
+ {0x1DFC, 233, 0, 0},
+ {0x1DFD, 220, 0, 0},
+ {0x1DFE, 230, 0, 0},
+ {0x1DFF, 220, 0, 0},
+ {0x1E00, 0, 2, 907},
+ {0x1E01, 0, 2, 909},
+ {0x1E02, 0, 2, 911},
+ {0x1E03, 0, 2, 913},
+ {0x1E04, 0, 2, 915},
+ {0x1E05, 0, 2, 917},
+ {0x1E06, 0, 2, 919},
+ {0x1E07, 0, 2, 921},
+ {0x1E08, 0, 2, 923},
+ {0x1E09, 0, 2, 925},
+ {0x1E0A, 0, 2, 927},
+ {0x1E0B, 0, 2, 929},
+ {0x1E0C, 0, 2, 931},
+ {0x1E0D, 0, 2, 933},
+ {0x1E0E, 0, 2, 935},
+ {0x1E0F, 0, 2, 937},
+ {0x1E10, 0, 2, 939},
+ {0x1E11, 0, 2, 941},
+ {0x1E12, 0, 2, 943},
+ {0x1E13, 0, 2, 945},
+ {0x1E14, 0, 2, 947},
+ {0x1E15, 0, 2, 949},
+ {0x1E16, 0, 2, 951},
+ {0x1E17, 0, 2, 953},
+ {0x1E18, 0, 2, 955},
+ {0x1E19, 0, 2, 957},
+ {0x1E1A, 0, 2, 959},
+ {0x1E1B, 0, 2, 961},
+ {0x1E1C, 0, 2, 963},
+ {0x1E1D, 0, 2, 965},
+ {0x1E1E, 0, 2, 967},
+ {0x1E1F, 0, 2, 969},
+ {0x1E20, 0, 2, 971},
+ {0x1E21, 0, 2, 973},
+ {0x1E22, 0, 2, 975},
+ {0x1E23, 0, 2, 977},
+ {0x1E24, 0, 2, 979},
+ {0x1E25, 0, 2, 981},
+ {0x1E26, 0, 2, 983},
+ {0x1E27, 0, 2, 985},
+ {0x1E28, 0, 2, 987},
+ {0x1E29, 0, 2, 989},
+ {0x1E2A, 0, 2, 991},
+ {0x1E2B, 0, 2, 993},
+ {0x1E2C, 0, 2, 995},
+ {0x1E2D, 0, 2, 997},
+ {0x1E2E, 0, 2, 999},
+ {0x1E2F, 0, 2, 1001},
+ {0x1E30, 0, 2, 1003},
+ {0x1E31, 0, 2, 1005},
+ {0x1E32, 0, 2, 1007},
+ {0x1E33, 0, 2, 1009},
+ {0x1E34, 0, 2, 1011},
+ {0x1E35, 0, 2, 1013},
+ {0x1E36, 0, 2, 1015},
+ {0x1E37, 0, 2, 1017},
+ {0x1E38, 0, 2, 1019},
+ {0x1E39, 0, 2, 1021},
+ {0x1E3A, 0, 2, 1023},
+ {0x1E3B, 0, 2, 1025},
+ {0x1E3C, 0, 2, 1027},
+ {0x1E3D, 0, 2, 1029},
+ {0x1E3E, 0, 2, 1031},
+ {0x1E3F, 0, 2, 1033},
+ {0x1E40, 0, 2, 1035},
+ {0x1E41, 0, 2, 1037},
+ {0x1E42, 0, 2, 1039},
+ {0x1E43, 0, 2, 1041},
+ {0x1E44, 0, 2, 1043},
+ {0x1E45, 0, 2, 1045},
+ {0x1E46, 0, 2, 1047},
+ {0x1E47, 0, 2, 1049},
+ {0x1E48, 0, 2, 1051},
+ {0x1E49, 0, 2, 1053},
+ {0x1E4A, 0, 2, 1055},
+ {0x1E4B, 0, 2, 1057},
+ {0x1E4C, 0, 2, 1059},
+ {0x1E4D, 0, 2, 1061},
+ {0x1E4E, 0, 2, 1063},
+ {0x1E4F, 0, 2, 1065},
+ {0x1E50, 0, 2, 1067},
+ {0x1E51, 0, 2, 1069},
+ {0x1E52, 0, 2, 1071},
+ {0x1E53, 0, 2, 1073},
+ {0x1E54, 0, 2, 1075},
+ {0x1E55, 0, 2, 1077},
+ {0x1E56, 0, 2, 1079},
+ {0x1E57, 0, 2, 1081},
+ {0x1E58, 0, 2, 1083},
+ {0x1E59, 0, 2, 1085},
+ {0x1E5A, 0, 2, 1087},
+ {0x1E5B, 0, 2, 1089},
+ {0x1E5C, 0, 2, 1091},
+ {0x1E5D, 0, 2, 1093},
+ {0x1E5E, 0, 2, 1095},
+ {0x1E5F, 0, 2, 1097},
+ {0x1E60, 0, 2, 1099},
+ {0x1E61, 0, 2, 1101},
+ {0x1E62, 0, 2, 1103},
+ {0x1E63, 0, 2, 1105},
+ {0x1E64, 0, 2, 1107},
+ {0x1E65, 0, 2, 1109},
+ {0x1E66, 0, 2, 1111},
+ {0x1E67, 0, 2, 1113},
+ {0x1E68, 0, 2, 1115},
+ {0x1E69, 0, 2, 1117},
+ {0x1E6A, 0, 2, 1119},
+ {0x1E6B, 0, 2, 1121},
+ {0x1E6C, 0, 2, 1123},
+ {0x1E6D, 0, 2, 1125},
+ {0x1E6E, 0, 2, 1127},
+ {0x1E6F, 0, 2, 1129},
+ {0x1E70, 0, 2, 1131},
+ {0x1E71, 0, 2, 1133},
+ {0x1E72, 0, 2, 1135},
+ {0x1E73, 0, 2, 1137},
+ {0x1E74, 0, 2, 1139},
+ {0x1E75, 0, 2, 1141},
+ {0x1E76, 0, 2, 1143},
+ {0x1E77, 0, 2, 1145},
+ {0x1E78, 0, 2, 1147},
+ {0x1E79, 0, 2, 1149},
+ {0x1E7A, 0, 2, 1151},
+ {0x1E7B, 0, 2, 1153},
+ {0x1E7C, 0, 2, 1155},
+ {0x1E7D, 0, 2, 1157},
+ {0x1E7E, 0, 2, 1159},
+ {0x1E7F, 0, 2, 1161},
+ {0x1E80, 0, 2, 1163},
+ {0x1E81, 0, 2, 1165},
+ {0x1E82, 0, 2, 1167},
+ {0x1E83, 0, 2, 1169},
+ {0x1E84, 0, 2, 1171},
+ {0x1E85, 0, 2, 1173},
+ {0x1E86, 0, 2, 1175},
+ {0x1E87, 0, 2, 1177},
+ {0x1E88, 0, 2, 1179},
+ {0x1E89, 0, 2, 1181},
+ {0x1E8A, 0, 2, 1183},
+ {0x1E8B, 0, 2, 1185},
+ {0x1E8C, 0, 2, 1187},
+ {0x1E8D, 0, 2, 1189},
+ {0x1E8E, 0, 2, 1191},
+ {0x1E8F, 0, 2, 1193},
+ {0x1E90, 0, 2, 1195},
+ {0x1E91, 0, 2, 1197},
+ {0x1E92, 0, 2, 1199},
+ {0x1E93, 0, 2, 1201},
+ {0x1E94, 0, 2, 1203},
+ {0x1E95, 0, 2, 1205},
+ {0x1E96, 0, 2, 1207},
+ {0x1E97, 0, 2, 1209},
+ {0x1E98, 0, 2, 1211},
+ {0x1E99, 0, 2, 1213},
+ {0x1E9A, 0, 2 | DECOMP_COMPAT, 1215},
+ {0x1E9B, 0, 2, 1217},
+ {0x1EA0, 0, 2, 1219},
+ {0x1EA1, 0, 2, 1221},
+ {0x1EA2, 0, 2, 1223},
+ {0x1EA3, 0, 2, 1225},
+ {0x1EA4, 0, 2, 1227},
+ {0x1EA5, 0, 2, 1229},
+ {0x1EA6, 0, 2, 1231},
+ {0x1EA7, 0, 2, 1233},
+ {0x1EA8, 0, 2, 1235},
+ {0x1EA9, 0, 2, 1237},
+ {0x1EAA, 0, 2, 1239},
+ {0x1EAB, 0, 2, 1241},
+ {0x1EAC, 0, 2, 1243},
+ {0x1EAD, 0, 2, 1245},
+ {0x1EAE, 0, 2, 1247},
+ {0x1EAF, 0, 2, 1249},
+ {0x1EB0, 0, 2, 1251},
+ {0x1EB1, 0, 2, 1253},
+ {0x1EB2, 0, 2, 1255},
+ {0x1EB3, 0, 2, 1257},
+ {0x1EB4, 0, 2, 1259},
+ {0x1EB5, 0, 2, 1261},
+ {0x1EB6, 0, 2, 1263},
+ {0x1EB7, 0, 2, 1265},
+ {0x1EB8, 0, 2, 1267},
+ {0x1EB9, 0, 2, 1269},
+ {0x1EBA, 0, 2, 1271},
+ {0x1EBB, 0, 2, 1273},
+ {0x1EBC, 0, 2, 1275},
+ {0x1EBD, 0, 2, 1277},
+ {0x1EBE, 0, 2, 1279},
+ {0x1EBF, 0, 2, 1281},
+ {0x1EC0, 0, 2, 1283},
+ {0x1EC1, 0, 2, 1285},
+ {0x1EC2, 0, 2, 1287},
+ {0x1EC3, 0, 2, 1289},
+ {0x1EC4, 0, 2, 1291},
+ {0x1EC5, 0, 2, 1293},
+ {0x1EC6, 0, 2, 1295},
+ {0x1EC7, 0, 2, 1297},
+ {0x1EC8, 0, 2, 1299},
+ {0x1EC9, 0, 2, 1301},
+ {0x1ECA, 0, 2, 1303},
+ {0x1ECB, 0, 2, 1305},
+ {0x1ECC, 0, 2, 1307},
+ {0x1ECD, 0, 2, 1309},
+ {0x1ECE, 0, 2, 1311},
+ {0x1ECF, 0, 2, 1313},
+ {0x1ED0, 0, 2, 1315},
+ {0x1ED1, 0, 2, 1317},
+ {0x1ED2, 0, 2, 1319},
+ {0x1ED3, 0, 2, 1321},
+ {0x1ED4, 0, 2, 1323},
+ {0x1ED5, 0, 2, 1325},
+ {0x1ED6, 0, 2, 1327},
+ {0x1ED7, 0, 2, 1329},
+ {0x1ED8, 0, 2, 1331},
+ {0x1ED9, 0, 2, 1333},
+ {0x1EDA, 0, 2, 1335},
+ {0x1EDB, 0, 2, 1337},
+ {0x1EDC, 0, 2, 1339},
+ {0x1EDD, 0, 2, 1341},
+ {0x1EDE, 0, 2, 1343},
+ {0x1EDF, 0, 2, 1345},
+ {0x1EE0, 0, 2, 1347},
+ {0x1EE1, 0, 2, 1349},
+ {0x1EE2, 0, 2, 1351},
+ {0x1EE3, 0, 2, 1353},
+ {0x1EE4, 0, 2, 1355},
+ {0x1EE5, 0, 2, 1357},
+ {0x1EE6, 0, 2, 1359},
+ {0x1EE7, 0, 2, 1361},
+ {0x1EE8, 0, 2, 1363},
+ {0x1EE9, 0, 2, 1365},
+ {0x1EEA, 0, 2, 1367},
+ {0x1EEB, 0, 2, 1369},
+ {0x1EEC, 0, 2, 1371},
+ {0x1EED, 0, 2, 1373},
+ {0x1EEE, 0, 2, 1375},
+ {0x1EEF, 0, 2, 1377},
+ {0x1EF0, 0, 2, 1379},
+ {0x1EF1, 0, 2, 1381},
+ {0x1EF2, 0, 2, 1383},
+ {0x1EF3, 0, 2, 1385},
+ {0x1EF4, 0, 2, 1387},
+ {0x1EF5, 0, 2, 1389},
+ {0x1EF6, 0, 2, 1391},
+ {0x1EF7, 0, 2, 1393},
+ {0x1EF8, 0, 2, 1395},
+ {0x1EF9, 0, 2, 1397},
+ {0x1F00, 0, 2, 1399},
+ {0x1F01, 0, 2, 1401},
+ {0x1F02, 0, 2, 1403},
+ {0x1F03, 0, 2, 1405},
+ {0x1F04, 0, 2, 1407},
+ {0x1F05, 0, 2, 1409},
+ {0x1F06, 0, 2, 1411},
+ {0x1F07, 0, 2, 1413},
+ {0x1F08, 0, 2, 1415},
+ {0x1F09, 0, 2, 1417},
+ {0x1F0A, 0, 2, 1419},
+ {0x1F0B, 0, 2, 1421},
+ {0x1F0C, 0, 2, 1423},
+ {0x1F0D, 0, 2, 1425},
+ {0x1F0E, 0, 2, 1427},
+ {0x1F0F, 0, 2, 1429},
+ {0x1F10, 0, 2, 1431},
+ {0x1F11, 0, 2, 1433},
+ {0x1F12, 0, 2, 1435},
+ {0x1F13, 0, 2, 1437},
+ {0x1F14, 0, 2, 1439},
+ {0x1F15, 0, 2, 1441},
+ {0x1F18, 0, 2, 1443},
+ {0x1F19, 0, 2, 1445},
+ {0x1F1A, 0, 2, 1447},
+ {0x1F1B, 0, 2, 1449},
+ {0x1F1C, 0, 2, 1451},
+ {0x1F1D, 0, 2, 1453},
+ {0x1F20, 0, 2, 1455},
+ {0x1F21, 0, 2, 1457},
+ {0x1F22, 0, 2, 1459},
+ {0x1F23, 0, 2, 1461},
+ {0x1F24, 0, 2, 1463},
+ {0x1F25, 0, 2, 1465},
+ {0x1F26, 0, 2, 1467},
+ {0x1F27, 0, 2, 1469},
+ {0x1F28, 0, 2, 1471},
+ {0x1F29, 0, 2, 1473},
+ {0x1F2A, 0, 2, 1475},
+ {0x1F2B, 0, 2, 1477},
+ {0x1F2C, 0, 2, 1479},
+ {0x1F2D, 0, 2, 1481},
+ {0x1F2E, 0, 2, 1483},
+ {0x1F2F, 0, 2, 1485},
+ {0x1F30, 0, 2, 1487},
+ {0x1F31, 0, 2, 1489},
+ {0x1F32, 0, 2, 1491},
+ {0x1F33, 0, 2, 1493},
+ {0x1F34, 0, 2, 1495},
+ {0x1F35, 0, 2, 1497},
+ {0x1F36, 0, 2, 1499},
+ {0x1F37, 0, 2, 1501},
+ {0x1F38, 0, 2, 1503},
+ {0x1F39, 0, 2, 1505},
+ {0x1F3A, 0, 2, 1507},
+ {0x1F3B, 0, 2, 1509},
+ {0x1F3C, 0, 2, 1511},
+ {0x1F3D, 0, 2, 1513},
+ {0x1F3E, 0, 2, 1515},
+ {0x1F3F, 0, 2, 1517},
+ {0x1F40, 0, 2, 1519},
+ {0x1F41, 0, 2, 1521},
+ {0x1F42, 0, 2, 1523},
+ {0x1F43, 0, 2, 1525},
+ {0x1F44, 0, 2, 1527},
+ {0x1F45, 0, 2, 1529},
+ {0x1F48, 0, 2, 1531},
+ {0x1F49, 0, 2, 1533},
+ {0x1F4A, 0, 2, 1535},
+ {0x1F4B, 0, 2, 1537},
+ {0x1F4C, 0, 2, 1539},
+ {0x1F4D, 0, 2, 1541},
+ {0x1F50, 0, 2, 1543},
+ {0x1F51, 0, 2, 1545},
+ {0x1F52, 0, 2, 1547},
+ {0x1F53, 0, 2, 1549},
+ {0x1F54, 0, 2, 1551},
+ {0x1F55, 0, 2, 1553},
+ {0x1F56, 0, 2, 1555},
+ {0x1F57, 0, 2, 1557},
+ {0x1F59, 0, 2, 1559},
+ {0x1F5B, 0, 2, 1561},
+ {0x1F5D, 0, 2, 1563},
+ {0x1F5F, 0, 2, 1565},
+ {0x1F60, 0, 2, 1567},
+ {0x1F61, 0, 2, 1569},
+ {0x1F62, 0, 2, 1571},
+ {0x1F63, 0, 2, 1573},
+ {0x1F64, 0, 2, 1575},
+ {0x1F65, 0, 2, 1577},
+ {0x1F66, 0, 2, 1579},
+ {0x1F67, 0, 2, 1581},
+ {0x1F68, 0, 2, 1583},
+ {0x1F69, 0, 2, 1585},
+ {0x1F6A, 0, 2, 1587},
+ {0x1F6B, 0, 2, 1589},
+ {0x1F6C, 0, 2, 1591},
+ {0x1F6D, 0, 2, 1593},
+ {0x1F6E, 0, 2, 1595},
+ {0x1F6F, 0, 2, 1597},
+ {0x1F70, 0, 2, 1599},
+ {0x1F71, 0, 1 | DECOMP_INLINE, 0x03AC},
+ {0x1F72, 0, 2, 1601},
+ {0x1F73, 0, 1 | DECOMP_INLINE, 0x03AD},
+ {0x1F74, 0, 2, 1603},
+ {0x1F75, 0, 1 | DECOMP_INLINE, 0x03AE},
+ {0x1F76, 0, 2, 1605},
+ {0x1F77, 0, 1 | DECOMP_INLINE, 0x03AF},
+ {0x1F78, 0, 2, 1607},
+ {0x1F79, 0, 1 | DECOMP_INLINE, 0x03CC},
+ {0x1F7A, 0, 2, 1609},
+ {0x1F7B, 0, 1 | DECOMP_INLINE, 0x03CD},
+ {0x1F7C, 0, 2, 1611},
+ {0x1F7D, 0, 1 | DECOMP_INLINE, 0x03CE},
+ {0x1F80, 0, 2, 1613},
+ {0x1F81, 0, 2, 1615},
+ {0x1F82, 0, 2, 1617},
+ {0x1F83, 0, 2, 1619},
+ {0x1F84, 0, 2, 1621},
+ {0x1F85, 0, 2, 1623},
+ {0x1F86, 0, 2, 1625},
+ {0x1F87, 0, 2, 1627},
+ {0x1F88, 0, 2, 1629},
+ {0x1F89, 0, 2, 1631},
+ {0x1F8A, 0, 2, 1633},
+ {0x1F8B, 0, 2, 1635},
+ {0x1F8C, 0, 2, 1637},
+ {0x1F8D, 0, 2, 1639},
+ {0x1F8E, 0, 2, 1641},
+ {0x1F8F, 0, 2, 1643},
+ {0x1F90, 0, 2, 1645},
+ {0x1F91, 0, 2, 1647},
+ {0x1F92, 0, 2, 1649},
+ {0x1F93, 0, 2, 1651},
+ {0x1F94, 0, 2, 1653},
+ {0x1F95, 0, 2, 1655},
+ {0x1F96, 0, 2, 1657},
+ {0x1F97, 0, 2, 1659},
+ {0x1F98, 0, 2, 1661},
+ {0x1F99, 0, 2, 1663},
+ {0x1F9A, 0, 2, 1665},
+ {0x1F9B, 0, 2, 1667},
+ {0x1F9C, 0, 2, 1669},
+ {0x1F9D, 0, 2, 1671},
+ {0x1F9E, 0, 2, 1673},
+ {0x1F9F, 0, 2, 1675},
+ {0x1FA0, 0, 2, 1677},
+ {0x1FA1, 0, 2, 1679},
+ {0x1FA2, 0, 2, 1681},
+ {0x1FA3, 0, 2, 1683},
+ {0x1FA4, 0, 2, 1685},
+ {0x1FA5, 0, 2, 1687},
+ {0x1FA6, 0, 2, 1689},
+ {0x1FA7, 0, 2, 1691},
+ {0x1FA8, 0, 2, 1693},
+ {0x1FA9, 0, 2, 1695},
+ {0x1FAA, 0, 2, 1697},
+ {0x1FAB, 0, 2, 1699},
+ {0x1FAC, 0, 2, 1701},
+ {0x1FAD, 0, 2, 1703},
+ {0x1FAE, 0, 2, 1705},
+ {0x1FAF, 0, 2, 1707},
+ {0x1FB0, 0, 2, 1709},
+ {0x1FB1, 0, 2, 1711},
+ {0x1FB2, 0, 2, 1713},
+ {0x1FB3, 0, 2, 1715},
+ {0x1FB4, 0, 2, 1717},
+ {0x1FB6, 0, 2, 1719},
+ {0x1FB7, 0, 2, 1721},
+ {0x1FB8, 0, 2, 1723},
+ {0x1FB9, 0, 2, 1725},
+ {0x1FBA, 0, 2, 1727},
+ {0x1FBB, 0, 1 | DECOMP_INLINE, 0x0386},
+ {0x1FBC, 0, 2, 1729},
+ {0x1FBD, 0, 2 | DECOMP_COMPAT, 1731},
+ {0x1FBE, 0, 1 | DECOMP_INLINE, 0x03B9},
+ {0x1FBF, 0, 2 | DECOMP_COMPAT, 1733},
+ {0x1FC0, 0, 2 | DECOMP_COMPAT, 1735},
+ {0x1FC1, 0, 2, 1737},
+ {0x1FC2, 0, 2, 1739},
+ {0x1FC3, 0, 2, 1741},
+ {0x1FC4, 0, 2, 1743},
+ {0x1FC6, 0, 2, 1745},
+ {0x1FC7, 0, 2, 1747},
+ {0x1FC8, 0, 2, 1749},
+ {0x1FC9, 0, 1 | DECOMP_INLINE, 0x0388},
+ {0x1FCA, 0, 2, 1751},
+ {0x1FCB, 0, 1 | DECOMP_INLINE, 0x0389},
+ {0x1FCC, 0, 2, 1753},
+ {0x1FCD, 0, 2, 1755},
+ {0x1FCE, 0, 2, 1757},
+ {0x1FCF, 0, 2, 1759},
+ {0x1FD0, 0, 2, 1761},
+ {0x1FD1, 0, 2, 1763},
+ {0x1FD2, 0, 2, 1765},
+ {0x1FD3, 0, 1 | DECOMP_INLINE, 0x0390},
+ {0x1FD6, 0, 2, 1767},
+ {0x1FD7, 0, 2, 1769},
+ {0x1FD8, 0, 2, 1771},
+ {0x1FD9, 0, 2, 1773},
+ {0x1FDA, 0, 2, 1775},
+ {0x1FDB, 0, 1 | DECOMP_INLINE, 0x038A},
+ {0x1FDD, 0, 2, 1777},
+ {0x1FDE, 0, 2, 1779},
+ {0x1FDF, 0, 2, 1781},
+ {0x1FE0, 0, 2, 1783},
+ {0x1FE1, 0, 2, 1785},
+ {0x1FE2, 0, 2, 1787},
+ {0x1FE3, 0, 1 | DECOMP_INLINE, 0x03B0},
+ {0x1FE4, 0, 2, 1789},
+ {0x1FE5, 0, 2, 1791},
+ {0x1FE6, 0, 2, 1793},
+ {0x1FE7, 0, 2, 1795},
+ {0x1FE8, 0, 2, 1797},
+ {0x1FE9, 0, 2, 1799},
+ {0x1FEA, 0, 2, 1801},
+ {0x1FEB, 0, 1 | DECOMP_INLINE, 0x038E},
+ {0x1FEC, 0, 2, 1803},
+ {0x1FED, 0, 2, 1805},
+ {0x1FEE, 0, 1 | DECOMP_INLINE, 0x0385},
+ {0x1FEF, 0, 1 | DECOMP_INLINE, 0x0060},
+ {0x1FF2, 0, 2, 1807},
+ {0x1FF3, 0, 2, 1809},
+ {0x1FF4, 0, 2, 1811},
+ {0x1FF6, 0, 2, 1813},
+ {0x1FF7, 0, 2, 1815},
+ {0x1FF8, 0, 2, 1817},
+ {0x1FF9, 0, 1 | DECOMP_INLINE, 0x038C},
+ {0x1FFA, 0, 2, 1819},
+ {0x1FFB, 0, 1 | DECOMP_INLINE, 0x038F},
+ {0x1FFC, 0, 2, 1821},
+ {0x1FFD, 0, 1 | DECOMP_INLINE, 0x00B4},
+ {0x1FFE, 0, 2 | DECOMP_COMPAT, 1823},
+ {0x2000, 0, 1 | DECOMP_INLINE, 0x2002},
+ {0x2001, 0, 1 | DECOMP_INLINE, 0x2003},
+ {0x2002, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0020},
+ {0x2003, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0020},
+ {0x2004, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0020},
+ {0x2005, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0020},
+ {0x2006, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0020},
+ {0x2007, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0020},
+ {0x2008, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0020},
+ {0x2009, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0020},
+ {0x200A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0020},
+ {0x2011, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2010},
+ {0x2017, 0, 2 | DECOMP_COMPAT, 1825},
+ {0x2024, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x002E},
+ {0x2025, 0, 2 | DECOMP_COMPAT, 1827},
+ {0x2026, 0, 3 | DECOMP_COMPAT, 1829},
+ {0x202F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0020},
+ {0x2033, 0, 2 | DECOMP_COMPAT, 1832},
+ {0x2034, 0, 3 | DECOMP_COMPAT, 1834},
+ {0x2036, 0, 2 | DECOMP_COMPAT, 1837},
+ {0x2037, 0, 3 | DECOMP_COMPAT, 1839},
+ {0x203C, 0, 2 | DECOMP_COMPAT, 1842},
+ {0x203E, 0, 2 | DECOMP_COMPAT, 1844},
+ {0x2047, 0, 2 | DECOMP_COMPAT, 1846},
+ {0x2048, 0, 2 | DECOMP_COMPAT, 1848},
+ {0x2049, 0, 2 | DECOMP_COMPAT, 1850},
+ {0x2057, 0, 4 | DECOMP_COMPAT, 1852},
+ {0x205F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0020},
+ {0x2070, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0030},
+ {0x2071, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0069},
+ {0x2074, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0034},
+ {0x2075, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0035},
+ {0x2076, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0036},
+ {0x2077, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0037},
+ {0x2078, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0038},
+ {0x2079, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0039},
+ {0x207A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x002B},
+ {0x207B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2212},
+ {0x207C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x003D},
+ {0x207D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0028},
+ {0x207E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0029},
+ {0x207F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006E},
+ {0x2080, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0030},
+ {0x2081, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0031},
+ {0x2082, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0032},
+ {0x2083, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0033},
+ {0x2084, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0034},
+ {0x2085, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0035},
+ {0x2086, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0036},
+ {0x2087, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0037},
+ {0x2088, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0038},
+ {0x2089, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0039},
+ {0x208A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x002B},
+ {0x208B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2212},
+ {0x208C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x003D},
+ {0x208D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0028},
+ {0x208E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0029},
+ {0x2090, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0061},
+ {0x2091, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0065},
+ {0x2092, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006F},
+ {0x2093, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0078},
+ {0x2094, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0259},
+ {0x2095, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0068},
+ {0x2096, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006B},
+ {0x2097, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006C},
+ {0x2098, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006D},
+ {0x2099, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006E},
+ {0x209A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0070},
+ {0x209B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0073},
+ {0x209C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0074},
+ {0x20A8, 0, 2 | DECOMP_COMPAT, 1856},
+ {0x20D0, 230, 0, 0},
+ {0x20D1, 230, 0, 0},
+ {0x20D2, 1, 0, 0},
+ {0x20D3, 1, 0, 0},
+ {0x20D4, 230, 0, 0},
+ {0x20D5, 230, 0, 0},
+ {0x20D6, 230, 0, 0},
+ {0x20D7, 230, 0, 0},
+ {0x20D8, 1, 0, 0},
+ {0x20D9, 1, 0, 0},
+ {0x20DA, 1, 0, 0},
+ {0x20DB, 230, 0, 0},
+ {0x20DC, 230, 0, 0},
+ {0x20E1, 230, 0, 0},
+ {0x20E5, 1, 0, 0},
+ {0x20E6, 1, 0, 0},
+ {0x20E7, 230, 0, 0},
+ {0x20E8, 220, 0, 0},
+ {0x20E9, 230, 0, 0},
+ {0x20EA, 1, 0, 0},
+ {0x20EB, 1, 0, 0},
+ {0x20EC, 220, 0, 0},
+ {0x20ED, 220, 0, 0},
+ {0x20EE, 220, 0, 0},
+ {0x20EF, 220, 0, 0},
+ {0x20F0, 230, 0, 0},
+ {0x2100, 0, 3 | DECOMP_COMPAT, 1858},
+ {0x2101, 0, 3 | DECOMP_COMPAT, 1861},
+ {0x2102, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0043},
+ {0x2103, 0, 2 | DECOMP_COMPAT, 1864},
+ {0x2105, 0, 3 | DECOMP_COMPAT, 1866},
+ {0x2106, 0, 3 | DECOMP_COMPAT, 1869},
+ {0x2107, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0190},
+ {0x2109, 0, 2 | DECOMP_COMPAT, 1872},
+ {0x210A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0067},
+ {0x210B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0048},
+ {0x210C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0048},
+ {0x210D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0048},
+ {0x210E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0068},
+ {0x210F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0127},
+ {0x2110, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0049},
+ {0x2111, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0049},
+ {0x2112, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004C},
+ {0x2113, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006C},
+ {0x2115, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004E},
+ {0x2116, 0, 2 | DECOMP_COMPAT, 1874},
+ {0x2119, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0050},
+ {0x211A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0051},
+ {0x211B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0052},
+ {0x211C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0052},
+ {0x211D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0052},
+ {0x2120, 0, 2 | DECOMP_COMPAT, 1876},
+ {0x2121, 0, 3 | DECOMP_COMPAT, 1878},
+ {0x2122, 0, 2 | DECOMP_COMPAT, 1881},
+ {0x2124, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005A},
+ {0x2126, 0, 1 | DECOMP_INLINE, 0x03A9},
+ {0x2128, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005A},
+ {0x212A, 0, 1 | DECOMP_INLINE, 0x004B},
+ {0x212B, 0, 1 | DECOMP_INLINE, 0x00C5},
+ {0x212C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0042},
+ {0x212D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0043},
+ {0x212F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0065},
+ {0x2130, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0045},
+ {0x2131, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0046},
+ {0x2133, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004D},
+ {0x2134, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006F},
+ {0x2135, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x05D0},
+ {0x2136, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x05D1},
+ {0x2137, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x05D2},
+ {0x2138, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x05D3},
+ {0x2139, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0069},
+ {0x213B, 0, 3 | DECOMP_COMPAT, 1883},
+ {0x213C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C0},
+ {0x213D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B3},
+ {0x213E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0393},
+ {0x213F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A0},
+ {0x2140, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2211},
+ {0x2145, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0044},
+ {0x2146, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0064},
+ {0x2147, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0065},
+ {0x2148, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0069},
+ {0x2149, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006A},
+ {0x2150, 0, 3 | DECOMP_COMPAT, 1886},
+ {0x2151, 0, 3 | DECOMP_COMPAT, 1889},
+ {0x2152, 0, 4 | DECOMP_COMPAT, 1892},
+ {0x2153, 0, 3 | DECOMP_COMPAT, 1896},
+ {0x2154, 0, 3 | DECOMP_COMPAT, 1899},
+ {0x2155, 0, 3 | DECOMP_COMPAT, 1902},
+ {0x2156, 0, 3 | DECOMP_COMPAT, 1905},
+ {0x2157, 0, 3 | DECOMP_COMPAT, 1908},
+ {0x2158, 0, 3 | DECOMP_COMPAT, 1911},
+ {0x2159, 0, 3 | DECOMP_COMPAT, 1914},
+ {0x215A, 0, 3 | DECOMP_COMPAT, 1917},
+ {0x215B, 0, 3 | DECOMP_COMPAT, 1920},
+ {0x215C, 0, 3 | DECOMP_COMPAT, 1923},
+ {0x215D, 0, 3 | DECOMP_COMPAT, 1926},
+ {0x215E, 0, 3 | DECOMP_COMPAT, 1929},
+ {0x215F, 0, 2 | DECOMP_COMPAT, 1932},
+ {0x2160, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0049},
+ {0x2161, 0, 2 | DECOMP_COMPAT, 1934},
+ {0x2162, 0, 3 | DECOMP_COMPAT, 1936},
+ {0x2163, 0, 2 | DECOMP_COMPAT, 1939},
+ {0x2164, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0056},
+ {0x2165, 0, 2 | DECOMP_COMPAT, 1941},
+ {0x2166, 0, 3 | DECOMP_COMPAT, 1943},
+ {0x2167, 0, 4 | DECOMP_COMPAT, 1946},
+ {0x2168, 0, 2 | DECOMP_COMPAT, 1950},
+ {0x2169, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0058},
+ {0x216A, 0, 2 | DECOMP_COMPAT, 1952},
+ {0x216B, 0, 3 | DECOMP_COMPAT, 1954},
+ {0x216C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004C},
+ {0x216D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0043},
+ {0x216E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0044},
+ {0x216F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004D},
+ {0x2170, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0069},
+ {0x2171, 0, 2 | DECOMP_COMPAT, 1957},
+ {0x2172, 0, 3 | DECOMP_COMPAT, 1959},
+ {0x2173, 0, 2 | DECOMP_COMPAT, 1962},
+ {0x2174, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0076},
+ {0x2175, 0, 2 | DECOMP_COMPAT, 1964},
+ {0x2176, 0, 3 | DECOMP_COMPAT, 1966},
+ {0x2177, 0, 4 | DECOMP_COMPAT, 1969},
+ {0x2178, 0, 2 | DECOMP_COMPAT, 1973},
+ {0x2179, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0078},
+ {0x217A, 0, 2 | DECOMP_COMPAT, 1975},
+ {0x217B, 0, 3 | DECOMP_COMPAT, 1977},
+ {0x217C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006C},
+ {0x217D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0063},
+ {0x217E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0064},
+ {0x217F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006D},
+ {0x2189, 0, 3 | DECOMP_COMPAT, 1980},
+ {0x219A, 0, 2, 1983},
+ {0x219B, 0, 2, 1985},
+ {0x21AE, 0, 2, 1987},
+ {0x21CD, 0, 2, 1989},
+ {0x21CE, 0, 2, 1991},
+ {0x21CF, 0, 2, 1993},
+ {0x2204, 0, 2, 1995},
+ {0x2209, 0, 2, 1997},
+ {0x220C, 0, 2, 1999},
+ {0x2224, 0, 2, 2001},
+ {0x2226, 0, 2, 2003},
+ {0x222C, 0, 2 | DECOMP_COMPAT, 2005},
+ {0x222D, 0, 3 | DECOMP_COMPAT, 2007},
+ {0x222F, 0, 2 | DECOMP_COMPAT, 2010},
+ {0x2230, 0, 3 | DECOMP_COMPAT, 2012},
+ {0x2241, 0, 2, 2015},
+ {0x2244, 0, 2, 2017},
+ {0x2247, 0, 2, 2019},
+ {0x2249, 0, 2, 2021},
+ {0x2260, 0, 2, 2023},
+ {0x2262, 0, 2, 2025},
+ {0x226D, 0, 2, 2027},
+ {0x226E, 0, 2, 2029},
+ {0x226F, 0, 2, 2031},
+ {0x2270, 0, 2, 2033},
+ {0x2271, 0, 2, 2035},
+ {0x2274, 0, 2, 2037},
+ {0x2275, 0, 2, 2039},
+ {0x2278, 0, 2, 2041},
+ {0x2279, 0, 2, 2043},
+ {0x2280, 0, 2, 2045},
+ {0x2281, 0, 2, 2047},
+ {0x2284, 0, 2, 2049},
+ {0x2285, 0, 2, 2051},
+ {0x2288, 0, 2, 2053},
+ {0x2289, 0, 2, 2055},
+ {0x22AC, 0, 2, 2057},
+ {0x22AD, 0, 2, 2059},
+ {0x22AE, 0, 2, 2061},
+ {0x22AF, 0, 2, 2063},
+ {0x22E0, 0, 2, 2065},
+ {0x22E1, 0, 2, 2067},
+ {0x22E2, 0, 2, 2069},
+ {0x22E3, 0, 2, 2071},
+ {0x22EA, 0, 2, 2073},
+ {0x22EB, 0, 2, 2075},
+ {0x22EC, 0, 2, 2077},
+ {0x22ED, 0, 2, 2079},
+ {0x2329, 0, 1 | DECOMP_INLINE, 0x3008},
+ {0x232A, 0, 1 | DECOMP_INLINE, 0x3009},
+ {0x2460, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0031},
+ {0x2461, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0032},
+ {0x2462, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0033},
+ {0x2463, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0034},
+ {0x2464, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0035},
+ {0x2465, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0036},
+ {0x2466, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0037},
+ {0x2467, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0038},
+ {0x2468, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0039},
+ {0x2469, 0, 2 | DECOMP_COMPAT, 2081},
+ {0x246A, 0, 2 | DECOMP_COMPAT, 2083},
+ {0x246B, 0, 2 | DECOMP_COMPAT, 2085},
+ {0x246C, 0, 2 | DECOMP_COMPAT, 2087},
+ {0x246D, 0, 2 | DECOMP_COMPAT, 2089},
+ {0x246E, 0, 2 | DECOMP_COMPAT, 2091},
+ {0x246F, 0, 2 | DECOMP_COMPAT, 2093},
+ {0x2470, 0, 2 | DECOMP_COMPAT, 2095},
+ {0x2471, 0, 2 | DECOMP_COMPAT, 2097},
+ {0x2472, 0, 2 | DECOMP_COMPAT, 2099},
+ {0x2473, 0, 2 | DECOMP_COMPAT, 2101},
+ {0x2474, 0, 3 | DECOMP_COMPAT, 2103},
+ {0x2475, 0, 3 | DECOMP_COMPAT, 2106},
+ {0x2476, 0, 3 | DECOMP_COMPAT, 2109},
+ {0x2477, 0, 3 | DECOMP_COMPAT, 2112},
+ {0x2478, 0, 3 | DECOMP_COMPAT, 2115},
+ {0x2479, 0, 3 | DECOMP_COMPAT, 2118},
+ {0x247A, 0, 3 | DECOMP_COMPAT, 2121},
+ {0x247B, 0, 3 | DECOMP_COMPAT, 2124},
+ {0x247C, 0, 3 | DECOMP_COMPAT, 2127},
+ {0x247D, 0, 4 | DECOMP_COMPAT, 2130},
+ {0x247E, 0, 4 | DECOMP_COMPAT, 2134},
+ {0x247F, 0, 4 | DECOMP_COMPAT, 2138},
+ {0x2480, 0, 4 | DECOMP_COMPAT, 2142},
+ {0x2481, 0, 4 | DECOMP_COMPAT, 2146},
+ {0x2482, 0, 4 | DECOMP_COMPAT, 2150},
+ {0x2483, 0, 4 | DECOMP_COMPAT, 2154},
+ {0x2484, 0, 4 | DECOMP_COMPAT, 2158},
+ {0x2485, 0, 4 | DECOMP_COMPAT, 2162},
+ {0x2486, 0, 4 | DECOMP_COMPAT, 2166},
+ {0x2487, 0, 4 | DECOMP_COMPAT, 2170},
+ {0x2488, 0, 2 | DECOMP_COMPAT, 2174},
+ {0x2489, 0, 2 | DECOMP_COMPAT, 2176},
+ {0x248A, 0, 2 | DECOMP_COMPAT, 2178},
+ {0x248B, 0, 2 | DECOMP_COMPAT, 2180},
+ {0x248C, 0, 2 | DECOMP_COMPAT, 2182},
+ {0x248D, 0, 2 | DECOMP_COMPAT, 2184},
+ {0x248E, 0, 2 | DECOMP_COMPAT, 2186},
+ {0x248F, 0, 2 | DECOMP_COMPAT, 2188},
+ {0x2490, 0, 2 | DECOMP_COMPAT, 2190},
+ {0x2491, 0, 3 | DECOMP_COMPAT, 2192},
+ {0x2492, 0, 3 | DECOMP_COMPAT, 2195},
+ {0x2493, 0, 3 | DECOMP_COMPAT, 2198},
+ {0x2494, 0, 3 | DECOMP_COMPAT, 2201},
+ {0x2495, 0, 3 | DECOMP_COMPAT, 2204},
+ {0x2496, 0, 3 | DECOMP_COMPAT, 2207},
+ {0x2497, 0, 3 | DECOMP_COMPAT, 2210},
+ {0x2498, 0, 3 | DECOMP_COMPAT, 2213},
+ {0x2499, 0, 3 | DECOMP_COMPAT, 2216},
+ {0x249A, 0, 3 | DECOMP_COMPAT, 2219},
+ {0x249B, 0, 3 | DECOMP_COMPAT, 2222},
+ {0x249C, 0, 3 | DECOMP_COMPAT, 2225},
+ {0x249D, 0, 3 | DECOMP_COMPAT, 2228},
+ {0x249E, 0, 3 | DECOMP_COMPAT, 2231},
+ {0x249F, 0, 3 | DECOMP_COMPAT, 2234},
+ {0x24A0, 0, 3 | DECOMP_COMPAT, 2237},
+ {0x24A1, 0, 3 | DECOMP_COMPAT, 2240},
+ {0x24A2, 0, 3 | DECOMP_COMPAT, 2243},
+ {0x24A3, 0, 3 | DECOMP_COMPAT, 2246},
+ {0x24A4, 0, 3 | DECOMP_COMPAT, 2249},
+ {0x24A5, 0, 3 | DECOMP_COMPAT, 2252},
+ {0x24A6, 0, 3 | DECOMP_COMPAT, 2255},
+ {0x24A7, 0, 3 | DECOMP_COMPAT, 2258},
+ {0x24A8, 0, 3 | DECOMP_COMPAT, 2261},
+ {0x24A9, 0, 3 | DECOMP_COMPAT, 2264},
+ {0x24AA, 0, 3 | DECOMP_COMPAT, 2267},
+ {0x24AB, 0, 3 | DECOMP_COMPAT, 2270},
+ {0x24AC, 0, 3 | DECOMP_COMPAT, 2273},
+ {0x24AD, 0, 3 | DECOMP_COMPAT, 2276},
+ {0x24AE, 0, 3 | DECOMP_COMPAT, 2279},
+ {0x24AF, 0, 3 | DECOMP_COMPAT, 2282},
+ {0x24B0, 0, 3 | DECOMP_COMPAT, 2285},
+ {0x24B1, 0, 3 | DECOMP_COMPAT, 2288},
+ {0x24B2, 0, 3 | DECOMP_COMPAT, 2291},
+ {0x24B3, 0, 3 | DECOMP_COMPAT, 2294},
+ {0x24B4, 0, 3 | DECOMP_COMPAT, 2297},
+ {0x24B5, 0, 3 | DECOMP_COMPAT, 2300},
+ {0x24B6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0041},
+ {0x24B7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0042},
+ {0x24B8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0043},
+ {0x24B9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0044},
+ {0x24BA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0045},
+ {0x24BB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0046},
+ {0x24BC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0047},
+ {0x24BD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0048},
+ {0x24BE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0049},
+ {0x24BF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004A},
+ {0x24C0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004B},
+ {0x24C1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004C},
+ {0x24C2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004D},
+ {0x24C3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004E},
+ {0x24C4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004F},
+ {0x24C5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0050},
+ {0x24C6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0051},
+ {0x24C7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0052},
+ {0x24C8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0053},
+ {0x24C9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0054},
+ {0x24CA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0055},
+ {0x24CB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0056},
+ {0x24CC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0057},
+ {0x24CD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0058},
+ {0x24CE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0059},
+ {0x24CF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005A},
+ {0x24D0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0061},
+ {0x24D1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0062},
+ {0x24D2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0063},
+ {0x24D3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0064},
+ {0x24D4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0065},
+ {0x24D5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0066},
+ {0x24D6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0067},
+ {0x24D7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0068},
+ {0x24D8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0069},
+ {0x24D9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006A},
+ {0x24DA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006B},
+ {0x24DB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006C},
+ {0x24DC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006D},
+ {0x24DD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006E},
+ {0x24DE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006F},
+ {0x24DF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0070},
+ {0x24E0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0071},
+ {0x24E1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0072},
+ {0x24E2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0073},
+ {0x24E3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0074},
+ {0x24E4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0075},
+ {0x24E5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0076},
+ {0x24E6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0077},
+ {0x24E7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0078},
+ {0x24E8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0079},
+ {0x24E9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007A},
+ {0x24EA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0030},
+ {0x2A0C, 0, 4 | DECOMP_COMPAT, 2303},
+ {0x2A74, 0, 3 | DECOMP_COMPAT, 2307},
+ {0x2A75, 0, 2 | DECOMP_COMPAT, 2310},
+ {0x2A76, 0, 3 | DECOMP_COMPAT, 2312},
+ {0x2ADC, 0, 2 | DECOMP_NO_COMPOSE, 2315}, /* in exclusion list */
+ {0x2C7C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006A},
+ {0x2C7D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0056},
+ {0x2CEF, 230, 0, 0},
+ {0x2CF0, 230, 0, 0},
+ {0x2CF1, 230, 0, 0},
+ {0x2D6F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2D61},
+ {0x2D7F, 9, 0, 0},
+ {0x2DE0, 230, 0, 0},
+ {0x2DE1, 230, 0, 0},
+ {0x2DE2, 230, 0, 0},
+ {0x2DE3, 230, 0, 0},
+ {0x2DE4, 230, 0, 0},
+ {0x2DE5, 230, 0, 0},
+ {0x2DE6, 230, 0, 0},
+ {0x2DE7, 230, 0, 0},
+ {0x2DE8, 230, 0, 0},
+ {0x2DE9, 230, 0, 0},
+ {0x2DEA, 230, 0, 0},
+ {0x2DEB, 230, 0, 0},
+ {0x2DEC, 230, 0, 0},
+ {0x2DED, 230, 0, 0},
+ {0x2DEE, 230, 0, 0},
+ {0x2DEF, 230, 0, 0},
+ {0x2DF0, 230, 0, 0},
+ {0x2DF1, 230, 0, 0},
+ {0x2DF2, 230, 0, 0},
+ {0x2DF3, 230, 0, 0},
+ {0x2DF4, 230, 0, 0},
+ {0x2DF5, 230, 0, 0},
+ {0x2DF6, 230, 0, 0},
+ {0x2DF7, 230, 0, 0},
+ {0x2DF8, 230, 0, 0},
+ {0x2DF9, 230, 0, 0},
+ {0x2DFA, 230, 0, 0},
+ {0x2DFB, 230, 0, 0},
+ {0x2DFC, 230, 0, 0},
+ {0x2DFD, 230, 0, 0},
+ {0x2DFE, 230, 0, 0},
+ {0x2DFF, 230, 0, 0},
+ {0x2E9F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6BCD},
+ {0x2EF3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9F9F},
+ {0x2F00, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E00},
+ {0x2F01, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E28},
+ {0x2F02, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E36},
+ {0x2F03, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E3F},
+ {0x2F04, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E59},
+ {0x2F05, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E85},
+ {0x2F06, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E8C},
+ {0x2F07, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4EA0},
+ {0x2F08, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4EBA},
+ {0x2F09, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x513F},
+ {0x2F0A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5165},
+ {0x2F0B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x516B},
+ {0x2F0C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5182},
+ {0x2F0D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5196},
+ {0x2F0E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x51AB},
+ {0x2F0F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x51E0},
+ {0x2F10, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x51F5},
+ {0x2F11, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5200},
+ {0x2F12, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x529B},
+ {0x2F13, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x52F9},
+ {0x2F14, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5315},
+ {0x2F15, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x531A},
+ {0x2F16, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5338},
+ {0x2F17, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5341},
+ {0x2F18, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x535C},
+ {0x2F19, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5369},
+ {0x2F1A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5382},
+ {0x2F1B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x53B6},
+ {0x2F1C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x53C8},
+ {0x2F1D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x53E3},
+ {0x2F1E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x56D7},
+ {0x2F1F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x571F},
+ {0x2F20, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x58EB},
+ {0x2F21, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5902},
+ {0x2F22, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x590A},
+ {0x2F23, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5915},
+ {0x2F24, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5927},
+ {0x2F25, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5973},
+ {0x2F26, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5B50},
+ {0x2F27, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5B80},
+ {0x2F28, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5BF8},
+ {0x2F29, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5C0F},
+ {0x2F2A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5C22},
+ {0x2F2B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5C38},
+ {0x2F2C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5C6E},
+ {0x2F2D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5C71},
+ {0x2F2E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5DDB},
+ {0x2F2F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5DE5},
+ {0x2F30, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5DF1},
+ {0x2F31, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5DFE},
+ {0x2F32, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5E72},
+ {0x2F33, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5E7A},
+ {0x2F34, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5E7F},
+ {0x2F35, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5EF4},
+ {0x2F36, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5EFE},
+ {0x2F37, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5F0B},
+ {0x2F38, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5F13},
+ {0x2F39, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5F50},
+ {0x2F3A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5F61},
+ {0x2F3B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5F73},
+ {0x2F3C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5FC3},
+ {0x2F3D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6208},
+ {0x2F3E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6236},
+ {0x2F3F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x624B},
+ {0x2F40, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x652F},
+ {0x2F41, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6534},
+ {0x2F42, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6587},
+ {0x2F43, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6597},
+ {0x2F44, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x65A4},
+ {0x2F45, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x65B9},
+ {0x2F46, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x65E0},
+ {0x2F47, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x65E5},
+ {0x2F48, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x66F0},
+ {0x2F49, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6708},
+ {0x2F4A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6728},
+ {0x2F4B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6B20},
+ {0x2F4C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6B62},
+ {0x2F4D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6B79},
+ {0x2F4E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6BB3},
+ {0x2F4F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6BCB},
+ {0x2F50, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6BD4},
+ {0x2F51, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6BDB},
+ {0x2F52, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6C0F},
+ {0x2F53, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6C14},
+ {0x2F54, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6C34},
+ {0x2F55, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x706B},
+ {0x2F56, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x722A},
+ {0x2F57, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7236},
+ {0x2F58, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x723B},
+ {0x2F59, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x723F},
+ {0x2F5A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7247},
+ {0x2F5B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7259},
+ {0x2F5C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x725B},
+ {0x2F5D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x72AC},
+ {0x2F5E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7384},
+ {0x2F5F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7389},
+ {0x2F60, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x74DC},
+ {0x2F61, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x74E6},
+ {0x2F62, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7518},
+ {0x2F63, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x751F},
+ {0x2F64, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7528},
+ {0x2F65, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7530},
+ {0x2F66, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x758B},
+ {0x2F67, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7592},
+ {0x2F68, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7676},
+ {0x2F69, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x767D},
+ {0x2F6A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x76AE},
+ {0x2F6B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x76BF},
+ {0x2F6C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x76EE},
+ {0x2F6D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x77DB},
+ {0x2F6E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x77E2},
+ {0x2F6F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x77F3},
+ {0x2F70, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x793A},
+ {0x2F71, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x79B8},
+ {0x2F72, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x79BE},
+ {0x2F73, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7A74},
+ {0x2F74, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7ACB},
+ {0x2F75, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7AF9},
+ {0x2F76, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7C73},
+ {0x2F77, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7CF8},
+ {0x2F78, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7F36},
+ {0x2F79, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7F51},
+ {0x2F7A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7F8A},
+ {0x2F7B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7FBD},
+ {0x2F7C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8001},
+ {0x2F7D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x800C},
+ {0x2F7E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8012},
+ {0x2F7F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8033},
+ {0x2F80, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x807F},
+ {0x2F81, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8089},
+ {0x2F82, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x81E3},
+ {0x2F83, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x81EA},
+ {0x2F84, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x81F3},
+ {0x2F85, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x81FC},
+ {0x2F86, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x820C},
+ {0x2F87, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x821B},
+ {0x2F88, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x821F},
+ {0x2F89, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x826E},
+ {0x2F8A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8272},
+ {0x2F8B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8278},
+ {0x2F8C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x864D},
+ {0x2F8D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x866B},
+ {0x2F8E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8840},
+ {0x2F8F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x884C},
+ {0x2F90, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8863},
+ {0x2F91, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x897E},
+ {0x2F92, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x898B},
+ {0x2F93, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x89D2},
+ {0x2F94, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8A00},
+ {0x2F95, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8C37},
+ {0x2F96, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8C46},
+ {0x2F97, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8C55},
+ {0x2F98, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8C78},
+ {0x2F99, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8C9D},
+ {0x2F9A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8D64},
+ {0x2F9B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8D70},
+ {0x2F9C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8DB3},
+ {0x2F9D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8EAB},
+ {0x2F9E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8ECA},
+ {0x2F9F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8F9B},
+ {0x2FA0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8FB0},
+ {0x2FA1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8FB5},
+ {0x2FA2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9091},
+ {0x2FA3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9149},
+ {0x2FA4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x91C6},
+ {0x2FA5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x91CC},
+ {0x2FA6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x91D1},
+ {0x2FA7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9577},
+ {0x2FA8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9580},
+ {0x2FA9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x961C},
+ {0x2FAA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x96B6},
+ {0x2FAB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x96B9},
+ {0x2FAC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x96E8},
+ {0x2FAD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9751},
+ {0x2FAE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x975E},
+ {0x2FAF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9762},
+ {0x2FB0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9769},
+ {0x2FB1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x97CB},
+ {0x2FB2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x97ED},
+ {0x2FB3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x97F3},
+ {0x2FB4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9801},
+ {0x2FB5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x98A8},
+ {0x2FB6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x98DB},
+ {0x2FB7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x98DF},
+ {0x2FB8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9996},
+ {0x2FB9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9999},
+ {0x2FBA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x99AC},
+ {0x2FBB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9AA8},
+ {0x2FBC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9AD8},
+ {0x2FBD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9ADF},
+ {0x2FBE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9B25},
+ {0x2FBF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9B2F},
+ {0x2FC0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9B32},
+ {0x2FC1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9B3C},
+ {0x2FC2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9B5A},
+ {0x2FC3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9CE5},
+ {0x2FC4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9E75},
+ {0x2FC5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9E7F},
+ {0x2FC6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9EA5},
+ {0x2FC7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9EBB},
+ {0x2FC8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9EC3},
+ {0x2FC9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9ECD},
+ {0x2FCA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9ED1},
+ {0x2FCB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9EF9},
+ {0x2FCC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9EFD},
+ {0x2FCD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9F0E},
+ {0x2FCE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9F13},
+ {0x2FCF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9F20},
+ {0x2FD0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9F3B},
+ {0x2FD1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9F4A},
+ {0x2FD2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9F52},
+ {0x2FD3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9F8D},
+ {0x2FD4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9F9C},
+ {0x2FD5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9FA0},
+ {0x3000, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0020},
+ {0x302A, 218, 0, 0},
+ {0x302B, 228, 0, 0},
+ {0x302C, 232, 0, 0},
+ {0x302D, 222, 0, 0},
+ {0x302E, 224, 0, 0},
+ {0x302F, 224, 0, 0},
+ {0x3036, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3012},
+ {0x3038, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5341},
+ {0x3039, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5344},
+ {0x303A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5345},
+ {0x304C, 0, 2, 2317},
+ {0x304E, 0, 2, 2319},
+ {0x3050, 0, 2, 2321},
+ {0x3052, 0, 2, 2323},
+ {0x3054, 0, 2, 2325},
+ {0x3056, 0, 2, 2327},
+ {0x3058, 0, 2, 2329},
+ {0x305A, 0, 2, 2331},
+ {0x305C, 0, 2, 2333},
+ {0x305E, 0, 2, 2335},
+ {0x3060, 0, 2, 2337},
+ {0x3062, 0, 2, 2339},
+ {0x3065, 0, 2, 2341},
+ {0x3067, 0, 2, 2343},
+ {0x3069, 0, 2, 2345},
+ {0x3070, 0, 2, 2347},
+ {0x3071, 0, 2, 2349},
+ {0x3073, 0, 2, 2351},
+ {0x3074, 0, 2, 2353},
+ {0x3076, 0, 2, 2355},
+ {0x3077, 0, 2, 2357},
+ {0x3079, 0, 2, 2359},
+ {0x307A, 0, 2, 2361},
+ {0x307C, 0, 2, 2363},
+ {0x307D, 0, 2, 2365},
+ {0x3094, 0, 2, 2367},
+ {0x3099, 8, 0, 0},
+ {0x309A, 8, 0, 0},
+ {0x309B, 0, 2 | DECOMP_COMPAT, 2369},
+ {0x309C, 0, 2 | DECOMP_COMPAT, 2371},
+ {0x309E, 0, 2, 2373},
+ {0x309F, 0, 2 | DECOMP_COMPAT, 2375},
+ {0x30AC, 0, 2, 2377},
+ {0x30AE, 0, 2, 2379},
+ {0x30B0, 0, 2, 2381},
+ {0x30B2, 0, 2, 2383},
+ {0x30B4, 0, 2, 2385},
+ {0x30B6, 0, 2, 2387},
+ {0x30B8, 0, 2, 2389},
+ {0x30BA, 0, 2, 2391},
+ {0x30BC, 0, 2, 2393},
+ {0x30BE, 0, 2, 2395},
+ {0x30C0, 0, 2, 2397},
+ {0x30C2, 0, 2, 2399},
+ {0x30C5, 0, 2, 2401},
+ {0x30C7, 0, 2, 2403},
+ {0x30C9, 0, 2, 2405},
+ {0x30D0, 0, 2, 2407},
+ {0x30D1, 0, 2, 2409},
+ {0x30D3, 0, 2, 2411},
+ {0x30D4, 0, 2, 2413},
+ {0x30D6, 0, 2, 2415},
+ {0x30D7, 0, 2, 2417},
+ {0x30D9, 0, 2, 2419},
+ {0x30DA, 0, 2, 2421},
+ {0x30DC, 0, 2, 2423},
+ {0x30DD, 0, 2, 2425},
+ {0x30F4, 0, 2, 2427},
+ {0x30F7, 0, 2, 2429},
+ {0x30F8, 0, 2, 2431},
+ {0x30F9, 0, 2, 2433},
+ {0x30FA, 0, 2, 2435},
+ {0x30FE, 0, 2, 2437},
+ {0x30FF, 0, 2 | DECOMP_COMPAT, 2439},
+ {0x3131, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1100},
+ {0x3132, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1101},
+ {0x3133, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x11AA},
+ {0x3134, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1102},
+ {0x3135, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x11AC},
+ {0x3136, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x11AD},
+ {0x3137, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1103},
+ {0x3138, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1104},
+ {0x3139, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1105},
+ {0x313A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x11B0},
+ {0x313B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x11B1},
+ {0x313C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x11B2},
+ {0x313D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x11B3},
+ {0x313E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x11B4},
+ {0x313F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x11B5},
+ {0x3140, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x111A},
+ {0x3141, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1106},
+ {0x3142, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1107},
+ {0x3143, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1108},
+ {0x3144, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1121},
+ {0x3145, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1109},
+ {0x3146, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x110A},
+ {0x3147, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x110B},
+ {0x3148, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x110C},
+ {0x3149, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x110D},
+ {0x314A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x110E},
+ {0x314B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x110F},
+ {0x314C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1110},
+ {0x314D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1111},
+ {0x314E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1112},
+ {0x314F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1161},
+ {0x3150, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1162},
+ {0x3151, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1163},
+ {0x3152, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1164},
+ {0x3153, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1165},
+ {0x3154, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1166},
+ {0x3155, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1167},
+ {0x3156, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1168},
+ {0x3157, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1169},
+ {0x3158, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x116A},
+ {0x3159, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x116B},
+ {0x315A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x116C},
+ {0x315B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x116D},
+ {0x315C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x116E},
+ {0x315D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x116F},
+ {0x315E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1170},
+ {0x315F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1171},
+ {0x3160, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1172},
+ {0x3161, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1173},
+ {0x3162, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1174},
+ {0x3163, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1175},
+ {0x3164, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1160},
+ {0x3165, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1114},
+ {0x3166, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1115},
+ {0x3167, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x11C7},
+ {0x3168, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x11C8},
+ {0x3169, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x11CC},
+ {0x316A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x11CE},
+ {0x316B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x11D3},
+ {0x316C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x11D7},
+ {0x316D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x11D9},
+ {0x316E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x111C},
+ {0x316F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x11DD},
+ {0x3170, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x11DF},
+ {0x3171, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x111D},
+ {0x3172, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x111E},
+ {0x3173, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1120},
+ {0x3174, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1122},
+ {0x3175, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1123},
+ {0x3176, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1127},
+ {0x3177, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1129},
+ {0x3178, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x112B},
+ {0x3179, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x112C},
+ {0x317A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x112D},
+ {0x317B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x112E},
+ {0x317C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x112F},
+ {0x317D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1132},
+ {0x317E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1136},
+ {0x317F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1140},
+ {0x3180, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1147},
+ {0x3181, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x114C},
+ {0x3182, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x11F1},
+ {0x3183, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x11F2},
+ {0x3184, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1157},
+ {0x3185, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1158},
+ {0x3186, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1159},
+ {0x3187, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1184},
+ {0x3188, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1185},
+ {0x3189, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1188},
+ {0x318A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1191},
+ {0x318B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1192},
+ {0x318C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1194},
+ {0x318D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x119E},
+ {0x318E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x11A1},
+ {0x3192, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E00},
+ {0x3193, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E8C},
+ {0x3194, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E09},
+ {0x3195, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x56DB},
+ {0x3196, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E0A},
+ {0x3197, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E2D},
+ {0x3198, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E0B},
+ {0x3199, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7532},
+ {0x319A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E59},
+ {0x319B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E19},
+ {0x319C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E01},
+ {0x319D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5929},
+ {0x319E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5730},
+ {0x319F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4EBA},
+ {0x3200, 0, 3 | DECOMP_COMPAT, 2441},
+ {0x3201, 0, 3 | DECOMP_COMPAT, 2444},
+ {0x3202, 0, 3 | DECOMP_COMPAT, 2447},
+ {0x3203, 0, 3 | DECOMP_COMPAT, 2450},
+ {0x3204, 0, 3 | DECOMP_COMPAT, 2453},
+ {0x3205, 0, 3 | DECOMP_COMPAT, 2456},
+ {0x3206, 0, 3 | DECOMP_COMPAT, 2459},
+ {0x3207, 0, 3 | DECOMP_COMPAT, 2462},
+ {0x3208, 0, 3 | DECOMP_COMPAT, 2465},
+ {0x3209, 0, 3 | DECOMP_COMPAT, 2468},
+ {0x320A, 0, 3 | DECOMP_COMPAT, 2471},
+ {0x320B, 0, 3 | DECOMP_COMPAT, 2474},
+ {0x320C, 0, 3 | DECOMP_COMPAT, 2477},
+ {0x320D, 0, 3 | DECOMP_COMPAT, 2480},
+ {0x320E, 0, 4 | DECOMP_COMPAT, 2483},
+ {0x320F, 0, 4 | DECOMP_COMPAT, 2487},
+ {0x3210, 0, 4 | DECOMP_COMPAT, 2491},
+ {0x3211, 0, 4 | DECOMP_COMPAT, 2495},
+ {0x3212, 0, 4 | DECOMP_COMPAT, 2499},
+ {0x3213, 0, 4 | DECOMP_COMPAT, 2503},
+ {0x3214, 0, 4 | DECOMP_COMPAT, 2507},
+ {0x3215, 0, 4 | DECOMP_COMPAT, 2511},
+ {0x3216, 0, 4 | DECOMP_COMPAT, 2515},
+ {0x3217, 0, 4 | DECOMP_COMPAT, 2519},
+ {0x3218, 0, 4 | DECOMP_COMPAT, 2523},
+ {0x3219, 0, 4 | DECOMP_COMPAT, 2527},
+ {0x321A, 0, 4 | DECOMP_COMPAT, 2531},
+ {0x321B, 0, 4 | DECOMP_COMPAT, 2535},
+ {0x321C, 0, 4 | DECOMP_COMPAT, 2539},
+ {0x321D, 0, 7 | DECOMP_COMPAT, 2543},
+ {0x321E, 0, 6 | DECOMP_COMPAT, 2550},
+ {0x3220, 0, 3 | DECOMP_COMPAT, 2556},
+ {0x3221, 0, 3 | DECOMP_COMPAT, 2559},
+ {0x3222, 0, 3 | DECOMP_COMPAT, 2562},
+ {0x3223, 0, 3 | DECOMP_COMPAT, 2565},
+ {0x3224, 0, 3 | DECOMP_COMPAT, 2568},
+ {0x3225, 0, 3 | DECOMP_COMPAT, 2571},
+ {0x3226, 0, 3 | DECOMP_COMPAT, 2574},
+ {0x3227, 0, 3 | DECOMP_COMPAT, 2577},
+ {0x3228, 0, 3 | DECOMP_COMPAT, 2580},
+ {0x3229, 0, 3 | DECOMP_COMPAT, 2583},
+ {0x322A, 0, 3 | DECOMP_COMPAT, 2586},
+ {0x322B, 0, 3 | DECOMP_COMPAT, 2589},
+ {0x322C, 0, 3 | DECOMP_COMPAT, 2592},
+ {0x322D, 0, 3 | DECOMP_COMPAT, 2595},
+ {0x322E, 0, 3 | DECOMP_COMPAT, 2598},
+ {0x322F, 0, 3 | DECOMP_COMPAT, 2601},
+ {0x3230, 0, 3 | DECOMP_COMPAT, 2604},
+ {0x3231, 0, 3 | DECOMP_COMPAT, 2607},
+ {0x3232, 0, 3 | DECOMP_COMPAT, 2610},
+ {0x3233, 0, 3 | DECOMP_COMPAT, 2613},
+ {0x3234, 0, 3 | DECOMP_COMPAT, 2616},
+ {0x3235, 0, 3 | DECOMP_COMPAT, 2619},
+ {0x3236, 0, 3 | DECOMP_COMPAT, 2622},
+ {0x3237, 0, 3 | DECOMP_COMPAT, 2625},
+ {0x3238, 0, 3 | DECOMP_COMPAT, 2628},
+ {0x3239, 0, 3 | DECOMP_COMPAT, 2631},
+ {0x323A, 0, 3 | DECOMP_COMPAT, 2634},
+ {0x323B, 0, 3 | DECOMP_COMPAT, 2637},
+ {0x323C, 0, 3 | DECOMP_COMPAT, 2640},
+ {0x323D, 0, 3 | DECOMP_COMPAT, 2643},
+ {0x323E, 0, 3 | DECOMP_COMPAT, 2646},
+ {0x323F, 0, 3 | DECOMP_COMPAT, 2649},
+ {0x3240, 0, 3 | DECOMP_COMPAT, 2652},
+ {0x3241, 0, 3 | DECOMP_COMPAT, 2655},
+ {0x3242, 0, 3 | DECOMP_COMPAT, 2658},
+ {0x3243, 0, 3 | DECOMP_COMPAT, 2661},
+ {0x3244, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x554F},
+ {0x3245, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5E7C},
+ {0x3246, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6587},
+ {0x3247, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7B8F},
+ {0x3250, 0, 3 | DECOMP_COMPAT, 2664},
+ {0x3251, 0, 2 | DECOMP_COMPAT, 2667},
+ {0x3252, 0, 2 | DECOMP_COMPAT, 2669},
+ {0x3253, 0, 2 | DECOMP_COMPAT, 2671},
+ {0x3254, 0, 2 | DECOMP_COMPAT, 2673},
+ {0x3255, 0, 2 | DECOMP_COMPAT, 2675},
+ {0x3256, 0, 2 | DECOMP_COMPAT, 2677},
+ {0x3257, 0, 2 | DECOMP_COMPAT, 2679},
+ {0x3258, 0, 2 | DECOMP_COMPAT, 2681},
+ {0x3259, 0, 2 | DECOMP_COMPAT, 2683},
+ {0x325A, 0, 2 | DECOMP_COMPAT, 2685},
+ {0x325B, 0, 2 | DECOMP_COMPAT, 2687},
+ {0x325C, 0, 2 | DECOMP_COMPAT, 2689},
+ {0x325D, 0, 2 | DECOMP_COMPAT, 2691},
+ {0x325E, 0, 2 | DECOMP_COMPAT, 2693},
+ {0x325F, 0, 2 | DECOMP_COMPAT, 2695},
+ {0x3260, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1100},
+ {0x3261, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1102},
+ {0x3262, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1103},
+ {0x3263, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1105},
+ {0x3264, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1106},
+ {0x3265, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1107},
+ {0x3266, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1109},
+ {0x3267, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x110B},
+ {0x3268, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x110C},
+ {0x3269, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x110E},
+ {0x326A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x110F},
+ {0x326B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1110},
+ {0x326C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1111},
+ {0x326D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1112},
+ {0x326E, 0, 2 | DECOMP_COMPAT, 2697},
+ {0x326F, 0, 2 | DECOMP_COMPAT, 2699},
+ {0x3270, 0, 2 | DECOMP_COMPAT, 2701},
+ {0x3271, 0, 2 | DECOMP_COMPAT, 2703},
+ {0x3272, 0, 2 | DECOMP_COMPAT, 2705},
+ {0x3273, 0, 2 | DECOMP_COMPAT, 2707},
+ {0x3274, 0, 2 | DECOMP_COMPAT, 2709},
+ {0x3275, 0, 2 | DECOMP_COMPAT, 2711},
+ {0x3276, 0, 2 | DECOMP_COMPAT, 2713},
+ {0x3277, 0, 2 | DECOMP_COMPAT, 2715},
+ {0x3278, 0, 2 | DECOMP_COMPAT, 2717},
+ {0x3279, 0, 2 | DECOMP_COMPAT, 2719},
+ {0x327A, 0, 2 | DECOMP_COMPAT, 2721},
+ {0x327B, 0, 2 | DECOMP_COMPAT, 2723},
+ {0x327C, 0, 5 | DECOMP_COMPAT, 2725},
+ {0x327D, 0, 4 | DECOMP_COMPAT, 2730},
+ {0x327E, 0, 2 | DECOMP_COMPAT, 2734},
+ {0x3280, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E00},
+ {0x3281, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E8C},
+ {0x3282, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E09},
+ {0x3283, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x56DB},
+ {0x3284, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E94},
+ {0x3285, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x516D},
+ {0x3286, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E03},
+ {0x3287, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x516B},
+ {0x3288, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E5D},
+ {0x3289, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5341},
+ {0x328A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6708},
+ {0x328B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x706B},
+ {0x328C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6C34},
+ {0x328D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6728},
+ {0x328E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x91D1},
+ {0x328F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x571F},
+ {0x3290, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x65E5},
+ {0x3291, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x682A},
+ {0x3292, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6709},
+ {0x3293, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x793E},
+ {0x3294, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x540D},
+ {0x3295, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7279},
+ {0x3296, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8CA1},
+ {0x3297, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x795D},
+ {0x3298, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x52B4},
+ {0x3299, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x79D8},
+ {0x329A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7537},
+ {0x329B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5973},
+ {0x329C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9069},
+ {0x329D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x512A},
+ {0x329E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5370},
+ {0x329F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6CE8},
+ {0x32A0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9805},
+ {0x32A1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4F11},
+ {0x32A2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5199},
+ {0x32A3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6B63},
+ {0x32A4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E0A},
+ {0x32A5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E2D},
+ {0x32A6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E0B},
+ {0x32A7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5DE6},
+ {0x32A8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x53F3},
+ {0x32A9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x533B},
+ {0x32AA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5B97},
+ {0x32AB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5B66},
+ {0x32AC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x76E3},
+ {0x32AD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4F01},
+ {0x32AE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8CC7},
+ {0x32AF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5354},
+ {0x32B0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x591C},
+ {0x32B1, 0, 2 | DECOMP_COMPAT, 2736},
+ {0x32B2, 0, 2 | DECOMP_COMPAT, 2738},
+ {0x32B3, 0, 2 | DECOMP_COMPAT, 2740},
+ {0x32B4, 0, 2 | DECOMP_COMPAT, 2742},
+ {0x32B5, 0, 2 | DECOMP_COMPAT, 2744},
+ {0x32B6, 0, 2 | DECOMP_COMPAT, 2746},
+ {0x32B7, 0, 2 | DECOMP_COMPAT, 2748},
+ {0x32B8, 0, 2 | DECOMP_COMPAT, 2750},
+ {0x32B9, 0, 2 | DECOMP_COMPAT, 2752},
+ {0x32BA, 0, 2 | DECOMP_COMPAT, 2754},
+ {0x32BB, 0, 2 | DECOMP_COMPAT, 2756},
+ {0x32BC, 0, 2 | DECOMP_COMPAT, 2758},
+ {0x32BD, 0, 2 | DECOMP_COMPAT, 2760},
+ {0x32BE, 0, 2 | DECOMP_COMPAT, 2762},
+ {0x32BF, 0, 2 | DECOMP_COMPAT, 2764},
+ {0x32C0, 0, 2 | DECOMP_COMPAT, 2766},
+ {0x32C1, 0, 2 | DECOMP_COMPAT, 2768},
+ {0x32C2, 0, 2 | DECOMP_COMPAT, 2770},
+ {0x32C3, 0, 2 | DECOMP_COMPAT, 2772},
+ {0x32C4, 0, 2 | DECOMP_COMPAT, 2774},
+ {0x32C5, 0, 2 | DECOMP_COMPAT, 2776},
+ {0x32C6, 0, 2 | DECOMP_COMPAT, 2778},
+ {0x32C7, 0, 2 | DECOMP_COMPAT, 2780},
+ {0x32C8, 0, 2 | DECOMP_COMPAT, 2782},
+ {0x32C9, 0, 3 | DECOMP_COMPAT, 2784},
+ {0x32CA, 0, 3 | DECOMP_COMPAT, 2787},
+ {0x32CB, 0, 3 | DECOMP_COMPAT, 2790},
+ {0x32CC, 0, 2 | DECOMP_COMPAT, 2793},
+ {0x32CD, 0, 3 | DECOMP_COMPAT, 2795},
+ {0x32CE, 0, 2 | DECOMP_COMPAT, 2798},
+ {0x32CF, 0, 3 | DECOMP_COMPAT, 2800},
+ {0x32D0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30A2},
+ {0x32D1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30A4},
+ {0x32D2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30A6},
+ {0x32D3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30A8},
+ {0x32D4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30AA},
+ {0x32D5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30AB},
+ {0x32D6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30AD},
+ {0x32D7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30AF},
+ {0x32D8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30B1},
+ {0x32D9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30B3},
+ {0x32DA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30B5},
+ {0x32DB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30B7},
+ {0x32DC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30B9},
+ {0x32DD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30BB},
+ {0x32DE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30BD},
+ {0x32DF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30BF},
+ {0x32E0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30C1},
+ {0x32E1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30C4},
+ {0x32E2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30C6},
+ {0x32E3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30C8},
+ {0x32E4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30CA},
+ {0x32E5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30CB},
+ {0x32E6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30CC},
+ {0x32E7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30CD},
+ {0x32E8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30CE},
+ {0x32E9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30CF},
+ {0x32EA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30D2},
+ {0x32EB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30D5},
+ {0x32EC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30D8},
+ {0x32ED, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30DB},
+ {0x32EE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30DE},
+ {0x32EF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30DF},
+ {0x32F0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30E0},
+ {0x32F1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30E1},
+ {0x32F2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30E2},
+ {0x32F3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30E4},
+ {0x32F4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30E6},
+ {0x32F5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30E8},
+ {0x32F6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30E9},
+ {0x32F7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30EA},
+ {0x32F8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30EB},
+ {0x32F9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30EC},
+ {0x32FA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30ED},
+ {0x32FB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30EF},
+ {0x32FC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30F0},
+ {0x32FD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30F1},
+ {0x32FE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30F2},
+ {0x32FF, 0, 2 | DECOMP_COMPAT, 2803},
+ {0x3300, 0, 4 | DECOMP_COMPAT, 2805},
+ {0x3301, 0, 4 | DECOMP_COMPAT, 2809},
+ {0x3302, 0, 4 | DECOMP_COMPAT, 2813},
+ {0x3303, 0, 3 | DECOMP_COMPAT, 2817},
+ {0x3304, 0, 4 | DECOMP_COMPAT, 2820},
+ {0x3305, 0, 3 | DECOMP_COMPAT, 2824},
+ {0x3306, 0, 3 | DECOMP_COMPAT, 2827},
+ {0x3307, 0, 5 | DECOMP_COMPAT, 2830},
+ {0x3308, 0, 4 | DECOMP_COMPAT, 2835},
+ {0x3309, 0, 3 | DECOMP_COMPAT, 2839},
+ {0x330A, 0, 3 | DECOMP_COMPAT, 2842},
+ {0x330B, 0, 3 | DECOMP_COMPAT, 2845},
+ {0x330C, 0, 4 | DECOMP_COMPAT, 2848},
+ {0x330D, 0, 4 | DECOMP_COMPAT, 2852},
+ {0x330E, 0, 3 | DECOMP_COMPAT, 2856},
+ {0x330F, 0, 3 | DECOMP_COMPAT, 2859},
+ {0x3310, 0, 2 | DECOMP_COMPAT, 2862},
+ {0x3311, 0, 3 | DECOMP_COMPAT, 2864},
+ {0x3312, 0, 4 | DECOMP_COMPAT, 2867},
+ {0x3313, 0, 4 | DECOMP_COMPAT, 2871},
+ {0x3314, 0, 2 | DECOMP_COMPAT, 2875},
+ {0x3315, 0, 5 | DECOMP_COMPAT, 2877},
+ {0x3316, 0, 6 | DECOMP_COMPAT, 2882},
+ {0x3317, 0, 5 | DECOMP_COMPAT, 2888},
+ {0x3318, 0, 3 | DECOMP_COMPAT, 2893},
+ {0x3319, 0, 5 | DECOMP_COMPAT, 2896},
+ {0x331A, 0, 5 | DECOMP_COMPAT, 2901},
+ {0x331B, 0, 4 | DECOMP_COMPAT, 2906},
+ {0x331C, 0, 3 | DECOMP_COMPAT, 2910},
+ {0x331D, 0, 3 | DECOMP_COMPAT, 2913},
+ {0x331E, 0, 3 | DECOMP_COMPAT, 2916},
+ {0x331F, 0, 4 | DECOMP_COMPAT, 2919},
+ {0x3320, 0, 5 | DECOMP_COMPAT, 2923},
+ {0x3321, 0, 4 | DECOMP_COMPAT, 2928},
+ {0x3322, 0, 3 | DECOMP_COMPAT, 2932},
+ {0x3323, 0, 3 | DECOMP_COMPAT, 2935},
+ {0x3324, 0, 3 | DECOMP_COMPAT, 2938},
+ {0x3325, 0, 2 | DECOMP_COMPAT, 2941},
+ {0x3326, 0, 2 | DECOMP_COMPAT, 2943},
+ {0x3327, 0, 2 | DECOMP_COMPAT, 2945},
+ {0x3328, 0, 2 | DECOMP_COMPAT, 2947},
+ {0x3329, 0, 3 | DECOMP_COMPAT, 2949},
+ {0x332A, 0, 3 | DECOMP_COMPAT, 2952},
+ {0x332B, 0, 5 | DECOMP_COMPAT, 2955},
+ {0x332C, 0, 3 | DECOMP_COMPAT, 2960},
+ {0x332D, 0, 4 | DECOMP_COMPAT, 2963},
+ {0x332E, 0, 5 | DECOMP_COMPAT, 2967},
+ {0x332F, 0, 3 | DECOMP_COMPAT, 2972},
+ {0x3330, 0, 2 | DECOMP_COMPAT, 2975},
+ {0x3331, 0, 2 | DECOMP_COMPAT, 2977},
+ {0x3332, 0, 5 | DECOMP_COMPAT, 2979},
+ {0x3333, 0, 4 | DECOMP_COMPAT, 2984},
+ {0x3334, 0, 5 | DECOMP_COMPAT, 2988},
+ {0x3335, 0, 3 | DECOMP_COMPAT, 2993},
+ {0x3336, 0, 5 | DECOMP_COMPAT, 2996},
+ {0x3337, 0, 2 | DECOMP_COMPAT, 3001},
+ {0x3338, 0, 3 | DECOMP_COMPAT, 3003},
+ {0x3339, 0, 3 | DECOMP_COMPAT, 3006},
+ {0x333A, 0, 3 | DECOMP_COMPAT, 3009},
+ {0x333B, 0, 3 | DECOMP_COMPAT, 3012},
+ {0x333C, 0, 3 | DECOMP_COMPAT, 3015},
+ {0x333D, 0, 4 | DECOMP_COMPAT, 3018},
+ {0x333E, 0, 3 | DECOMP_COMPAT, 3022},
+ {0x333F, 0, 2 | DECOMP_COMPAT, 3025},
+ {0x3340, 0, 3 | DECOMP_COMPAT, 3027},
+ {0x3341, 0, 3 | DECOMP_COMPAT, 3030},
+ {0x3342, 0, 3 | DECOMP_COMPAT, 3033},
+ {0x3343, 0, 4 | DECOMP_COMPAT, 3036},
+ {0x3344, 0, 3 | DECOMP_COMPAT, 3040},
+ {0x3345, 0, 3 | DECOMP_COMPAT, 3043},
+ {0x3346, 0, 3 | DECOMP_COMPAT, 3046},
+ {0x3347, 0, 5 | DECOMP_COMPAT, 3049},
+ {0x3348, 0, 4 | DECOMP_COMPAT, 3054},
+ {0x3349, 0, 2 | DECOMP_COMPAT, 3058},
+ {0x334A, 0, 5 | DECOMP_COMPAT, 3060},
+ {0x334B, 0, 2 | DECOMP_COMPAT, 3065},
+ {0x334C, 0, 4 | DECOMP_COMPAT, 3067},
+ {0x334D, 0, 4 | DECOMP_COMPAT, 3071},
+ {0x334E, 0, 3 | DECOMP_COMPAT, 3075},
+ {0x334F, 0, 3 | DECOMP_COMPAT, 3078},
+ {0x3350, 0, 3 | DECOMP_COMPAT, 3081},
+ {0x3351, 0, 4 | DECOMP_COMPAT, 3084},
+ {0x3352, 0, 2 | DECOMP_COMPAT, 3088},
+ {0x3353, 0, 3 | DECOMP_COMPAT, 3090},
+ {0x3354, 0, 4 | DECOMP_COMPAT, 3093},
+ {0x3355, 0, 2 | DECOMP_COMPAT, 3097},
+ {0x3356, 0, 5 | DECOMP_COMPAT, 3099},
+ {0x3357, 0, 3 | DECOMP_COMPAT, 3104},
+ {0x3358, 0, 2 | DECOMP_COMPAT, 3107},
+ {0x3359, 0, 2 | DECOMP_COMPAT, 3109},
+ {0x335A, 0, 2 | DECOMP_COMPAT, 3111},
+ {0x335B, 0, 2 | DECOMP_COMPAT, 3113},
+ {0x335C, 0, 2 | DECOMP_COMPAT, 3115},
+ {0x335D, 0, 2 | DECOMP_COMPAT, 3117},
+ {0x335E, 0, 2 | DECOMP_COMPAT, 3119},
+ {0x335F, 0, 2 | DECOMP_COMPAT, 3121},
+ {0x3360, 0, 2 | DECOMP_COMPAT, 3123},
+ {0x3361, 0, 2 | DECOMP_COMPAT, 3125},
+ {0x3362, 0, 3 | DECOMP_COMPAT, 3127},
+ {0x3363, 0, 3 | DECOMP_COMPAT, 3130},
+ {0x3364, 0, 3 | DECOMP_COMPAT, 3133},
+ {0x3365, 0, 3 | DECOMP_COMPAT, 3136},
+ {0x3366, 0, 3 | DECOMP_COMPAT, 3139},
+ {0x3367, 0, 3 | DECOMP_COMPAT, 3142},
+ {0x3368, 0, 3 | DECOMP_COMPAT, 3145},
+ {0x3369, 0, 3 | DECOMP_COMPAT, 3148},
+ {0x336A, 0, 3 | DECOMP_COMPAT, 3151},
+ {0x336B, 0, 3 | DECOMP_COMPAT, 3154},
+ {0x336C, 0, 3 | DECOMP_COMPAT, 3157},
+ {0x336D, 0, 3 | DECOMP_COMPAT, 3160},
+ {0x336E, 0, 3 | DECOMP_COMPAT, 3163},
+ {0x336F, 0, 3 | DECOMP_COMPAT, 3166},
+ {0x3370, 0, 3 | DECOMP_COMPAT, 3169},
+ {0x3371, 0, 3 | DECOMP_COMPAT, 3172},
+ {0x3372, 0, 2 | DECOMP_COMPAT, 3175},
+ {0x3373, 0, 2 | DECOMP_COMPAT, 3177},
+ {0x3374, 0, 3 | DECOMP_COMPAT, 3179},
+ {0x3375, 0, 2 | DECOMP_COMPAT, 3182},
+ {0x3376, 0, 2 | DECOMP_COMPAT, 3184},
+ {0x3377, 0, 2 | DECOMP_COMPAT, 3186},
+ {0x3378, 0, 3 | DECOMP_COMPAT, 3188},
+ {0x3379, 0, 3 | DECOMP_COMPAT, 3191},
+ {0x337A, 0, 2 | DECOMP_COMPAT, 3194},
+ {0x337B, 0, 2 | DECOMP_COMPAT, 3196},
+ {0x337C, 0, 2 | DECOMP_COMPAT, 3198},
+ {0x337D, 0, 2 | DECOMP_COMPAT, 3200},
+ {0x337E, 0, 2 | DECOMP_COMPAT, 3202},
+ {0x337F, 0, 4 | DECOMP_COMPAT, 3204},
+ {0x3380, 0, 2 | DECOMP_COMPAT, 3208},
+ {0x3381, 0, 2 | DECOMP_COMPAT, 3210},
+ {0x3382, 0, 2 | DECOMP_COMPAT, 3212},
+ {0x3383, 0, 2 | DECOMP_COMPAT, 3214},
+ {0x3384, 0, 2 | DECOMP_COMPAT, 3216},
+ {0x3385, 0, 2 | DECOMP_COMPAT, 3218},
+ {0x3386, 0, 2 | DECOMP_COMPAT, 3220},
+ {0x3387, 0, 2 | DECOMP_COMPAT, 3222},
+ {0x3388, 0, 3 | DECOMP_COMPAT, 3224},
+ {0x3389, 0, 4 | DECOMP_COMPAT, 3227},
+ {0x338A, 0, 2 | DECOMP_COMPAT, 3231},
+ {0x338B, 0, 2 | DECOMP_COMPAT, 3233},
+ {0x338C, 0, 2 | DECOMP_COMPAT, 3235},
+ {0x338D, 0, 2 | DECOMP_COMPAT, 3237},
+ {0x338E, 0, 2 | DECOMP_COMPAT, 3239},
+ {0x338F, 0, 2 | DECOMP_COMPAT, 3241},
+ {0x3390, 0, 2 | DECOMP_COMPAT, 3243},
+ {0x3391, 0, 3 | DECOMP_COMPAT, 3245},
+ {0x3392, 0, 3 | DECOMP_COMPAT, 3248},
+ {0x3393, 0, 3 | DECOMP_COMPAT, 3251},
+ {0x3394, 0, 3 | DECOMP_COMPAT, 3254},
+ {0x3395, 0, 2 | DECOMP_COMPAT, 3257},
+ {0x3396, 0, 2 | DECOMP_COMPAT, 3259},
+ {0x3397, 0, 2 | DECOMP_COMPAT, 3261},
+ {0x3398, 0, 2 | DECOMP_COMPAT, 3263},
+ {0x3399, 0, 2 | DECOMP_COMPAT, 3265},
+ {0x339A, 0, 2 | DECOMP_COMPAT, 3267},
+ {0x339B, 0, 2 | DECOMP_COMPAT, 3269},
+ {0x339C, 0, 2 | DECOMP_COMPAT, 3271},
+ {0x339D, 0, 2 | DECOMP_COMPAT, 3273},
+ {0x339E, 0, 2 | DECOMP_COMPAT, 3275},
+ {0x339F, 0, 3 | DECOMP_COMPAT, 3277},
+ {0x33A0, 0, 3 | DECOMP_COMPAT, 3280},
+ {0x33A1, 0, 2 | DECOMP_COMPAT, 3283},
+ {0x33A2, 0, 3 | DECOMP_COMPAT, 3285},
+ {0x33A3, 0, 3 | DECOMP_COMPAT, 3288},
+ {0x33A4, 0, 3 | DECOMP_COMPAT, 3291},
+ {0x33A5, 0, 2 | DECOMP_COMPAT, 3294},
+ {0x33A6, 0, 3 | DECOMP_COMPAT, 3296},
+ {0x33A7, 0, 3 | DECOMP_COMPAT, 3299},
+ {0x33A8, 0, 4 | DECOMP_COMPAT, 3302},
+ {0x33A9, 0, 2 | DECOMP_COMPAT, 3306},
+ {0x33AA, 0, 3 | DECOMP_COMPAT, 3308},
+ {0x33AB, 0, 3 | DECOMP_COMPAT, 3311},
+ {0x33AC, 0, 3 | DECOMP_COMPAT, 3314},
+ {0x33AD, 0, 3 | DECOMP_COMPAT, 3317},
+ {0x33AE, 0, 5 | DECOMP_COMPAT, 3320},
+ {0x33AF, 0, 6 | DECOMP_COMPAT, 3325},
+ {0x33B0, 0, 2 | DECOMP_COMPAT, 3331},
+ {0x33B1, 0, 2 | DECOMP_COMPAT, 3333},
+ {0x33B2, 0, 2 | DECOMP_COMPAT, 3335},
+ {0x33B3, 0, 2 | DECOMP_COMPAT, 3337},
+ {0x33B4, 0, 2 | DECOMP_COMPAT, 3339},
+ {0x33B5, 0, 2 | DECOMP_COMPAT, 3341},
+ {0x33B6, 0, 2 | DECOMP_COMPAT, 3343},
+ {0x33B7, 0, 2 | DECOMP_COMPAT, 3345},
+ {0x33B8, 0, 2 | DECOMP_COMPAT, 3347},
+ {0x33B9, 0, 2 | DECOMP_COMPAT, 3349},
+ {0x33BA, 0, 2 | DECOMP_COMPAT, 3351},
+ {0x33BB, 0, 2 | DECOMP_COMPAT, 3353},
+ {0x33BC, 0, 2 | DECOMP_COMPAT, 3355},
+ {0x33BD, 0, 2 | DECOMP_COMPAT, 3357},
+ {0x33BE, 0, 2 | DECOMP_COMPAT, 3359},
+ {0x33BF, 0, 2 | DECOMP_COMPAT, 3361},
+ {0x33C0, 0, 2 | DECOMP_COMPAT, 3363},
+ {0x33C1, 0, 2 | DECOMP_COMPAT, 3365},
+ {0x33C2, 0, 4 | DECOMP_COMPAT, 3367},
+ {0x33C3, 0, 2 | DECOMP_COMPAT, 3371},
+ {0x33C4, 0, 2 | DECOMP_COMPAT, 3373},
+ {0x33C5, 0, 2 | DECOMP_COMPAT, 3375},
+ {0x33C6, 0, 4 | DECOMP_COMPAT, 3377},
+ {0x33C7, 0, 3 | DECOMP_COMPAT, 3381},
+ {0x33C8, 0, 2 | DECOMP_COMPAT, 3384},
+ {0x33C9, 0, 2 | DECOMP_COMPAT, 3386},
+ {0x33CA, 0, 2 | DECOMP_COMPAT, 3388},
+ {0x33CB, 0, 2 | DECOMP_COMPAT, 3390},
+ {0x33CC, 0, 2 | DECOMP_COMPAT, 3392},
+ {0x33CD, 0, 2 | DECOMP_COMPAT, 3394},
+ {0x33CE, 0, 2 | DECOMP_COMPAT, 3396},
+ {0x33CF, 0, 2 | DECOMP_COMPAT, 3398},
+ {0x33D0, 0, 2 | DECOMP_COMPAT, 3400},
+ {0x33D1, 0, 2 | DECOMP_COMPAT, 3402},
+ {0x33D2, 0, 3 | DECOMP_COMPAT, 3404},
+ {0x33D3, 0, 2 | DECOMP_COMPAT, 3407},
+ {0x33D4, 0, 2 | DECOMP_COMPAT, 3409},
+ {0x33D5, 0, 3 | DECOMP_COMPAT, 3411},
+ {0x33D6, 0, 3 | DECOMP_COMPAT, 3414},
+ {0x33D7, 0, 2 | DECOMP_COMPAT, 3417},
+ {0x33D8, 0, 4 | DECOMP_COMPAT, 3419},
+ {0x33D9, 0, 3 | DECOMP_COMPAT, 3423},
+ {0x33DA, 0, 2 | DECOMP_COMPAT, 3426},
+ {0x33DB, 0, 2 | DECOMP_COMPAT, 3428},
+ {0x33DC, 0, 2 | DECOMP_COMPAT, 3430},
+ {0x33DD, 0, 2 | DECOMP_COMPAT, 3432},
+ {0x33DE, 0, 3 | DECOMP_COMPAT, 3434},
+ {0x33DF, 0, 3 | DECOMP_COMPAT, 3437},
+ {0x33E0, 0, 2 | DECOMP_COMPAT, 3440},
+ {0x33E1, 0, 2 | DECOMP_COMPAT, 3442},
+ {0x33E2, 0, 2 | DECOMP_COMPAT, 3444},
+ {0x33E3, 0, 2 | DECOMP_COMPAT, 3446},
+ {0x33E4, 0, 2 | DECOMP_COMPAT, 3448},
+ {0x33E5, 0, 2 | DECOMP_COMPAT, 3450},
+ {0x33E6, 0, 2 | DECOMP_COMPAT, 3452},
+ {0x33E7, 0, 2 | DECOMP_COMPAT, 3454},
+ {0x33E8, 0, 2 | DECOMP_COMPAT, 3456},
+ {0x33E9, 0, 3 | DECOMP_COMPAT, 3458},
+ {0x33EA, 0, 3 | DECOMP_COMPAT, 3461},
+ {0x33EB, 0, 3 | DECOMP_COMPAT, 3464},
+ {0x33EC, 0, 3 | DECOMP_COMPAT, 3467},
+ {0x33ED, 0, 3 | DECOMP_COMPAT, 3470},
+ {0x33EE, 0, 3 | DECOMP_COMPAT, 3473},
+ {0x33EF, 0, 3 | DECOMP_COMPAT, 3476},
+ {0x33F0, 0, 3 | DECOMP_COMPAT, 3479},
+ {0x33F1, 0, 3 | DECOMP_COMPAT, 3482},
+ {0x33F2, 0, 3 | DECOMP_COMPAT, 3485},
+ {0x33F3, 0, 3 | DECOMP_COMPAT, 3488},
+ {0x33F4, 0, 3 | DECOMP_COMPAT, 3491},
+ {0x33F5, 0, 3 | DECOMP_COMPAT, 3494},
+ {0x33F6, 0, 3 | DECOMP_COMPAT, 3497},
+ {0x33F7, 0, 3 | DECOMP_COMPAT, 3500},
+ {0x33F8, 0, 3 | DECOMP_COMPAT, 3503},
+ {0x33F9, 0, 3 | DECOMP_COMPAT, 3506},
+ {0x33FA, 0, 3 | DECOMP_COMPAT, 3509},
+ {0x33FB, 0, 3 | DECOMP_COMPAT, 3512},
+ {0x33FC, 0, 3 | DECOMP_COMPAT, 3515},
+ {0x33FD, 0, 3 | DECOMP_COMPAT, 3518},
+ {0x33FE, 0, 3 | DECOMP_COMPAT, 3521},
+ {0x33FF, 0, 3 | DECOMP_COMPAT, 3524},
+ {0xA66F, 230, 0, 0},
+ {0xA674, 230, 0, 0},
+ {0xA675, 230, 0, 0},
+ {0xA676, 230, 0, 0},
+ {0xA677, 230, 0, 0},
+ {0xA678, 230, 0, 0},
+ {0xA679, 230, 0, 0},
+ {0xA67A, 230, 0, 0},
+ {0xA67B, 230, 0, 0},
+ {0xA67C, 230, 0, 0},
+ {0xA67D, 230, 0, 0},
+ {0xA69C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x044A},
+ {0xA69D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x044C},
+ {0xA69E, 230, 0, 0},
+ {0xA69F, 230, 0, 0},
+ {0xA6F0, 230, 0, 0},
+ {0xA6F1, 230, 0, 0},
+ {0xA770, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0xA76F},
+ {0xA7F2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0043},
+ {0xA7F3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0046},
+ {0xA7F4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0051},
+ {0xA7F8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0126},
+ {0xA7F9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0153},
+ {0xA806, 9, 0, 0},
+ {0xA82C, 9, 0, 0},
+ {0xA8C4, 9, 0, 0},
+ {0xA8E0, 230, 0, 0},
+ {0xA8E1, 230, 0, 0},
+ {0xA8E2, 230, 0, 0},
+ {0xA8E3, 230, 0, 0},
+ {0xA8E4, 230, 0, 0},
+ {0xA8E5, 230, 0, 0},
+ {0xA8E6, 230, 0, 0},
+ {0xA8E7, 230, 0, 0},
+ {0xA8E8, 230, 0, 0},
+ {0xA8E9, 230, 0, 0},
+ {0xA8EA, 230, 0, 0},
+ {0xA8EB, 230, 0, 0},
+ {0xA8EC, 230, 0, 0},
+ {0xA8ED, 230, 0, 0},
+ {0xA8EE, 230, 0, 0},
+ {0xA8EF, 230, 0, 0},
+ {0xA8F0, 230, 0, 0},
+ {0xA8F1, 230, 0, 0},
+ {0xA92B, 220, 0, 0},
+ {0xA92C, 220, 0, 0},
+ {0xA92D, 220, 0, 0},
+ {0xA953, 9, 0, 0},
+ {0xA9B3, 7, 0, 0},
+ {0xA9C0, 9, 0, 0},
+ {0xAAB0, 230, 0, 0},
+ {0xAAB2, 230, 0, 0},
+ {0xAAB3, 230, 0, 0},
+ {0xAAB4, 220, 0, 0},
+ {0xAAB7, 230, 0, 0},
+ {0xAAB8, 230, 0, 0},
+ {0xAABE, 230, 0, 0},
+ {0xAABF, 230, 0, 0},
+ {0xAAC1, 230, 0, 0},
+ {0xAAF6, 9, 0, 0},
+ {0xAB5C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0xA727},
+ {0xAB5D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0xAB37},
+ {0xAB5E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x026B},
+ {0xAB5F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0xAB52},
+ {0xAB69, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x028D},
+ {0xABED, 9, 0, 0},
+ {0xF900, 0, 1 | DECOMP_INLINE, 0x8C48},
+ {0xF901, 0, 1 | DECOMP_INLINE, 0x66F4},
+ {0xF902, 0, 1 | DECOMP_INLINE, 0x8ECA},
+ {0xF903, 0, 1 | DECOMP_INLINE, 0x8CC8},
+ {0xF904, 0, 1 | DECOMP_INLINE, 0x6ED1},
+ {0xF905, 0, 1 | DECOMP_INLINE, 0x4E32},
+ {0xF906, 0, 1 | DECOMP_INLINE, 0x53E5},
+ {0xF907, 0, 1 | DECOMP_INLINE, 0x9F9C},
+ {0xF908, 0, 1 | DECOMP_INLINE, 0x9F9C},
+ {0xF909, 0, 1 | DECOMP_INLINE, 0x5951},
+ {0xF90A, 0, 1 | DECOMP_INLINE, 0x91D1},
+ {0xF90B, 0, 1 | DECOMP_INLINE, 0x5587},
+ {0xF90C, 0, 1 | DECOMP_INLINE, 0x5948},
+ {0xF90D, 0, 1 | DECOMP_INLINE, 0x61F6},
+ {0xF90E, 0, 1 | DECOMP_INLINE, 0x7669},
+ {0xF90F, 0, 1 | DECOMP_INLINE, 0x7F85},
+ {0xF910, 0, 1 | DECOMP_INLINE, 0x863F},
+ {0xF911, 0, 1 | DECOMP_INLINE, 0x87BA},
+ {0xF912, 0, 1 | DECOMP_INLINE, 0x88F8},
+ {0xF913, 0, 1 | DECOMP_INLINE, 0x908F},
+ {0xF914, 0, 1 | DECOMP_INLINE, 0x6A02},
+ {0xF915, 0, 1 | DECOMP_INLINE, 0x6D1B},
+ {0xF916, 0, 1 | DECOMP_INLINE, 0x70D9},
+ {0xF917, 0, 1 | DECOMP_INLINE, 0x73DE},
+ {0xF918, 0, 1 | DECOMP_INLINE, 0x843D},
+ {0xF919, 0, 1 | DECOMP_INLINE, 0x916A},
+ {0xF91A, 0, 1 | DECOMP_INLINE, 0x99F1},
+ {0xF91B, 0, 1 | DECOMP_INLINE, 0x4E82},
+ {0xF91C, 0, 1 | DECOMP_INLINE, 0x5375},
+ {0xF91D, 0, 1 | DECOMP_INLINE, 0x6B04},
+ {0xF91E, 0, 1 | DECOMP_INLINE, 0x721B},
+ {0xF91F, 0, 1 | DECOMP_INLINE, 0x862D},
+ {0xF920, 0, 1 | DECOMP_INLINE, 0x9E1E},
+ {0xF921, 0, 1 | DECOMP_INLINE, 0x5D50},
+ {0xF922, 0, 1 | DECOMP_INLINE, 0x6FEB},
+ {0xF923, 0, 1 | DECOMP_INLINE, 0x85CD},
+ {0xF924, 0, 1 | DECOMP_INLINE, 0x8964},
+ {0xF925, 0, 1 | DECOMP_INLINE, 0x62C9},
+ {0xF926, 0, 1 | DECOMP_INLINE, 0x81D8},
+ {0xF927, 0, 1 | DECOMP_INLINE, 0x881F},
+ {0xF928, 0, 1 | DECOMP_INLINE, 0x5ECA},
+ {0xF929, 0, 1 | DECOMP_INLINE, 0x6717},
+ {0xF92A, 0, 1 | DECOMP_INLINE, 0x6D6A},
+ {0xF92B, 0, 1 | DECOMP_INLINE, 0x72FC},
+ {0xF92C, 0, 1 | DECOMP_INLINE, 0x90CE},
+ {0xF92D, 0, 1 | DECOMP_INLINE, 0x4F86},
+ {0xF92E, 0, 1 | DECOMP_INLINE, 0x51B7},
+ {0xF92F, 0, 1 | DECOMP_INLINE, 0x52DE},
+ {0xF930, 0, 1 | DECOMP_INLINE, 0x64C4},
+ {0xF931, 0, 1 | DECOMP_INLINE, 0x6AD3},
+ {0xF932, 0, 1 | DECOMP_INLINE, 0x7210},
+ {0xF933, 0, 1 | DECOMP_INLINE, 0x76E7},
+ {0xF934, 0, 1 | DECOMP_INLINE, 0x8001},
+ {0xF935, 0, 1 | DECOMP_INLINE, 0x8606},
+ {0xF936, 0, 1 | DECOMP_INLINE, 0x865C},
+ {0xF937, 0, 1 | DECOMP_INLINE, 0x8DEF},
+ {0xF938, 0, 1 | DECOMP_INLINE, 0x9732},
+ {0xF939, 0, 1 | DECOMP_INLINE, 0x9B6F},
+ {0xF93A, 0, 1 | DECOMP_INLINE, 0x9DFA},
+ {0xF93B, 0, 1 | DECOMP_INLINE, 0x788C},
+ {0xF93C, 0, 1 | DECOMP_INLINE, 0x797F},
+ {0xF93D, 0, 1 | DECOMP_INLINE, 0x7DA0},
+ {0xF93E, 0, 1 | DECOMP_INLINE, 0x83C9},
+ {0xF93F, 0, 1 | DECOMP_INLINE, 0x9304},
+ {0xF940, 0, 1 | DECOMP_INLINE, 0x9E7F},
+ {0xF941, 0, 1 | DECOMP_INLINE, 0x8AD6},
+ {0xF942, 0, 1 | DECOMP_INLINE, 0x58DF},
+ {0xF943, 0, 1 | DECOMP_INLINE, 0x5F04},
+ {0xF944, 0, 1 | DECOMP_INLINE, 0x7C60},
+ {0xF945, 0, 1 | DECOMP_INLINE, 0x807E},
+ {0xF946, 0, 1 | DECOMP_INLINE, 0x7262},
+ {0xF947, 0, 1 | DECOMP_INLINE, 0x78CA},
+ {0xF948, 0, 1 | DECOMP_INLINE, 0x8CC2},
+ {0xF949, 0, 1 | DECOMP_INLINE, 0x96F7},
+ {0xF94A, 0, 1 | DECOMP_INLINE, 0x58D8},
+ {0xF94B, 0, 1 | DECOMP_INLINE, 0x5C62},
+ {0xF94C, 0, 1 | DECOMP_INLINE, 0x6A13},
+ {0xF94D, 0, 1 | DECOMP_INLINE, 0x6DDA},
+ {0xF94E, 0, 1 | DECOMP_INLINE, 0x6F0F},
+ {0xF94F, 0, 1 | DECOMP_INLINE, 0x7D2F},
+ {0xF950, 0, 1 | DECOMP_INLINE, 0x7E37},
+ {0xF951, 0, 1 | DECOMP_INLINE, 0x964B},
+ {0xF952, 0, 1 | DECOMP_INLINE, 0x52D2},
+ {0xF953, 0, 1 | DECOMP_INLINE, 0x808B},
+ {0xF954, 0, 1 | DECOMP_INLINE, 0x51DC},
+ {0xF955, 0, 1 | DECOMP_INLINE, 0x51CC},
+ {0xF956, 0, 1 | DECOMP_INLINE, 0x7A1C},
+ {0xF957, 0, 1 | DECOMP_INLINE, 0x7DBE},
+ {0xF958, 0, 1 | DECOMP_INLINE, 0x83F1},
+ {0xF959, 0, 1 | DECOMP_INLINE, 0x9675},
+ {0xF95A, 0, 1 | DECOMP_INLINE, 0x8B80},
+ {0xF95B, 0, 1 | DECOMP_INLINE, 0x62CF},
+ {0xF95C, 0, 1 | DECOMP_INLINE, 0x6A02},
+ {0xF95D, 0, 1 | DECOMP_INLINE, 0x8AFE},
+ {0xF95E, 0, 1 | DECOMP_INLINE, 0x4E39},
+ {0xF95F, 0, 1 | DECOMP_INLINE, 0x5BE7},
+ {0xF960, 0, 1 | DECOMP_INLINE, 0x6012},
+ {0xF961, 0, 1 | DECOMP_INLINE, 0x7387},
+ {0xF962, 0, 1 | DECOMP_INLINE, 0x7570},
+ {0xF963, 0, 1 | DECOMP_INLINE, 0x5317},
+ {0xF964, 0, 1 | DECOMP_INLINE, 0x78FB},
+ {0xF965, 0, 1 | DECOMP_INLINE, 0x4FBF},
+ {0xF966, 0, 1 | DECOMP_INLINE, 0x5FA9},
+ {0xF967, 0, 1 | DECOMP_INLINE, 0x4E0D},
+ {0xF968, 0, 1 | DECOMP_INLINE, 0x6CCC},
+ {0xF969, 0, 1 | DECOMP_INLINE, 0x6578},
+ {0xF96A, 0, 1 | DECOMP_INLINE, 0x7D22},
+ {0xF96B, 0, 1 | DECOMP_INLINE, 0x53C3},
+ {0xF96C, 0, 1 | DECOMP_INLINE, 0x585E},
+ {0xF96D, 0, 1 | DECOMP_INLINE, 0x7701},
+ {0xF96E, 0, 1 | DECOMP_INLINE, 0x8449},
+ {0xF96F, 0, 1 | DECOMP_INLINE, 0x8AAA},
+ {0xF970, 0, 1 | DECOMP_INLINE, 0x6BBA},
+ {0xF971, 0, 1 | DECOMP_INLINE, 0x8FB0},
+ {0xF972, 0, 1 | DECOMP_INLINE, 0x6C88},
+ {0xF973, 0, 1 | DECOMP_INLINE, 0x62FE},
+ {0xF974, 0, 1 | DECOMP_INLINE, 0x82E5},
+ {0xF975, 0, 1 | DECOMP_INLINE, 0x63A0},
+ {0xF976, 0, 1 | DECOMP_INLINE, 0x7565},
+ {0xF977, 0, 1 | DECOMP_INLINE, 0x4EAE},
+ {0xF978, 0, 1 | DECOMP_INLINE, 0x5169},
+ {0xF979, 0, 1 | DECOMP_INLINE, 0x51C9},
+ {0xF97A, 0, 1 | DECOMP_INLINE, 0x6881},
+ {0xF97B, 0, 1 | DECOMP_INLINE, 0x7CE7},
+ {0xF97C, 0, 1 | DECOMP_INLINE, 0x826F},
+ {0xF97D, 0, 1 | DECOMP_INLINE, 0x8AD2},
+ {0xF97E, 0, 1 | DECOMP_INLINE, 0x91CF},
+ {0xF97F, 0, 1 | DECOMP_INLINE, 0x52F5},
+ {0xF980, 0, 1 | DECOMP_INLINE, 0x5442},
+ {0xF981, 0, 1 | DECOMP_INLINE, 0x5973},
+ {0xF982, 0, 1 | DECOMP_INLINE, 0x5EEC},
+ {0xF983, 0, 1 | DECOMP_INLINE, 0x65C5},
+ {0xF984, 0, 1 | DECOMP_INLINE, 0x6FFE},
+ {0xF985, 0, 1 | DECOMP_INLINE, 0x792A},
+ {0xF986, 0, 1 | DECOMP_INLINE, 0x95AD},
+ {0xF987, 0, 1 | DECOMP_INLINE, 0x9A6A},
+ {0xF988, 0, 1 | DECOMP_INLINE, 0x9E97},
+ {0xF989, 0, 1 | DECOMP_INLINE, 0x9ECE},
+ {0xF98A, 0, 1 | DECOMP_INLINE, 0x529B},
+ {0xF98B, 0, 1 | DECOMP_INLINE, 0x66C6},
+ {0xF98C, 0, 1 | DECOMP_INLINE, 0x6B77},
+ {0xF98D, 0, 1 | DECOMP_INLINE, 0x8F62},
+ {0xF98E, 0, 1 | DECOMP_INLINE, 0x5E74},
+ {0xF98F, 0, 1 | DECOMP_INLINE, 0x6190},
+ {0xF990, 0, 1 | DECOMP_INLINE, 0x6200},
+ {0xF991, 0, 1 | DECOMP_INLINE, 0x649A},
+ {0xF992, 0, 1 | DECOMP_INLINE, 0x6F23},
+ {0xF993, 0, 1 | DECOMP_INLINE, 0x7149},
+ {0xF994, 0, 1 | DECOMP_INLINE, 0x7489},
+ {0xF995, 0, 1 | DECOMP_INLINE, 0x79CA},
+ {0xF996, 0, 1 | DECOMP_INLINE, 0x7DF4},
+ {0xF997, 0, 1 | DECOMP_INLINE, 0x806F},
+ {0xF998, 0, 1 | DECOMP_INLINE, 0x8F26},
+ {0xF999, 0, 1 | DECOMP_INLINE, 0x84EE},
+ {0xF99A, 0, 1 | DECOMP_INLINE, 0x9023},
+ {0xF99B, 0, 1 | DECOMP_INLINE, 0x934A},
+ {0xF99C, 0, 1 | DECOMP_INLINE, 0x5217},
+ {0xF99D, 0, 1 | DECOMP_INLINE, 0x52A3},
+ {0xF99E, 0, 1 | DECOMP_INLINE, 0x54BD},
+ {0xF99F, 0, 1 | DECOMP_INLINE, 0x70C8},
+ {0xF9A0, 0, 1 | DECOMP_INLINE, 0x88C2},
+ {0xF9A1, 0, 1 | DECOMP_INLINE, 0x8AAA},
+ {0xF9A2, 0, 1 | DECOMP_INLINE, 0x5EC9},
+ {0xF9A3, 0, 1 | DECOMP_INLINE, 0x5FF5},
+ {0xF9A4, 0, 1 | DECOMP_INLINE, 0x637B},
+ {0xF9A5, 0, 1 | DECOMP_INLINE, 0x6BAE},
+ {0xF9A6, 0, 1 | DECOMP_INLINE, 0x7C3E},
+ {0xF9A7, 0, 1 | DECOMP_INLINE, 0x7375},
+ {0xF9A8, 0, 1 | DECOMP_INLINE, 0x4EE4},
+ {0xF9A9, 0, 1 | DECOMP_INLINE, 0x56F9},
+ {0xF9AA, 0, 1 | DECOMP_INLINE, 0x5BE7},
+ {0xF9AB, 0, 1 | DECOMP_INLINE, 0x5DBA},
+ {0xF9AC, 0, 1 | DECOMP_INLINE, 0x601C},
+ {0xF9AD, 0, 1 | DECOMP_INLINE, 0x73B2},
+ {0xF9AE, 0, 1 | DECOMP_INLINE, 0x7469},
+ {0xF9AF, 0, 1 | DECOMP_INLINE, 0x7F9A},
+ {0xF9B0, 0, 1 | DECOMP_INLINE, 0x8046},
+ {0xF9B1, 0, 1 | DECOMP_INLINE, 0x9234},
+ {0xF9B2, 0, 1 | DECOMP_INLINE, 0x96F6},
+ {0xF9B3, 0, 1 | DECOMP_INLINE, 0x9748},
+ {0xF9B4, 0, 1 | DECOMP_INLINE, 0x9818},
+ {0xF9B5, 0, 1 | DECOMP_INLINE, 0x4F8B},
+ {0xF9B6, 0, 1 | DECOMP_INLINE, 0x79AE},
+ {0xF9B7, 0, 1 | DECOMP_INLINE, 0x91B4},
+ {0xF9B8, 0, 1 | DECOMP_INLINE, 0x96B8},
+ {0xF9B9, 0, 1 | DECOMP_INLINE, 0x60E1},
+ {0xF9BA, 0, 1 | DECOMP_INLINE, 0x4E86},
+ {0xF9BB, 0, 1 | DECOMP_INLINE, 0x50DA},
+ {0xF9BC, 0, 1 | DECOMP_INLINE, 0x5BEE},
+ {0xF9BD, 0, 1 | DECOMP_INLINE, 0x5C3F},
+ {0xF9BE, 0, 1 | DECOMP_INLINE, 0x6599},
+ {0xF9BF, 0, 1 | DECOMP_INLINE, 0x6A02},
+ {0xF9C0, 0, 1 | DECOMP_INLINE, 0x71CE},
+ {0xF9C1, 0, 1 | DECOMP_INLINE, 0x7642},
+ {0xF9C2, 0, 1 | DECOMP_INLINE, 0x84FC},
+ {0xF9C3, 0, 1 | DECOMP_INLINE, 0x907C},
+ {0xF9C4, 0, 1 | DECOMP_INLINE, 0x9F8D},
+ {0xF9C5, 0, 1 | DECOMP_INLINE, 0x6688},
+ {0xF9C6, 0, 1 | DECOMP_INLINE, 0x962E},
+ {0xF9C7, 0, 1 | DECOMP_INLINE, 0x5289},
+ {0xF9C8, 0, 1 | DECOMP_INLINE, 0x677B},
+ {0xF9C9, 0, 1 | DECOMP_INLINE, 0x67F3},
+ {0xF9CA, 0, 1 | DECOMP_INLINE, 0x6D41},
+ {0xF9CB, 0, 1 | DECOMP_INLINE, 0x6E9C},
+ {0xF9CC, 0, 1 | DECOMP_INLINE, 0x7409},
+ {0xF9CD, 0, 1 | DECOMP_INLINE, 0x7559},
+ {0xF9CE, 0, 1 | DECOMP_INLINE, 0x786B},
+ {0xF9CF, 0, 1 | DECOMP_INLINE, 0x7D10},
+ {0xF9D0, 0, 1 | DECOMP_INLINE, 0x985E},
+ {0xF9D1, 0, 1 | DECOMP_INLINE, 0x516D},
+ {0xF9D2, 0, 1 | DECOMP_INLINE, 0x622E},
+ {0xF9D3, 0, 1 | DECOMP_INLINE, 0x9678},
+ {0xF9D4, 0, 1 | DECOMP_INLINE, 0x502B},
+ {0xF9D5, 0, 1 | DECOMP_INLINE, 0x5D19},
+ {0xF9D6, 0, 1 | DECOMP_INLINE, 0x6DEA},
+ {0xF9D7, 0, 1 | DECOMP_INLINE, 0x8F2A},
+ {0xF9D8, 0, 1 | DECOMP_INLINE, 0x5F8B},
+ {0xF9D9, 0, 1 | DECOMP_INLINE, 0x6144},
+ {0xF9DA, 0, 1 | DECOMP_INLINE, 0x6817},
+ {0xF9DB, 0, 1 | DECOMP_INLINE, 0x7387},
+ {0xF9DC, 0, 1 | DECOMP_INLINE, 0x9686},
+ {0xF9DD, 0, 1 | DECOMP_INLINE, 0x5229},
+ {0xF9DE, 0, 1 | DECOMP_INLINE, 0x540F},
+ {0xF9DF, 0, 1 | DECOMP_INLINE, 0x5C65},
+ {0xF9E0, 0, 1 | DECOMP_INLINE, 0x6613},
+ {0xF9E1, 0, 1 | DECOMP_INLINE, 0x674E},
+ {0xF9E2, 0, 1 | DECOMP_INLINE, 0x68A8},
+ {0xF9E3, 0, 1 | DECOMP_INLINE, 0x6CE5},
+ {0xF9E4, 0, 1 | DECOMP_INLINE, 0x7406},
+ {0xF9E5, 0, 1 | DECOMP_INLINE, 0x75E2},
+ {0xF9E6, 0, 1 | DECOMP_INLINE, 0x7F79},
+ {0xF9E7, 0, 1 | DECOMP_INLINE, 0x88CF},
+ {0xF9E8, 0, 1 | DECOMP_INLINE, 0x88E1},
+ {0xF9E9, 0, 1 | DECOMP_INLINE, 0x91CC},
+ {0xF9EA, 0, 1 | DECOMP_INLINE, 0x96E2},
+ {0xF9EB, 0, 1 | DECOMP_INLINE, 0x533F},
+ {0xF9EC, 0, 1 | DECOMP_INLINE, 0x6EBA},
+ {0xF9ED, 0, 1 | DECOMP_INLINE, 0x541D},
+ {0xF9EE, 0, 1 | DECOMP_INLINE, 0x71D0},
+ {0xF9EF, 0, 1 | DECOMP_INLINE, 0x7498},
+ {0xF9F0, 0, 1 | DECOMP_INLINE, 0x85FA},
+ {0xF9F1, 0, 1 | DECOMP_INLINE, 0x96A3},
+ {0xF9F2, 0, 1 | DECOMP_INLINE, 0x9C57},
+ {0xF9F3, 0, 1 | DECOMP_INLINE, 0x9E9F},
+ {0xF9F4, 0, 1 | DECOMP_INLINE, 0x6797},
+ {0xF9F5, 0, 1 | DECOMP_INLINE, 0x6DCB},
+ {0xF9F6, 0, 1 | DECOMP_INLINE, 0x81E8},
+ {0xF9F7, 0, 1 | DECOMP_INLINE, 0x7ACB},
+ {0xF9F8, 0, 1 | DECOMP_INLINE, 0x7B20},
+ {0xF9F9, 0, 1 | DECOMP_INLINE, 0x7C92},
+ {0xF9FA, 0, 1 | DECOMP_INLINE, 0x72C0},
+ {0xF9FB, 0, 1 | DECOMP_INLINE, 0x7099},
+ {0xF9FC, 0, 1 | DECOMP_INLINE, 0x8B58},
+ {0xF9FD, 0, 1 | DECOMP_INLINE, 0x4EC0},
+ {0xF9FE, 0, 1 | DECOMP_INLINE, 0x8336},
+ {0xF9FF, 0, 1 | DECOMP_INLINE, 0x523A},
+ {0xFA00, 0, 1 | DECOMP_INLINE, 0x5207},
+ {0xFA01, 0, 1 | DECOMP_INLINE, 0x5EA6},
+ {0xFA02, 0, 1 | DECOMP_INLINE, 0x62D3},
+ {0xFA03, 0, 1 | DECOMP_INLINE, 0x7CD6},
+ {0xFA04, 0, 1 | DECOMP_INLINE, 0x5B85},
+ {0xFA05, 0, 1 | DECOMP_INLINE, 0x6D1E},
+ {0xFA06, 0, 1 | DECOMP_INLINE, 0x66B4},
+ {0xFA07, 0, 1 | DECOMP_INLINE, 0x8F3B},
+ {0xFA08, 0, 1 | DECOMP_INLINE, 0x884C},
+ {0xFA09, 0, 1 | DECOMP_INLINE, 0x964D},
+ {0xFA0A, 0, 1 | DECOMP_INLINE, 0x898B},
+ {0xFA0B, 0, 1 | DECOMP_INLINE, 0x5ED3},
+ {0xFA0C, 0, 1 | DECOMP_INLINE, 0x5140},
+ {0xFA0D, 0, 1 | DECOMP_INLINE, 0x55C0},
+ {0xFA10, 0, 1 | DECOMP_INLINE, 0x585A},
+ {0xFA12, 0, 1 | DECOMP_INLINE, 0x6674},
+ {0xFA15, 0, 1 | DECOMP_INLINE, 0x51DE},
+ {0xFA16, 0, 1 | DECOMP_INLINE, 0x732A},
+ {0xFA17, 0, 1 | DECOMP_INLINE, 0x76CA},
+ {0xFA18, 0, 1 | DECOMP_INLINE, 0x793C},
+ {0xFA19, 0, 1 | DECOMP_INLINE, 0x795E},
+ {0xFA1A, 0, 1 | DECOMP_INLINE, 0x7965},
+ {0xFA1B, 0, 1 | DECOMP_INLINE, 0x798F},
+ {0xFA1C, 0, 1 | DECOMP_INLINE, 0x9756},
+ {0xFA1D, 0, 1 | DECOMP_INLINE, 0x7CBE},
+ {0xFA1E, 0, 1 | DECOMP_INLINE, 0x7FBD},
+ {0xFA20, 0, 1 | DECOMP_INLINE, 0x8612},
+ {0xFA22, 0, 1 | DECOMP_INLINE, 0x8AF8},
+ {0xFA25, 0, 1 | DECOMP_INLINE, 0x9038},
+ {0xFA26, 0, 1 | DECOMP_INLINE, 0x90FD},
+ {0xFA2A, 0, 1 | DECOMP_INLINE, 0x98EF},
+ {0xFA2B, 0, 1 | DECOMP_INLINE, 0x98FC},
+ {0xFA2C, 0, 1 | DECOMP_INLINE, 0x9928},
+ {0xFA2D, 0, 1 | DECOMP_INLINE, 0x9DB4},
+ {0xFA2E, 0, 1 | DECOMP_INLINE, 0x90DE},
+ {0xFA2F, 0, 1 | DECOMP_INLINE, 0x96B7},
+ {0xFA30, 0, 1 | DECOMP_INLINE, 0x4FAE},
+ {0xFA31, 0, 1 | DECOMP_INLINE, 0x50E7},
+ {0xFA32, 0, 1 | DECOMP_INLINE, 0x514D},
+ {0xFA33, 0, 1 | DECOMP_INLINE, 0x52C9},
+ {0xFA34, 0, 1 | DECOMP_INLINE, 0x52E4},
+ {0xFA35, 0, 1 | DECOMP_INLINE, 0x5351},
+ {0xFA36, 0, 1 | DECOMP_INLINE, 0x559D},
+ {0xFA37, 0, 1 | DECOMP_INLINE, 0x5606},
+ {0xFA38, 0, 1 | DECOMP_INLINE, 0x5668},
+ {0xFA39, 0, 1 | DECOMP_INLINE, 0x5840},
+ {0xFA3A, 0, 1 | DECOMP_INLINE, 0x58A8},
+ {0xFA3B, 0, 1 | DECOMP_INLINE, 0x5C64},
+ {0xFA3C, 0, 1 | DECOMP_INLINE, 0x5C6E},
+ {0xFA3D, 0, 1 | DECOMP_INLINE, 0x6094},
+ {0xFA3E, 0, 1 | DECOMP_INLINE, 0x6168},
+ {0xFA3F, 0, 1 | DECOMP_INLINE, 0x618E},
+ {0xFA40, 0, 1 | DECOMP_INLINE, 0x61F2},
+ {0xFA41, 0, 1 | DECOMP_INLINE, 0x654F},
+ {0xFA42, 0, 1 | DECOMP_INLINE, 0x65E2},
+ {0xFA43, 0, 1 | DECOMP_INLINE, 0x6691},
+ {0xFA44, 0, 1 | DECOMP_INLINE, 0x6885},
+ {0xFA45, 0, 1 | DECOMP_INLINE, 0x6D77},
+ {0xFA46, 0, 1 | DECOMP_INLINE, 0x6E1A},
+ {0xFA47, 0, 1 | DECOMP_INLINE, 0x6F22},
+ {0xFA48, 0, 1 | DECOMP_INLINE, 0x716E},
+ {0xFA49, 0, 1 | DECOMP_INLINE, 0x722B},
+ {0xFA4A, 0, 1 | DECOMP_INLINE, 0x7422},
+ {0xFA4B, 0, 1 | DECOMP_INLINE, 0x7891},
+ {0xFA4C, 0, 1 | DECOMP_INLINE, 0x793E},
+ {0xFA4D, 0, 1 | DECOMP_INLINE, 0x7949},
+ {0xFA4E, 0, 1 | DECOMP_INLINE, 0x7948},
+ {0xFA4F, 0, 1 | DECOMP_INLINE, 0x7950},
+ {0xFA50, 0, 1 | DECOMP_INLINE, 0x7956},
+ {0xFA51, 0, 1 | DECOMP_INLINE, 0x795D},
+ {0xFA52, 0, 1 | DECOMP_INLINE, 0x798D},
+ {0xFA53, 0, 1 | DECOMP_INLINE, 0x798E},
+ {0xFA54, 0, 1 | DECOMP_INLINE, 0x7A40},
+ {0xFA55, 0, 1 | DECOMP_INLINE, 0x7A81},
+ {0xFA56, 0, 1 | DECOMP_INLINE, 0x7BC0},
+ {0xFA57, 0, 1 | DECOMP_INLINE, 0x7DF4},
+ {0xFA58, 0, 1 | DECOMP_INLINE, 0x7E09},
+ {0xFA59, 0, 1 | DECOMP_INLINE, 0x7E41},
+ {0xFA5A, 0, 1 | DECOMP_INLINE, 0x7F72},
+ {0xFA5B, 0, 1 | DECOMP_INLINE, 0x8005},
+ {0xFA5C, 0, 1 | DECOMP_INLINE, 0x81ED},
+ {0xFA5D, 0, 1 | DECOMP_INLINE, 0x8279},
+ {0xFA5E, 0, 1 | DECOMP_INLINE, 0x8279},
+ {0xFA5F, 0, 1 | DECOMP_INLINE, 0x8457},
+ {0xFA60, 0, 1 | DECOMP_INLINE, 0x8910},
+ {0xFA61, 0, 1 | DECOMP_INLINE, 0x8996},
+ {0xFA62, 0, 1 | DECOMP_INLINE, 0x8B01},
+ {0xFA63, 0, 1 | DECOMP_INLINE, 0x8B39},
+ {0xFA64, 0, 1 | DECOMP_INLINE, 0x8CD3},
+ {0xFA65, 0, 1 | DECOMP_INLINE, 0x8D08},
+ {0xFA66, 0, 1 | DECOMP_INLINE, 0x8FB6},
+ {0xFA67, 0, 1 | DECOMP_INLINE, 0x9038},
+ {0xFA68, 0, 1 | DECOMP_INLINE, 0x96E3},
+ {0xFA69, 0, 1 | DECOMP_INLINE, 0x97FF},
+ {0xFA6A, 0, 1 | DECOMP_INLINE, 0x983B},
+ {0xFA6B, 0, 1 | DECOMP_INLINE, 0x6075},
+ {0xFA6C, 0, 1, 3527},
+ {0xFA6D, 0, 1 | DECOMP_INLINE, 0x8218},
+ {0xFA70, 0, 1 | DECOMP_INLINE, 0x4E26},
+ {0xFA71, 0, 1 | DECOMP_INLINE, 0x51B5},
+ {0xFA72, 0, 1 | DECOMP_INLINE, 0x5168},
+ {0xFA73, 0, 1 | DECOMP_INLINE, 0x4F80},
+ {0xFA74, 0, 1 | DECOMP_INLINE, 0x5145},
+ {0xFA75, 0, 1 | DECOMP_INLINE, 0x5180},
+ {0xFA76, 0, 1 | DECOMP_INLINE, 0x52C7},
+ {0xFA77, 0, 1 | DECOMP_INLINE, 0x52FA},
+ {0xFA78, 0, 1 | DECOMP_INLINE, 0x559D},
+ {0xFA79, 0, 1 | DECOMP_INLINE, 0x5555},
+ {0xFA7A, 0, 1 | DECOMP_INLINE, 0x5599},
+ {0xFA7B, 0, 1 | DECOMP_INLINE, 0x55E2},
+ {0xFA7C, 0, 1 | DECOMP_INLINE, 0x585A},
+ {0xFA7D, 0, 1 | DECOMP_INLINE, 0x58B3},
+ {0xFA7E, 0, 1 | DECOMP_INLINE, 0x5944},
+ {0xFA7F, 0, 1 | DECOMP_INLINE, 0x5954},
+ {0xFA80, 0, 1 | DECOMP_INLINE, 0x5A62},
+ {0xFA81, 0, 1 | DECOMP_INLINE, 0x5B28},
+ {0xFA82, 0, 1 | DECOMP_INLINE, 0x5ED2},
+ {0xFA83, 0, 1 | DECOMP_INLINE, 0x5ED9},
+ {0xFA84, 0, 1 | DECOMP_INLINE, 0x5F69},
+ {0xFA85, 0, 1 | DECOMP_INLINE, 0x5FAD},
+ {0xFA86, 0, 1 | DECOMP_INLINE, 0x60D8},
+ {0xFA87, 0, 1 | DECOMP_INLINE, 0x614E},
+ {0xFA88, 0, 1 | DECOMP_INLINE, 0x6108},
+ {0xFA89, 0, 1 | DECOMP_INLINE, 0x618E},
+ {0xFA8A, 0, 1 | DECOMP_INLINE, 0x6160},
+ {0xFA8B, 0, 1 | DECOMP_INLINE, 0x61F2},
+ {0xFA8C, 0, 1 | DECOMP_INLINE, 0x6234},
+ {0xFA8D, 0, 1 | DECOMP_INLINE, 0x63C4},
+ {0xFA8E, 0, 1 | DECOMP_INLINE, 0x641C},
+ {0xFA8F, 0, 1 | DECOMP_INLINE, 0x6452},
+ {0xFA90, 0, 1 | DECOMP_INLINE, 0x6556},
+ {0xFA91, 0, 1 | DECOMP_INLINE, 0x6674},
+ {0xFA92, 0, 1 | DECOMP_INLINE, 0x6717},
+ {0xFA93, 0, 1 | DECOMP_INLINE, 0x671B},
+ {0xFA94, 0, 1 | DECOMP_INLINE, 0x6756},
+ {0xFA95, 0, 1 | DECOMP_INLINE, 0x6B79},
+ {0xFA96, 0, 1 | DECOMP_INLINE, 0x6BBA},
+ {0xFA97, 0, 1 | DECOMP_INLINE, 0x6D41},
+ {0xFA98, 0, 1 | DECOMP_INLINE, 0x6EDB},
+ {0xFA99, 0, 1 | DECOMP_INLINE, 0x6ECB},
+ {0xFA9A, 0, 1 | DECOMP_INLINE, 0x6F22},
+ {0xFA9B, 0, 1 | DECOMP_INLINE, 0x701E},
+ {0xFA9C, 0, 1 | DECOMP_INLINE, 0x716E},
+ {0xFA9D, 0, 1 | DECOMP_INLINE, 0x77A7},
+ {0xFA9E, 0, 1 | DECOMP_INLINE, 0x7235},
+ {0xFA9F, 0, 1 | DECOMP_INLINE, 0x72AF},
+ {0xFAA0, 0, 1 | DECOMP_INLINE, 0x732A},
+ {0xFAA1, 0, 1 | DECOMP_INLINE, 0x7471},
+ {0xFAA2, 0, 1 | DECOMP_INLINE, 0x7506},
+ {0xFAA3, 0, 1 | DECOMP_INLINE, 0x753B},
+ {0xFAA4, 0, 1 | DECOMP_INLINE, 0x761D},
+ {0xFAA5, 0, 1 | DECOMP_INLINE, 0x761F},
+ {0xFAA6, 0, 1 | DECOMP_INLINE, 0x76CA},
+ {0xFAA7, 0, 1 | DECOMP_INLINE, 0x76DB},
+ {0xFAA8, 0, 1 | DECOMP_INLINE, 0x76F4},
+ {0xFAA9, 0, 1 | DECOMP_INLINE, 0x774A},
+ {0xFAAA, 0, 1 | DECOMP_INLINE, 0x7740},
+ {0xFAAB, 0, 1 | DECOMP_INLINE, 0x78CC},
+ {0xFAAC, 0, 1 | DECOMP_INLINE, 0x7AB1},
+ {0xFAAD, 0, 1 | DECOMP_INLINE, 0x7BC0},
+ {0xFAAE, 0, 1 | DECOMP_INLINE, 0x7C7B},
+ {0xFAAF, 0, 1 | DECOMP_INLINE, 0x7D5B},
+ {0xFAB0, 0, 1 | DECOMP_INLINE, 0x7DF4},
+ {0xFAB1, 0, 1 | DECOMP_INLINE, 0x7F3E},
+ {0xFAB2, 0, 1 | DECOMP_INLINE, 0x8005},
+ {0xFAB3, 0, 1 | DECOMP_INLINE, 0x8352},
+ {0xFAB4, 0, 1 | DECOMP_INLINE, 0x83EF},
+ {0xFAB5, 0, 1 | DECOMP_INLINE, 0x8779},
+ {0xFAB6, 0, 1 | DECOMP_INLINE, 0x8941},
+ {0xFAB7, 0, 1 | DECOMP_INLINE, 0x8986},
+ {0xFAB8, 0, 1 | DECOMP_INLINE, 0x8996},
+ {0xFAB9, 0, 1 | DECOMP_INLINE, 0x8ABF},
+ {0xFABA, 0, 1 | DECOMP_INLINE, 0x8AF8},
+ {0xFABB, 0, 1 | DECOMP_INLINE, 0x8ACB},
+ {0xFABC, 0, 1 | DECOMP_INLINE, 0x8B01},
+ {0xFABD, 0, 1 | DECOMP_INLINE, 0x8AFE},
+ {0xFABE, 0, 1 | DECOMP_INLINE, 0x8AED},
+ {0xFABF, 0, 1 | DECOMP_INLINE, 0x8B39},
+ {0xFAC0, 0, 1 | DECOMP_INLINE, 0x8B8A},
+ {0xFAC1, 0, 1 | DECOMP_INLINE, 0x8D08},
+ {0xFAC2, 0, 1 | DECOMP_INLINE, 0x8F38},
+ {0xFAC3, 0, 1 | DECOMP_INLINE, 0x9072},
+ {0xFAC4, 0, 1 | DECOMP_INLINE, 0x9199},
+ {0xFAC5, 0, 1 | DECOMP_INLINE, 0x9276},
+ {0xFAC6, 0, 1 | DECOMP_INLINE, 0x967C},
+ {0xFAC7, 0, 1 | DECOMP_INLINE, 0x96E3},
+ {0xFAC8, 0, 1 | DECOMP_INLINE, 0x9756},
+ {0xFAC9, 0, 1 | DECOMP_INLINE, 0x97DB},
+ {0xFACA, 0, 1 | DECOMP_INLINE, 0x97FF},
+ {0xFACB, 0, 1 | DECOMP_INLINE, 0x980B},
+ {0xFACC, 0, 1 | DECOMP_INLINE, 0x983B},
+ {0xFACD, 0, 1 | DECOMP_INLINE, 0x9B12},
+ {0xFACE, 0, 1 | DECOMP_INLINE, 0x9F9C},
+ {0xFACF, 0, 1, 3528},
+ {0xFAD0, 0, 1, 3529},
+ {0xFAD1, 0, 1, 3530},
+ {0xFAD2, 0, 1 | DECOMP_INLINE, 0x3B9D},
+ {0xFAD3, 0, 1 | DECOMP_INLINE, 0x4018},
+ {0xFAD4, 0, 1 | DECOMP_INLINE, 0x4039},
+ {0xFAD5, 0, 1, 3531},
+ {0xFAD6, 0, 1, 3532},
+ {0xFAD7, 0, 1, 3533},
+ {0xFAD8, 0, 1 | DECOMP_INLINE, 0x9F43},
+ {0xFAD9, 0, 1 | DECOMP_INLINE, 0x9F8E},
+ {0xFB00, 0, 2 | DECOMP_COMPAT, 3534},
+ {0xFB01, 0, 2 | DECOMP_COMPAT, 3536},
+ {0xFB02, 0, 2 | DECOMP_COMPAT, 3538},
+ {0xFB03, 0, 3 | DECOMP_COMPAT, 3540},
+ {0xFB04, 0, 3 | DECOMP_COMPAT, 3543},
+ {0xFB05, 0, 2 | DECOMP_COMPAT, 3546},
+ {0xFB06, 0, 2 | DECOMP_COMPAT, 3548},
+ {0xFB13, 0, 2 | DECOMP_COMPAT, 3550},
+ {0xFB14, 0, 2 | DECOMP_COMPAT, 3552},
+ {0xFB15, 0, 2 | DECOMP_COMPAT, 3554},
+ {0xFB16, 0, 2 | DECOMP_COMPAT, 3556},
+ {0xFB17, 0, 2 | DECOMP_COMPAT, 3558},
+ {0xFB1D, 0, 2 | DECOMP_NO_COMPOSE, 3560}, /* in exclusion list */
+ {0xFB1E, 26, 0, 0},
+ {0xFB1F, 0, 2 | DECOMP_NO_COMPOSE, 3562}, /* in exclusion list */
+ {0xFB20, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x05E2},
+ {0xFB21, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x05D0},
+ {0xFB22, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x05D3},
+ {0xFB23, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x05D4},
+ {0xFB24, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x05DB},
+ {0xFB25, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x05DC},
+ {0xFB26, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x05DD},
+ {0xFB27, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x05E8},
+ {0xFB28, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x05EA},
+ {0xFB29, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x002B},
+ {0xFB2A, 0, 2 | DECOMP_NO_COMPOSE, 3564}, /* in exclusion list */
+ {0xFB2B, 0, 2 | DECOMP_NO_COMPOSE, 3566}, /* in exclusion list */
+ {0xFB2C, 0, 2 | DECOMP_NO_COMPOSE, 3568}, /* in exclusion list */
+ {0xFB2D, 0, 2 | DECOMP_NO_COMPOSE, 3570}, /* in exclusion list */
+ {0xFB2E, 0, 2 | DECOMP_NO_COMPOSE, 3572}, /* in exclusion list */
+ {0xFB2F, 0, 2 | DECOMP_NO_COMPOSE, 3574}, /* in exclusion list */
+ {0xFB30, 0, 2 | DECOMP_NO_COMPOSE, 3576}, /* in exclusion list */
+ {0xFB31, 0, 2 | DECOMP_NO_COMPOSE, 3578}, /* in exclusion list */
+ {0xFB32, 0, 2 | DECOMP_NO_COMPOSE, 3580}, /* in exclusion list */
+ {0xFB33, 0, 2 | DECOMP_NO_COMPOSE, 3582}, /* in exclusion list */
+ {0xFB34, 0, 2 | DECOMP_NO_COMPOSE, 3584}, /* in exclusion list */
+ {0xFB35, 0, 2 | DECOMP_NO_COMPOSE, 3586}, /* in exclusion list */
+ {0xFB36, 0, 2 | DECOMP_NO_COMPOSE, 3588}, /* in exclusion list */
+ {0xFB38, 0, 2 | DECOMP_NO_COMPOSE, 3590}, /* in exclusion list */
+ {0xFB39, 0, 2 | DECOMP_NO_COMPOSE, 3592}, /* in exclusion list */
+ {0xFB3A, 0, 2 | DECOMP_NO_COMPOSE, 3594}, /* in exclusion list */
+ {0xFB3B, 0, 2 | DECOMP_NO_COMPOSE, 3596}, /* in exclusion list */
+ {0xFB3C, 0, 2 | DECOMP_NO_COMPOSE, 3598}, /* in exclusion list */
+ {0xFB3E, 0, 2 | DECOMP_NO_COMPOSE, 3600}, /* in exclusion list */
+ {0xFB40, 0, 2 | DECOMP_NO_COMPOSE, 3602}, /* in exclusion list */
+ {0xFB41, 0, 2 | DECOMP_NO_COMPOSE, 3604}, /* in exclusion list */
+ {0xFB43, 0, 2 | DECOMP_NO_COMPOSE, 3606}, /* in exclusion list */
+ {0xFB44, 0, 2 | DECOMP_NO_COMPOSE, 3608}, /* in exclusion list */
+ {0xFB46, 0, 2 | DECOMP_NO_COMPOSE, 3610}, /* in exclusion list */
+ {0xFB47, 0, 2 | DECOMP_NO_COMPOSE, 3612}, /* in exclusion list */
+ {0xFB48, 0, 2 | DECOMP_NO_COMPOSE, 3614}, /* in exclusion list */
+ {0xFB49, 0, 2 | DECOMP_NO_COMPOSE, 3616}, /* in exclusion list */
+ {0xFB4A, 0, 2 | DECOMP_NO_COMPOSE, 3618}, /* in exclusion list */
+ {0xFB4B, 0, 2 | DECOMP_NO_COMPOSE, 3620}, /* in exclusion list */
+ {0xFB4C, 0, 2 | DECOMP_NO_COMPOSE, 3622}, /* in exclusion list */
+ {0xFB4D, 0, 2 | DECOMP_NO_COMPOSE, 3624}, /* in exclusion list */
+ {0xFB4E, 0, 2 | DECOMP_NO_COMPOSE, 3626}, /* in exclusion list */
+ {0xFB4F, 0, 2 | DECOMP_COMPAT, 3628},
+ {0xFB50, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0671},
+ {0xFB51, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0671},
+ {0xFB52, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x067B},
+ {0xFB53, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x067B},
+ {0xFB54, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x067B},
+ {0xFB55, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x067B},
+ {0xFB56, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x067E},
+ {0xFB57, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x067E},
+ {0xFB58, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x067E},
+ {0xFB59, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x067E},
+ {0xFB5A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0680},
+ {0xFB5B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0680},
+ {0xFB5C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0680},
+ {0xFB5D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0680},
+ {0xFB5E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x067A},
+ {0xFB5F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x067A},
+ {0xFB60, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x067A},
+ {0xFB61, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x067A},
+ {0xFB62, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x067F},
+ {0xFB63, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x067F},
+ {0xFB64, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x067F},
+ {0xFB65, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x067F},
+ {0xFB66, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0679},
+ {0xFB67, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0679},
+ {0xFB68, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0679},
+ {0xFB69, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0679},
+ {0xFB6A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06A4},
+ {0xFB6B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06A4},
+ {0xFB6C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06A4},
+ {0xFB6D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06A4},
+ {0xFB6E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06A6},
+ {0xFB6F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06A6},
+ {0xFB70, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06A6},
+ {0xFB71, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06A6},
+ {0xFB72, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0684},
+ {0xFB73, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0684},
+ {0xFB74, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0684},
+ {0xFB75, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0684},
+ {0xFB76, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0683},
+ {0xFB77, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0683},
+ {0xFB78, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0683},
+ {0xFB79, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0683},
+ {0xFB7A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0686},
+ {0xFB7B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0686},
+ {0xFB7C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0686},
+ {0xFB7D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0686},
+ {0xFB7E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0687},
+ {0xFB7F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0687},
+ {0xFB80, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0687},
+ {0xFB81, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0687},
+ {0xFB82, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x068D},
+ {0xFB83, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x068D},
+ {0xFB84, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x068C},
+ {0xFB85, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x068C},
+ {0xFB86, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x068E},
+ {0xFB87, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x068E},
+ {0xFB88, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0688},
+ {0xFB89, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0688},
+ {0xFB8A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0698},
+ {0xFB8B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0698},
+ {0xFB8C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0691},
+ {0xFB8D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0691},
+ {0xFB8E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06A9},
+ {0xFB8F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06A9},
+ {0xFB90, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06A9},
+ {0xFB91, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06A9},
+ {0xFB92, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06AF},
+ {0xFB93, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06AF},
+ {0xFB94, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06AF},
+ {0xFB95, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06AF},
+ {0xFB96, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06B3},
+ {0xFB97, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06B3},
+ {0xFB98, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06B3},
+ {0xFB99, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06B3},
+ {0xFB9A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06B1},
+ {0xFB9B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06B1},
+ {0xFB9C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06B1},
+ {0xFB9D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06B1},
+ {0xFB9E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06BA},
+ {0xFB9F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06BA},
+ {0xFBA0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06BB},
+ {0xFBA1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06BB},
+ {0xFBA2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06BB},
+ {0xFBA3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06BB},
+ {0xFBA4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06C0},
+ {0xFBA5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06C0},
+ {0xFBA6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06C1},
+ {0xFBA7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06C1},
+ {0xFBA8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06C1},
+ {0xFBA9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06C1},
+ {0xFBAA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06BE},
+ {0xFBAB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06BE},
+ {0xFBAC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06BE},
+ {0xFBAD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06BE},
+ {0xFBAE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06D2},
+ {0xFBAF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06D2},
+ {0xFBB0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06D3},
+ {0xFBB1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06D3},
+ {0xFBD3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06AD},
+ {0xFBD4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06AD},
+ {0xFBD5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06AD},
+ {0xFBD6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06AD},
+ {0xFBD7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06C7},
+ {0xFBD8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06C7},
+ {0xFBD9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06C6},
+ {0xFBDA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06C6},
+ {0xFBDB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06C8},
+ {0xFBDC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06C8},
+ {0xFBDD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0677},
+ {0xFBDE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06CB},
+ {0xFBDF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06CB},
+ {0xFBE0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06C5},
+ {0xFBE1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06C5},
+ {0xFBE2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06C9},
+ {0xFBE3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06C9},
+ {0xFBE4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06D0},
+ {0xFBE5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06D0},
+ {0xFBE6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06D0},
+ {0xFBE7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06D0},
+ {0xFBE8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0649},
+ {0xFBE9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0649},
+ {0xFBEA, 0, 2 | DECOMP_COMPAT, 3630},
+ {0xFBEB, 0, 2 | DECOMP_COMPAT, 3632},
+ {0xFBEC, 0, 2 | DECOMP_COMPAT, 3634},
+ {0xFBED, 0, 2 | DECOMP_COMPAT, 3636},
+ {0xFBEE, 0, 2 | DECOMP_COMPAT, 3638},
+ {0xFBEF, 0, 2 | DECOMP_COMPAT, 3640},
+ {0xFBF0, 0, 2 | DECOMP_COMPAT, 3642},
+ {0xFBF1, 0, 2 | DECOMP_COMPAT, 3644},
+ {0xFBF2, 0, 2 | DECOMP_COMPAT, 3646},
+ {0xFBF3, 0, 2 | DECOMP_COMPAT, 3648},
+ {0xFBF4, 0, 2 | DECOMP_COMPAT, 3650},
+ {0xFBF5, 0, 2 | DECOMP_COMPAT, 3652},
+ {0xFBF6, 0, 2 | DECOMP_COMPAT, 3654},
+ {0xFBF7, 0, 2 | DECOMP_COMPAT, 3656},
+ {0xFBF8, 0, 2 | DECOMP_COMPAT, 3658},
+ {0xFBF9, 0, 2 | DECOMP_COMPAT, 3660},
+ {0xFBFA, 0, 2 | DECOMP_COMPAT, 3662},
+ {0xFBFB, 0, 2 | DECOMP_COMPAT, 3664},
+ {0xFBFC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06CC},
+ {0xFBFD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06CC},
+ {0xFBFE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06CC},
+ {0xFBFF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06CC},
+ {0xFC00, 0, 2 | DECOMP_COMPAT, 3666},
+ {0xFC01, 0, 2 | DECOMP_COMPAT, 3668},
+ {0xFC02, 0, 2 | DECOMP_COMPAT, 3670},
+ {0xFC03, 0, 2 | DECOMP_COMPAT, 3672},
+ {0xFC04, 0, 2 | DECOMP_COMPAT, 3674},
+ {0xFC05, 0, 2 | DECOMP_COMPAT, 3676},
+ {0xFC06, 0, 2 | DECOMP_COMPAT, 3678},
+ {0xFC07, 0, 2 | DECOMP_COMPAT, 3680},
+ {0xFC08, 0, 2 | DECOMP_COMPAT, 3682},
+ {0xFC09, 0, 2 | DECOMP_COMPAT, 3684},
+ {0xFC0A, 0, 2 | DECOMP_COMPAT, 3686},
+ {0xFC0B, 0, 2 | DECOMP_COMPAT, 3688},
+ {0xFC0C, 0, 2 | DECOMP_COMPAT, 3690},
+ {0xFC0D, 0, 2 | DECOMP_COMPAT, 3692},
+ {0xFC0E, 0, 2 | DECOMP_COMPAT, 3694},
+ {0xFC0F, 0, 2 | DECOMP_COMPAT, 3696},
+ {0xFC10, 0, 2 | DECOMP_COMPAT, 3698},
+ {0xFC11, 0, 2 | DECOMP_COMPAT, 3700},
+ {0xFC12, 0, 2 | DECOMP_COMPAT, 3702},
+ {0xFC13, 0, 2 | DECOMP_COMPAT, 3704},
+ {0xFC14, 0, 2 | DECOMP_COMPAT, 3706},
+ {0xFC15, 0, 2 | DECOMP_COMPAT, 3708},
+ {0xFC16, 0, 2 | DECOMP_COMPAT, 3710},
+ {0xFC17, 0, 2 | DECOMP_COMPAT, 3712},
+ {0xFC18, 0, 2 | DECOMP_COMPAT, 3714},
+ {0xFC19, 0, 2 | DECOMP_COMPAT, 3716},
+ {0xFC1A, 0, 2 | DECOMP_COMPAT, 3718},
+ {0xFC1B, 0, 2 | DECOMP_COMPAT, 3720},
+ {0xFC1C, 0, 2 | DECOMP_COMPAT, 3722},
+ {0xFC1D, 0, 2 | DECOMP_COMPAT, 3724},
+ {0xFC1E, 0, 2 | DECOMP_COMPAT, 3726},
+ {0xFC1F, 0, 2 | DECOMP_COMPAT, 3728},
+ {0xFC20, 0, 2 | DECOMP_COMPAT, 3730},
+ {0xFC21, 0, 2 | DECOMP_COMPAT, 3732},
+ {0xFC22, 0, 2 | DECOMP_COMPAT, 3734},
+ {0xFC23, 0, 2 | DECOMP_COMPAT, 3736},
+ {0xFC24, 0, 2 | DECOMP_COMPAT, 3738},
+ {0xFC25, 0, 2 | DECOMP_COMPAT, 3740},
+ {0xFC26, 0, 2 | DECOMP_COMPAT, 3742},
+ {0xFC27, 0, 2 | DECOMP_COMPAT, 3744},
+ {0xFC28, 0, 2 | DECOMP_COMPAT, 3746},
+ {0xFC29, 0, 2 | DECOMP_COMPAT, 3748},
+ {0xFC2A, 0, 2 | DECOMP_COMPAT, 3750},
+ {0xFC2B, 0, 2 | DECOMP_COMPAT, 3752},
+ {0xFC2C, 0, 2 | DECOMP_COMPAT, 3754},
+ {0xFC2D, 0, 2 | DECOMP_COMPAT, 3756},
+ {0xFC2E, 0, 2 | DECOMP_COMPAT, 3758},
+ {0xFC2F, 0, 2 | DECOMP_COMPAT, 3760},
+ {0xFC30, 0, 2 | DECOMP_COMPAT, 3762},
+ {0xFC31, 0, 2 | DECOMP_COMPAT, 3764},
+ {0xFC32, 0, 2 | DECOMP_COMPAT, 3766},
+ {0xFC33, 0, 2 | DECOMP_COMPAT, 3768},
+ {0xFC34, 0, 2 | DECOMP_COMPAT, 3770},
+ {0xFC35, 0, 2 | DECOMP_COMPAT, 3772},
+ {0xFC36, 0, 2 | DECOMP_COMPAT, 3774},
+ {0xFC37, 0, 2 | DECOMP_COMPAT, 3776},
+ {0xFC38, 0, 2 | DECOMP_COMPAT, 3778},
+ {0xFC39, 0, 2 | DECOMP_COMPAT, 3780},
+ {0xFC3A, 0, 2 | DECOMP_COMPAT, 3782},
+ {0xFC3B, 0, 2 | DECOMP_COMPAT, 3784},
+ {0xFC3C, 0, 2 | DECOMP_COMPAT, 3786},
+ {0xFC3D, 0, 2 | DECOMP_COMPAT, 3788},
+ {0xFC3E, 0, 2 | DECOMP_COMPAT, 3790},
+ {0xFC3F, 0, 2 | DECOMP_COMPAT, 3792},
+ {0xFC40, 0, 2 | DECOMP_COMPAT, 3794},
+ {0xFC41, 0, 2 | DECOMP_COMPAT, 3796},
+ {0xFC42, 0, 2 | DECOMP_COMPAT, 3798},
+ {0xFC43, 0, 2 | DECOMP_COMPAT, 3800},
+ {0xFC44, 0, 2 | DECOMP_COMPAT, 3802},
+ {0xFC45, 0, 2 | DECOMP_COMPAT, 3804},
+ {0xFC46, 0, 2 | DECOMP_COMPAT, 3806},
+ {0xFC47, 0, 2 | DECOMP_COMPAT, 3808},
+ {0xFC48, 0, 2 | DECOMP_COMPAT, 3810},
+ {0xFC49, 0, 2 | DECOMP_COMPAT, 3812},
+ {0xFC4A, 0, 2 | DECOMP_COMPAT, 3814},
+ {0xFC4B, 0, 2 | DECOMP_COMPAT, 3816},
+ {0xFC4C, 0, 2 | DECOMP_COMPAT, 3818},
+ {0xFC4D, 0, 2 | DECOMP_COMPAT, 3820},
+ {0xFC4E, 0, 2 | DECOMP_COMPAT, 3822},
+ {0xFC4F, 0, 2 | DECOMP_COMPAT, 3824},
+ {0xFC50, 0, 2 | DECOMP_COMPAT, 3826},
+ {0xFC51, 0, 2 | DECOMP_COMPAT, 3828},
+ {0xFC52, 0, 2 | DECOMP_COMPAT, 3830},
+ {0xFC53, 0, 2 | DECOMP_COMPAT, 3832},
+ {0xFC54, 0, 2 | DECOMP_COMPAT, 3834},
+ {0xFC55, 0, 2 | DECOMP_COMPAT, 3836},
+ {0xFC56, 0, 2 | DECOMP_COMPAT, 3838},
+ {0xFC57, 0, 2 | DECOMP_COMPAT, 3840},
+ {0xFC58, 0, 2 | DECOMP_COMPAT, 3842},
+ {0xFC59, 0, 2 | DECOMP_COMPAT, 3844},
+ {0xFC5A, 0, 2 | DECOMP_COMPAT, 3846},
+ {0xFC5B, 0, 2 | DECOMP_COMPAT, 3848},
+ {0xFC5C, 0, 2 | DECOMP_COMPAT, 3850},
+ {0xFC5D, 0, 2 | DECOMP_COMPAT, 3852},
+ {0xFC5E, 0, 3 | DECOMP_COMPAT, 3854},
+ {0xFC5F, 0, 3 | DECOMP_COMPAT, 3857},
+ {0xFC60, 0, 3 | DECOMP_COMPAT, 3860},
+ {0xFC61, 0, 3 | DECOMP_COMPAT, 3863},
+ {0xFC62, 0, 3 | DECOMP_COMPAT, 3866},
+ {0xFC63, 0, 3 | DECOMP_COMPAT, 3869},
+ {0xFC64, 0, 2 | DECOMP_COMPAT, 3872},
+ {0xFC65, 0, 2 | DECOMP_COMPAT, 3874},
+ {0xFC66, 0, 2 | DECOMP_COMPAT, 3876},
+ {0xFC67, 0, 2 | DECOMP_COMPAT, 3878},
+ {0xFC68, 0, 2 | DECOMP_COMPAT, 3880},
+ {0xFC69, 0, 2 | DECOMP_COMPAT, 3882},
+ {0xFC6A, 0, 2 | DECOMP_COMPAT, 3884},
+ {0xFC6B, 0, 2 | DECOMP_COMPAT, 3886},
+ {0xFC6C, 0, 2 | DECOMP_COMPAT, 3888},
+ {0xFC6D, 0, 2 | DECOMP_COMPAT, 3890},
+ {0xFC6E, 0, 2 | DECOMP_COMPAT, 3892},
+ {0xFC6F, 0, 2 | DECOMP_COMPAT, 3894},
+ {0xFC70, 0, 2 | DECOMP_COMPAT, 3896},
+ {0xFC71, 0, 2 | DECOMP_COMPAT, 3898},
+ {0xFC72, 0, 2 | DECOMP_COMPAT, 3900},
+ {0xFC73, 0, 2 | DECOMP_COMPAT, 3902},
+ {0xFC74, 0, 2 | DECOMP_COMPAT, 3904},
+ {0xFC75, 0, 2 | DECOMP_COMPAT, 3906},
+ {0xFC76, 0, 2 | DECOMP_COMPAT, 3908},
+ {0xFC77, 0, 2 | DECOMP_COMPAT, 3910},
+ {0xFC78, 0, 2 | DECOMP_COMPAT, 3912},
+ {0xFC79, 0, 2 | DECOMP_COMPAT, 3914},
+ {0xFC7A, 0, 2 | DECOMP_COMPAT, 3916},
+ {0xFC7B, 0, 2 | DECOMP_COMPAT, 3918},
+ {0xFC7C, 0, 2 | DECOMP_COMPAT, 3920},
+ {0xFC7D, 0, 2 | DECOMP_COMPAT, 3922},
+ {0xFC7E, 0, 2 | DECOMP_COMPAT, 3924},
+ {0xFC7F, 0, 2 | DECOMP_COMPAT, 3926},
+ {0xFC80, 0, 2 | DECOMP_COMPAT, 3928},
+ {0xFC81, 0, 2 | DECOMP_COMPAT, 3930},
+ {0xFC82, 0, 2 | DECOMP_COMPAT, 3932},
+ {0xFC83, 0, 2 | DECOMP_COMPAT, 3934},
+ {0xFC84, 0, 2 | DECOMP_COMPAT, 3936},
+ {0xFC85, 0, 2 | DECOMP_COMPAT, 3938},
+ {0xFC86, 0, 2 | DECOMP_COMPAT, 3940},
+ {0xFC87, 0, 2 | DECOMP_COMPAT, 3942},
+ {0xFC88, 0, 2 | DECOMP_COMPAT, 3944},
+ {0xFC89, 0, 2 | DECOMP_COMPAT, 3946},
+ {0xFC8A, 0, 2 | DECOMP_COMPAT, 3948},
+ {0xFC8B, 0, 2 | DECOMP_COMPAT, 3950},
+ {0xFC8C, 0, 2 | DECOMP_COMPAT, 3952},
+ {0xFC8D, 0, 2 | DECOMP_COMPAT, 3954},
+ {0xFC8E, 0, 2 | DECOMP_COMPAT, 3956},
+ {0xFC8F, 0, 2 | DECOMP_COMPAT, 3958},
+ {0xFC90, 0, 2 | DECOMP_COMPAT, 3960},
+ {0xFC91, 0, 2 | DECOMP_COMPAT, 3962},
+ {0xFC92, 0, 2 | DECOMP_COMPAT, 3964},
+ {0xFC93, 0, 2 | DECOMP_COMPAT, 3966},
+ {0xFC94, 0, 2 | DECOMP_COMPAT, 3968},
+ {0xFC95, 0, 2 | DECOMP_COMPAT, 3970},
+ {0xFC96, 0, 2 | DECOMP_COMPAT, 3972},
+ {0xFC97, 0, 2 | DECOMP_COMPAT, 3974},
+ {0xFC98, 0, 2 | DECOMP_COMPAT, 3976},
+ {0xFC99, 0, 2 | DECOMP_COMPAT, 3978},
+ {0xFC9A, 0, 2 | DECOMP_COMPAT, 3980},
+ {0xFC9B, 0, 2 | DECOMP_COMPAT, 3982},
+ {0xFC9C, 0, 2 | DECOMP_COMPAT, 3984},
+ {0xFC9D, 0, 2 | DECOMP_COMPAT, 3986},
+ {0xFC9E, 0, 2 | DECOMP_COMPAT, 3988},
+ {0xFC9F, 0, 2 | DECOMP_COMPAT, 3990},
+ {0xFCA0, 0, 2 | DECOMP_COMPAT, 3992},
+ {0xFCA1, 0, 2 | DECOMP_COMPAT, 3994},
+ {0xFCA2, 0, 2 | DECOMP_COMPAT, 3996},
+ {0xFCA3, 0, 2 | DECOMP_COMPAT, 3998},
+ {0xFCA4, 0, 2 | DECOMP_COMPAT, 4000},
+ {0xFCA5, 0, 2 | DECOMP_COMPAT, 4002},
+ {0xFCA6, 0, 2 | DECOMP_COMPAT, 4004},
+ {0xFCA7, 0, 2 | DECOMP_COMPAT, 4006},
+ {0xFCA8, 0, 2 | DECOMP_COMPAT, 4008},
+ {0xFCA9, 0, 2 | DECOMP_COMPAT, 4010},
+ {0xFCAA, 0, 2 | DECOMP_COMPAT, 4012},
+ {0xFCAB, 0, 2 | DECOMP_COMPAT, 4014},
+ {0xFCAC, 0, 2 | DECOMP_COMPAT, 4016},
+ {0xFCAD, 0, 2 | DECOMP_COMPAT, 4018},
+ {0xFCAE, 0, 2 | DECOMP_COMPAT, 4020},
+ {0xFCAF, 0, 2 | DECOMP_COMPAT, 4022},
+ {0xFCB0, 0, 2 | DECOMP_COMPAT, 4024},
+ {0xFCB1, 0, 2 | DECOMP_COMPAT, 4026},
+ {0xFCB2, 0, 2 | DECOMP_COMPAT, 4028},
+ {0xFCB3, 0, 2 | DECOMP_COMPAT, 4030},
+ {0xFCB4, 0, 2 | DECOMP_COMPAT, 4032},
+ {0xFCB5, 0, 2 | DECOMP_COMPAT, 4034},
+ {0xFCB6, 0, 2 | DECOMP_COMPAT, 4036},
+ {0xFCB7, 0, 2 | DECOMP_COMPAT, 4038},
+ {0xFCB8, 0, 2 | DECOMP_COMPAT, 4040},
+ {0xFCB9, 0, 2 | DECOMP_COMPAT, 4042},
+ {0xFCBA, 0, 2 | DECOMP_COMPAT, 4044},
+ {0xFCBB, 0, 2 | DECOMP_COMPAT, 4046},
+ {0xFCBC, 0, 2 | DECOMP_COMPAT, 4048},
+ {0xFCBD, 0, 2 | DECOMP_COMPAT, 4050},
+ {0xFCBE, 0, 2 | DECOMP_COMPAT, 4052},
+ {0xFCBF, 0, 2 | DECOMP_COMPAT, 4054},
+ {0xFCC0, 0, 2 | DECOMP_COMPAT, 4056},
+ {0xFCC1, 0, 2 | DECOMP_COMPAT, 4058},
+ {0xFCC2, 0, 2 | DECOMP_COMPAT, 4060},
+ {0xFCC3, 0, 2 | DECOMP_COMPAT, 4062},
+ {0xFCC4, 0, 2 | DECOMP_COMPAT, 4064},
+ {0xFCC5, 0, 2 | DECOMP_COMPAT, 4066},
+ {0xFCC6, 0, 2 | DECOMP_COMPAT, 4068},
+ {0xFCC7, 0, 2 | DECOMP_COMPAT, 4070},
+ {0xFCC8, 0, 2 | DECOMP_COMPAT, 4072},
+ {0xFCC9, 0, 2 | DECOMP_COMPAT, 4074},
+ {0xFCCA, 0, 2 | DECOMP_COMPAT, 4076},
+ {0xFCCB, 0, 2 | DECOMP_COMPAT, 4078},
+ {0xFCCC, 0, 2 | DECOMP_COMPAT, 4080},
+ {0xFCCD, 0, 2 | DECOMP_COMPAT, 4082},
+ {0xFCCE, 0, 2 | DECOMP_COMPAT, 4084},
+ {0xFCCF, 0, 2 | DECOMP_COMPAT, 4086},
+ {0xFCD0, 0, 2 | DECOMP_COMPAT, 4088},
+ {0xFCD1, 0, 2 | DECOMP_COMPAT, 4090},
+ {0xFCD2, 0, 2 | DECOMP_COMPAT, 4092},
+ {0xFCD3, 0, 2 | DECOMP_COMPAT, 4094},
+ {0xFCD4, 0, 2 | DECOMP_COMPAT, 4096},
+ {0xFCD5, 0, 2 | DECOMP_COMPAT, 4098},
+ {0xFCD6, 0, 2 | DECOMP_COMPAT, 4100},
+ {0xFCD7, 0, 2 | DECOMP_COMPAT, 4102},
+ {0xFCD8, 0, 2 | DECOMP_COMPAT, 4104},
+ {0xFCD9, 0, 2 | DECOMP_COMPAT, 4106},
+ {0xFCDA, 0, 2 | DECOMP_COMPAT, 4108},
+ {0xFCDB, 0, 2 | DECOMP_COMPAT, 4110},
+ {0xFCDC, 0, 2 | DECOMP_COMPAT, 4112},
+ {0xFCDD, 0, 2 | DECOMP_COMPAT, 4114},
+ {0xFCDE, 0, 2 | DECOMP_COMPAT, 4116},
+ {0xFCDF, 0, 2 | DECOMP_COMPAT, 4118},
+ {0xFCE0, 0, 2 | DECOMP_COMPAT, 4120},
+ {0xFCE1, 0, 2 | DECOMP_COMPAT, 4122},
+ {0xFCE2, 0, 2 | DECOMP_COMPAT, 4124},
+ {0xFCE3, 0, 2 | DECOMP_COMPAT, 4126},
+ {0xFCE4, 0, 2 | DECOMP_COMPAT, 4128},
+ {0xFCE5, 0, 2 | DECOMP_COMPAT, 4130},
+ {0xFCE6, 0, 2 | DECOMP_COMPAT, 4132},
+ {0xFCE7, 0, 2 | DECOMP_COMPAT, 4134},
+ {0xFCE8, 0, 2 | DECOMP_COMPAT, 4136},
+ {0xFCE9, 0, 2 | DECOMP_COMPAT, 4138},
+ {0xFCEA, 0, 2 | DECOMP_COMPAT, 4140},
+ {0xFCEB, 0, 2 | DECOMP_COMPAT, 4142},
+ {0xFCEC, 0, 2 | DECOMP_COMPAT, 4144},
+ {0xFCED, 0, 2 | DECOMP_COMPAT, 4146},
+ {0xFCEE, 0, 2 | DECOMP_COMPAT, 4148},
+ {0xFCEF, 0, 2 | DECOMP_COMPAT, 4150},
+ {0xFCF0, 0, 2 | DECOMP_COMPAT, 4152},
+ {0xFCF1, 0, 2 | DECOMP_COMPAT, 4154},
+ {0xFCF2, 0, 3 | DECOMP_COMPAT, 4156},
+ {0xFCF3, 0, 3 | DECOMP_COMPAT, 4159},
+ {0xFCF4, 0, 3 | DECOMP_COMPAT, 4162},
+ {0xFCF5, 0, 2 | DECOMP_COMPAT, 4165},
+ {0xFCF6, 0, 2 | DECOMP_COMPAT, 4167},
+ {0xFCF7, 0, 2 | DECOMP_COMPAT, 4169},
+ {0xFCF8, 0, 2 | DECOMP_COMPAT, 4171},
+ {0xFCF9, 0, 2 | DECOMP_COMPAT, 4173},
+ {0xFCFA, 0, 2 | DECOMP_COMPAT, 4175},
+ {0xFCFB, 0, 2 | DECOMP_COMPAT, 4177},
+ {0xFCFC, 0, 2 | DECOMP_COMPAT, 4179},
+ {0xFCFD, 0, 2 | DECOMP_COMPAT, 4181},
+ {0xFCFE, 0, 2 | DECOMP_COMPAT, 4183},
+ {0xFCFF, 0, 2 | DECOMP_COMPAT, 4185},
+ {0xFD00, 0, 2 | DECOMP_COMPAT, 4187},
+ {0xFD01, 0, 2 | DECOMP_COMPAT, 4189},
+ {0xFD02, 0, 2 | DECOMP_COMPAT, 4191},
+ {0xFD03, 0, 2 | DECOMP_COMPAT, 4193},
+ {0xFD04, 0, 2 | DECOMP_COMPAT, 4195},
+ {0xFD05, 0, 2 | DECOMP_COMPAT, 4197},
+ {0xFD06, 0, 2 | DECOMP_COMPAT, 4199},
+ {0xFD07, 0, 2 | DECOMP_COMPAT, 4201},
+ {0xFD08, 0, 2 | DECOMP_COMPAT, 4203},
+ {0xFD09, 0, 2 | DECOMP_COMPAT, 4205},
+ {0xFD0A, 0, 2 | DECOMP_COMPAT, 4207},
+ {0xFD0B, 0, 2 | DECOMP_COMPAT, 4209},
+ {0xFD0C, 0, 2 | DECOMP_COMPAT, 4211},
+ {0xFD0D, 0, 2 | DECOMP_COMPAT, 4213},
+ {0xFD0E, 0, 2 | DECOMP_COMPAT, 4215},
+ {0xFD0F, 0, 2 | DECOMP_COMPAT, 4217},
+ {0xFD10, 0, 2 | DECOMP_COMPAT, 4219},
+ {0xFD11, 0, 2 | DECOMP_COMPAT, 4221},
+ {0xFD12, 0, 2 | DECOMP_COMPAT, 4223},
+ {0xFD13, 0, 2 | DECOMP_COMPAT, 4225},
+ {0xFD14, 0, 2 | DECOMP_COMPAT, 4227},
+ {0xFD15, 0, 2 | DECOMP_COMPAT, 4229},
+ {0xFD16, 0, 2 | DECOMP_COMPAT, 4231},
+ {0xFD17, 0, 2 | DECOMP_COMPAT, 4233},
+ {0xFD18, 0, 2 | DECOMP_COMPAT, 4235},
+ {0xFD19, 0, 2 | DECOMP_COMPAT, 4237},
+ {0xFD1A, 0, 2 | DECOMP_COMPAT, 4239},
+ {0xFD1B, 0, 2 | DECOMP_COMPAT, 4241},
+ {0xFD1C, 0, 2 | DECOMP_COMPAT, 4243},
+ {0xFD1D, 0, 2 | DECOMP_COMPAT, 4245},
+ {0xFD1E, 0, 2 | DECOMP_COMPAT, 4247},
+ {0xFD1F, 0, 2 | DECOMP_COMPAT, 4249},
+ {0xFD20, 0, 2 | DECOMP_COMPAT, 4251},
+ {0xFD21, 0, 2 | DECOMP_COMPAT, 4253},
+ {0xFD22, 0, 2 | DECOMP_COMPAT, 4255},
+ {0xFD23, 0, 2 | DECOMP_COMPAT, 4257},
+ {0xFD24, 0, 2 | DECOMP_COMPAT, 4259},
+ {0xFD25, 0, 2 | DECOMP_COMPAT, 4261},
+ {0xFD26, 0, 2 | DECOMP_COMPAT, 4263},
+ {0xFD27, 0, 2 | DECOMP_COMPAT, 4265},
+ {0xFD28, 0, 2 | DECOMP_COMPAT, 4267},
+ {0xFD29, 0, 2 | DECOMP_COMPAT, 4269},
+ {0xFD2A, 0, 2 | DECOMP_COMPAT, 4271},
+ {0xFD2B, 0, 2 | DECOMP_COMPAT, 4273},
+ {0xFD2C, 0, 2 | DECOMP_COMPAT, 4275},
+ {0xFD2D, 0, 2 | DECOMP_COMPAT, 4277},
+ {0xFD2E, 0, 2 | DECOMP_COMPAT, 4279},
+ {0xFD2F, 0, 2 | DECOMP_COMPAT, 4281},
+ {0xFD30, 0, 2 | DECOMP_COMPAT, 4283},
+ {0xFD31, 0, 2 | DECOMP_COMPAT, 4285},
+ {0xFD32, 0, 2 | DECOMP_COMPAT, 4287},
+ {0xFD33, 0, 2 | DECOMP_COMPAT, 4289},
+ {0xFD34, 0, 2 | DECOMP_COMPAT, 4291},
+ {0xFD35, 0, 2 | DECOMP_COMPAT, 4293},
+ {0xFD36, 0, 2 | DECOMP_COMPAT, 4295},
+ {0xFD37, 0, 2 | DECOMP_COMPAT, 4297},
+ {0xFD38, 0, 2 | DECOMP_COMPAT, 4299},
+ {0xFD39, 0, 2 | DECOMP_COMPAT, 4301},
+ {0xFD3A, 0, 2 | DECOMP_COMPAT, 4303},
+ {0xFD3B, 0, 2 | DECOMP_COMPAT, 4305},
+ {0xFD3C, 0, 2 | DECOMP_COMPAT, 4307},
+ {0xFD3D, 0, 2 | DECOMP_COMPAT, 4309},
+ {0xFD50, 0, 3 | DECOMP_COMPAT, 4311},
+ {0xFD51, 0, 3 | DECOMP_COMPAT, 4314},
+ {0xFD52, 0, 3 | DECOMP_COMPAT, 4317},
+ {0xFD53, 0, 3 | DECOMP_COMPAT, 4320},
+ {0xFD54, 0, 3 | DECOMP_COMPAT, 4323},
+ {0xFD55, 0, 3 | DECOMP_COMPAT, 4326},
+ {0xFD56, 0, 3 | DECOMP_COMPAT, 4329},
+ {0xFD57, 0, 3 | DECOMP_COMPAT, 4332},
+ {0xFD58, 0, 3 | DECOMP_COMPAT, 4335},
+ {0xFD59, 0, 3 | DECOMP_COMPAT, 4338},
+ {0xFD5A, 0, 3 | DECOMP_COMPAT, 4341},
+ {0xFD5B, 0, 3 | DECOMP_COMPAT, 4344},
+ {0xFD5C, 0, 3 | DECOMP_COMPAT, 4347},
+ {0xFD5D, 0, 3 | DECOMP_COMPAT, 4350},
+ {0xFD5E, 0, 3 | DECOMP_COMPAT, 4353},
+ {0xFD5F, 0, 3 | DECOMP_COMPAT, 4356},
+ {0xFD60, 0, 3 | DECOMP_COMPAT, 4359},
+ {0xFD61, 0, 3 | DECOMP_COMPAT, 4362},
+ {0xFD62, 0, 3 | DECOMP_COMPAT, 4365},
+ {0xFD63, 0, 3 | DECOMP_COMPAT, 4368},
+ {0xFD64, 0, 3 | DECOMP_COMPAT, 4371},
+ {0xFD65, 0, 3 | DECOMP_COMPAT, 4374},
+ {0xFD66, 0, 3 | DECOMP_COMPAT, 4377},
+ {0xFD67, 0, 3 | DECOMP_COMPAT, 4380},
+ {0xFD68, 0, 3 | DECOMP_COMPAT, 4383},
+ {0xFD69, 0, 3 | DECOMP_COMPAT, 4386},
+ {0xFD6A, 0, 3 | DECOMP_COMPAT, 4389},
+ {0xFD6B, 0, 3 | DECOMP_COMPAT, 4392},
+ {0xFD6C, 0, 3 | DECOMP_COMPAT, 4395},
+ {0xFD6D, 0, 3 | DECOMP_COMPAT, 4398},
+ {0xFD6E, 0, 3 | DECOMP_COMPAT, 4401},
+ {0xFD6F, 0, 3 | DECOMP_COMPAT, 4404},
+ {0xFD70, 0, 3 | DECOMP_COMPAT, 4407},
+ {0xFD71, 0, 3 | DECOMP_COMPAT, 4410},
+ {0xFD72, 0, 3 | DECOMP_COMPAT, 4413},
+ {0xFD73, 0, 3 | DECOMP_COMPAT, 4416},
+ {0xFD74, 0, 3 | DECOMP_COMPAT, 4419},
+ {0xFD75, 0, 3 | DECOMP_COMPAT, 4422},
+ {0xFD76, 0, 3 | DECOMP_COMPAT, 4425},
+ {0xFD77, 0, 3 | DECOMP_COMPAT, 4428},
+ {0xFD78, 0, 3 | DECOMP_COMPAT, 4431},
+ {0xFD79, 0, 3 | DECOMP_COMPAT, 4434},
+ {0xFD7A, 0, 3 | DECOMP_COMPAT, 4437},
+ {0xFD7B, 0, 3 | DECOMP_COMPAT, 4440},
+ {0xFD7C, 0, 3 | DECOMP_COMPAT, 4443},
+ {0xFD7D, 0, 3 | DECOMP_COMPAT, 4446},
+ {0xFD7E, 0, 3 | DECOMP_COMPAT, 4449},
+ {0xFD7F, 0, 3 | DECOMP_COMPAT, 4452},
+ {0xFD80, 0, 3 | DECOMP_COMPAT, 4455},
+ {0xFD81, 0, 3 | DECOMP_COMPAT, 4458},
+ {0xFD82, 0, 3 | DECOMP_COMPAT, 4461},
+ {0xFD83, 0, 3 | DECOMP_COMPAT, 4464},
+ {0xFD84, 0, 3 | DECOMP_COMPAT, 4467},
+ {0xFD85, 0, 3 | DECOMP_COMPAT, 4470},
+ {0xFD86, 0, 3 | DECOMP_COMPAT, 4473},
+ {0xFD87, 0, 3 | DECOMP_COMPAT, 4476},
+ {0xFD88, 0, 3 | DECOMP_COMPAT, 4479},
+ {0xFD89, 0, 3 | DECOMP_COMPAT, 4482},
+ {0xFD8A, 0, 3 | DECOMP_COMPAT, 4485},
+ {0xFD8B, 0, 3 | DECOMP_COMPAT, 4488},
+ {0xFD8C, 0, 3 | DECOMP_COMPAT, 4491},
+ {0xFD8D, 0, 3 | DECOMP_COMPAT, 4494},
+ {0xFD8E, 0, 3 | DECOMP_COMPAT, 4497},
+ {0xFD8F, 0, 3 | DECOMP_COMPAT, 4500},
+ {0xFD92, 0, 3 | DECOMP_COMPAT, 4503},
+ {0xFD93, 0, 3 | DECOMP_COMPAT, 4506},
+ {0xFD94, 0, 3 | DECOMP_COMPAT, 4509},
+ {0xFD95, 0, 3 | DECOMP_COMPAT, 4512},
+ {0xFD96, 0, 3 | DECOMP_COMPAT, 4515},
+ {0xFD97, 0, 3 | DECOMP_COMPAT, 4518},
+ {0xFD98, 0, 3 | DECOMP_COMPAT, 4521},
+ {0xFD99, 0, 3 | DECOMP_COMPAT, 4524},
+ {0xFD9A, 0, 3 | DECOMP_COMPAT, 4527},
+ {0xFD9B, 0, 3 | DECOMP_COMPAT, 4530},
+ {0xFD9C, 0, 3 | DECOMP_COMPAT, 4533},
+ {0xFD9D, 0, 3 | DECOMP_COMPAT, 4536},
+ {0xFD9E, 0, 3 | DECOMP_COMPAT, 4539},
+ {0xFD9F, 0, 3 | DECOMP_COMPAT, 4542},
+ {0xFDA0, 0, 3 | DECOMP_COMPAT, 4545},
+ {0xFDA1, 0, 3 | DECOMP_COMPAT, 4548},
+ {0xFDA2, 0, 3 | DECOMP_COMPAT, 4551},
+ {0xFDA3, 0, 3 | DECOMP_COMPAT, 4554},
+ {0xFDA4, 0, 3 | DECOMP_COMPAT, 4557},
+ {0xFDA5, 0, 3 | DECOMP_COMPAT, 4560},
+ {0xFDA6, 0, 3 | DECOMP_COMPAT, 4563},
+ {0xFDA7, 0, 3 | DECOMP_COMPAT, 4566},
+ {0xFDA8, 0, 3 | DECOMP_COMPAT, 4569},
+ {0xFDA9, 0, 3 | DECOMP_COMPAT, 4572},
+ {0xFDAA, 0, 3 | DECOMP_COMPAT, 4575},
+ {0xFDAB, 0, 3 | DECOMP_COMPAT, 4578},
+ {0xFDAC, 0, 3 | DECOMP_COMPAT, 4581},
+ {0xFDAD, 0, 3 | DECOMP_COMPAT, 4584},
+ {0xFDAE, 0, 3 | DECOMP_COMPAT, 4587},
+ {0xFDAF, 0, 3 | DECOMP_COMPAT, 4590},
+ {0xFDB0, 0, 3 | DECOMP_COMPAT, 4593},
+ {0xFDB1, 0, 3 | DECOMP_COMPAT, 4596},
+ {0xFDB2, 0, 3 | DECOMP_COMPAT, 4599},
+ {0xFDB3, 0, 3 | DECOMP_COMPAT, 4602},
+ {0xFDB4, 0, 3 | DECOMP_COMPAT, 4605},
+ {0xFDB5, 0, 3 | DECOMP_COMPAT, 4608},
+ {0xFDB6, 0, 3 | DECOMP_COMPAT, 4611},
+ {0xFDB7, 0, 3 | DECOMP_COMPAT, 4614},
+ {0xFDB8, 0, 3 | DECOMP_COMPAT, 4617},
+ {0xFDB9, 0, 3 | DECOMP_COMPAT, 4620},
+ {0xFDBA, 0, 3 | DECOMP_COMPAT, 4623},
+ {0xFDBB, 0, 3 | DECOMP_COMPAT, 4626},
+ {0xFDBC, 0, 3 | DECOMP_COMPAT, 4629},
+ {0xFDBD, 0, 3 | DECOMP_COMPAT, 4632},
+ {0xFDBE, 0, 3 | DECOMP_COMPAT, 4635},
+ {0xFDBF, 0, 3 | DECOMP_COMPAT, 4638},
+ {0xFDC0, 0, 3 | DECOMP_COMPAT, 4641},
+ {0xFDC1, 0, 3 | DECOMP_COMPAT, 4644},
+ {0xFDC2, 0, 3 | DECOMP_COMPAT, 4647},
+ {0xFDC3, 0, 3 | DECOMP_COMPAT, 4650},
+ {0xFDC4, 0, 3 | DECOMP_COMPAT, 4653},
+ {0xFDC5, 0, 3 | DECOMP_COMPAT, 4656},
+ {0xFDC6, 0, 3 | DECOMP_COMPAT, 4659},
+ {0xFDC7, 0, 3 | DECOMP_COMPAT, 4662},
+ {0xFDF0, 0, 3 | DECOMP_COMPAT, 4665},
+ {0xFDF1, 0, 3 | DECOMP_COMPAT, 4668},
+ {0xFDF2, 0, 4 | DECOMP_COMPAT, 4671},
+ {0xFDF3, 0, 4 | DECOMP_COMPAT, 4675},
+ {0xFDF4, 0, 4 | DECOMP_COMPAT, 4679},
+ {0xFDF5, 0, 4 | DECOMP_COMPAT, 4683},
+ {0xFDF6, 0, 4 | DECOMP_COMPAT, 4687},
+ {0xFDF7, 0, 4 | DECOMP_COMPAT, 4691},
+ {0xFDF8, 0, 4 | DECOMP_COMPAT, 4695},
+ {0xFDF9, 0, 3 | DECOMP_COMPAT, 4699},
+ {0xFDFA, 0, 18 | DECOMP_COMPAT, 4702},
+ {0xFDFB, 0, 8 | DECOMP_COMPAT, 4720},
+ {0xFDFC, 0, 4 | DECOMP_COMPAT, 4728},
+ {0xFE10, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x002C},
+ {0xFE11, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3001},
+ {0xFE12, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3002},
+ {0xFE13, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x003A},
+ {0xFE14, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x003B},
+ {0xFE15, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0021},
+ {0xFE16, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x003F},
+ {0xFE17, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3016},
+ {0xFE18, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3017},
+ {0xFE19, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2026},
+ {0xFE20, 230, 0, 0},
+ {0xFE21, 230, 0, 0},
+ {0xFE22, 230, 0, 0},
+ {0xFE23, 230, 0, 0},
+ {0xFE24, 230, 0, 0},
+ {0xFE25, 230, 0, 0},
+ {0xFE26, 230, 0, 0},
+ {0xFE27, 220, 0, 0},
+ {0xFE28, 220, 0, 0},
+ {0xFE29, 220, 0, 0},
+ {0xFE2A, 220, 0, 0},
+ {0xFE2B, 220, 0, 0},
+ {0xFE2C, 220, 0, 0},
+ {0xFE2D, 220, 0, 0},
+ {0xFE2E, 230, 0, 0},
+ {0xFE2F, 230, 0, 0},
+ {0xFE30, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2025},
+ {0xFE31, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2014},
+ {0xFE32, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2013},
+ {0xFE33, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005F},
+ {0xFE34, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005F},
+ {0xFE35, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0028},
+ {0xFE36, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0029},
+ {0xFE37, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007B},
+ {0xFE38, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007D},
+ {0xFE39, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3014},
+ {0xFE3A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3015},
+ {0xFE3B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3010},
+ {0xFE3C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3011},
+ {0xFE3D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x300A},
+ {0xFE3E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x300B},
+ {0xFE3F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3008},
+ {0xFE40, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3009},
+ {0xFE41, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x300C},
+ {0xFE42, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x300D},
+ {0xFE43, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x300E},
+ {0xFE44, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x300F},
+ {0xFE47, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005B},
+ {0xFE48, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005D},
+ {0xFE49, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x203E},
+ {0xFE4A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x203E},
+ {0xFE4B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x203E},
+ {0xFE4C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x203E},
+ {0xFE4D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005F},
+ {0xFE4E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005F},
+ {0xFE4F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005F},
+ {0xFE50, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x002C},
+ {0xFE51, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3001},
+ {0xFE52, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x002E},
+ {0xFE54, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x003B},
+ {0xFE55, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x003A},
+ {0xFE56, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x003F},
+ {0xFE57, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0021},
+ {0xFE58, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2014},
+ {0xFE59, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0028},
+ {0xFE5A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0029},
+ {0xFE5B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007B},
+ {0xFE5C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007D},
+ {0xFE5D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3014},
+ {0xFE5E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3015},
+ {0xFE5F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0023},
+ {0xFE60, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0026},
+ {0xFE61, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x002A},
+ {0xFE62, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x002B},
+ {0xFE63, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x002D},
+ {0xFE64, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x003C},
+ {0xFE65, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x003E},
+ {0xFE66, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x003D},
+ {0xFE68, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005C},
+ {0xFE69, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0024},
+ {0xFE6A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0025},
+ {0xFE6B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0040},
+ {0xFE70, 0, 2 | DECOMP_COMPAT, 4732},
+ {0xFE71, 0, 2 | DECOMP_COMPAT, 4734},
+ {0xFE72, 0, 2 | DECOMP_COMPAT, 4736},
+ {0xFE74, 0, 2 | DECOMP_COMPAT, 4738},
+ {0xFE76, 0, 2 | DECOMP_COMPAT, 4740},
+ {0xFE77, 0, 2 | DECOMP_COMPAT, 4742},
+ {0xFE78, 0, 2 | DECOMP_COMPAT, 4744},
+ {0xFE79, 0, 2 | DECOMP_COMPAT, 4746},
+ {0xFE7A, 0, 2 | DECOMP_COMPAT, 4748},
+ {0xFE7B, 0, 2 | DECOMP_COMPAT, 4750},
+ {0xFE7C, 0, 2 | DECOMP_COMPAT, 4752},
+ {0xFE7D, 0, 2 | DECOMP_COMPAT, 4754},
+ {0xFE7E, 0, 2 | DECOMP_COMPAT, 4756},
+ {0xFE7F, 0, 2 | DECOMP_COMPAT, 4758},
+ {0xFE80, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0621},
+ {0xFE81, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0622},
+ {0xFE82, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0622},
+ {0xFE83, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0623},
+ {0xFE84, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0623},
+ {0xFE85, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0624},
+ {0xFE86, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0624},
+ {0xFE87, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0625},
+ {0xFE88, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0625},
+ {0xFE89, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0626},
+ {0xFE8A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0626},
+ {0xFE8B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0626},
+ {0xFE8C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0626},
+ {0xFE8D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0627},
+ {0xFE8E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0627},
+ {0xFE8F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0628},
+ {0xFE90, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0628},
+ {0xFE91, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0628},
+ {0xFE92, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0628},
+ {0xFE93, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0629},
+ {0xFE94, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0629},
+ {0xFE95, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062A},
+ {0xFE96, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062A},
+ {0xFE97, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062A},
+ {0xFE98, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062A},
+ {0xFE99, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062B},
+ {0xFE9A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062B},
+ {0xFE9B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062B},
+ {0xFE9C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062B},
+ {0xFE9D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062C},
+ {0xFE9E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062C},
+ {0xFE9F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062C},
+ {0xFEA0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062C},
+ {0xFEA1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062D},
+ {0xFEA2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062D},
+ {0xFEA3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062D},
+ {0xFEA4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062D},
+ {0xFEA5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062E},
+ {0xFEA6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062E},
+ {0xFEA7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062E},
+ {0xFEA8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062E},
+ {0xFEA9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062F},
+ {0xFEAA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062F},
+ {0xFEAB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0630},
+ {0xFEAC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0630},
+ {0xFEAD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0631},
+ {0xFEAE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0631},
+ {0xFEAF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0632},
+ {0xFEB0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0632},
+ {0xFEB1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0633},
+ {0xFEB2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0633},
+ {0xFEB3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0633},
+ {0xFEB4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0633},
+ {0xFEB5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0634},
+ {0xFEB6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0634},
+ {0xFEB7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0634},
+ {0xFEB8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0634},
+ {0xFEB9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0635},
+ {0xFEBA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0635},
+ {0xFEBB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0635},
+ {0xFEBC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0635},
+ {0xFEBD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0636},
+ {0xFEBE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0636},
+ {0xFEBF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0636},
+ {0xFEC0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0636},
+ {0xFEC1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0637},
+ {0xFEC2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0637},
+ {0xFEC3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0637},
+ {0xFEC4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0637},
+ {0xFEC5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0638},
+ {0xFEC6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0638},
+ {0xFEC7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0638},
+ {0xFEC8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0638},
+ {0xFEC9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0639},
+ {0xFECA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0639},
+ {0xFECB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0639},
+ {0xFECC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0639},
+ {0xFECD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x063A},
+ {0xFECE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x063A},
+ {0xFECF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x063A},
+ {0xFED0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x063A},
+ {0xFED1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0641},
+ {0xFED2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0641},
+ {0xFED3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0641},
+ {0xFED4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0641},
+ {0xFED5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0642},
+ {0xFED6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0642},
+ {0xFED7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0642},
+ {0xFED8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0642},
+ {0xFED9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0643},
+ {0xFEDA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0643},
+ {0xFEDB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0643},
+ {0xFEDC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0643},
+ {0xFEDD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0644},
+ {0xFEDE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0644},
+ {0xFEDF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0644},
+ {0xFEE0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0644},
+ {0xFEE1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0645},
+ {0xFEE2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0645},
+ {0xFEE3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0645},
+ {0xFEE4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0645},
+ {0xFEE5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0646},
+ {0xFEE6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0646},
+ {0xFEE7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0646},
+ {0xFEE8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0646},
+ {0xFEE9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0647},
+ {0xFEEA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0647},
+ {0xFEEB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0647},
+ {0xFEEC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0647},
+ {0xFEED, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0648},
+ {0xFEEE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0648},
+ {0xFEEF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0649},
+ {0xFEF0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0649},
+ {0xFEF1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x064A},
+ {0xFEF2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x064A},
+ {0xFEF3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x064A},
+ {0xFEF4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x064A},
+ {0xFEF5, 0, 2 | DECOMP_COMPAT, 4760},
+ {0xFEF6, 0, 2 | DECOMP_COMPAT, 4762},
+ {0xFEF7, 0, 2 | DECOMP_COMPAT, 4764},
+ {0xFEF8, 0, 2 | DECOMP_COMPAT, 4766},
+ {0xFEF9, 0, 2 | DECOMP_COMPAT, 4768},
+ {0xFEFA, 0, 2 | DECOMP_COMPAT, 4770},
+ {0xFEFB, 0, 2 | DECOMP_COMPAT, 4772},
+ {0xFEFC, 0, 2 | DECOMP_COMPAT, 4774},
+ {0xFF01, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0021},
+ {0xFF02, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0022},
+ {0xFF03, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0023},
+ {0xFF04, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0024},
+ {0xFF05, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0025},
+ {0xFF06, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0026},
+ {0xFF07, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0027},
+ {0xFF08, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0028},
+ {0xFF09, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0029},
+ {0xFF0A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x002A},
+ {0xFF0B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x002B},
+ {0xFF0C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x002C},
+ {0xFF0D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x002D},
+ {0xFF0E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x002E},
+ {0xFF0F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x002F},
+ {0xFF10, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0030},
+ {0xFF11, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0031},
+ {0xFF12, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0032},
+ {0xFF13, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0033},
+ {0xFF14, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0034},
+ {0xFF15, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0035},
+ {0xFF16, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0036},
+ {0xFF17, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0037},
+ {0xFF18, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0038},
+ {0xFF19, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0039},
+ {0xFF1A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x003A},
+ {0xFF1B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x003B},
+ {0xFF1C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x003C},
+ {0xFF1D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x003D},
+ {0xFF1E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x003E},
+ {0xFF1F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x003F},
+ {0xFF20, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0040},
+ {0xFF21, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0041},
+ {0xFF22, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0042},
+ {0xFF23, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0043},
+ {0xFF24, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0044},
+ {0xFF25, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0045},
+ {0xFF26, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0046},
+ {0xFF27, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0047},
+ {0xFF28, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0048},
+ {0xFF29, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0049},
+ {0xFF2A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004A},
+ {0xFF2B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004B},
+ {0xFF2C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004C},
+ {0xFF2D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004D},
+ {0xFF2E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004E},
+ {0xFF2F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004F},
+ {0xFF30, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0050},
+ {0xFF31, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0051},
+ {0xFF32, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0052},
+ {0xFF33, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0053},
+ {0xFF34, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0054},
+ {0xFF35, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0055},
+ {0xFF36, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0056},
+ {0xFF37, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0057},
+ {0xFF38, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0058},
+ {0xFF39, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0059},
+ {0xFF3A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005A},
+ {0xFF3B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005B},
+ {0xFF3C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005C},
+ {0xFF3D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005D},
+ {0xFF3E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005E},
+ {0xFF3F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005F},
+ {0xFF40, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0060},
+ {0xFF41, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0061},
+ {0xFF42, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0062},
+ {0xFF43, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0063},
+ {0xFF44, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0064},
+ {0xFF45, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0065},
+ {0xFF46, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0066},
+ {0xFF47, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0067},
+ {0xFF48, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0068},
+ {0xFF49, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0069},
+ {0xFF4A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006A},
+ {0xFF4B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006B},
+ {0xFF4C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006C},
+ {0xFF4D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006D},
+ {0xFF4E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006E},
+ {0xFF4F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006F},
+ {0xFF50, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0070},
+ {0xFF51, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0071},
+ {0xFF52, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0072},
+ {0xFF53, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0073},
+ {0xFF54, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0074},
+ {0xFF55, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0075},
+ {0xFF56, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0076},
+ {0xFF57, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0077},
+ {0xFF58, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0078},
+ {0xFF59, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0079},
+ {0xFF5A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007A},
+ {0xFF5B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007B},
+ {0xFF5C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007C},
+ {0xFF5D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007D},
+ {0xFF5E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007E},
+ {0xFF5F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2985},
+ {0xFF60, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2986},
+ {0xFF61, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3002},
+ {0xFF62, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x300C},
+ {0xFF63, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x300D},
+ {0xFF64, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3001},
+ {0xFF65, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30FB},
+ {0xFF66, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30F2},
+ {0xFF67, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30A1},
+ {0xFF68, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30A3},
+ {0xFF69, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30A5},
+ {0xFF6A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30A7},
+ {0xFF6B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30A9},
+ {0xFF6C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30E3},
+ {0xFF6D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30E5},
+ {0xFF6E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30E7},
+ {0xFF6F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30C3},
+ {0xFF70, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30FC},
+ {0xFF71, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30A2},
+ {0xFF72, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30A4},
+ {0xFF73, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30A6},
+ {0xFF74, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30A8},
+ {0xFF75, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30AA},
+ {0xFF76, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30AB},
+ {0xFF77, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30AD},
+ {0xFF78, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30AF},
+ {0xFF79, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30B1},
+ {0xFF7A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30B3},
+ {0xFF7B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30B5},
+ {0xFF7C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30B7},
+ {0xFF7D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30B9},
+ {0xFF7E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30BB},
+ {0xFF7F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30BD},
+ {0xFF80, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30BF},
+ {0xFF81, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30C1},
+ {0xFF82, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30C4},
+ {0xFF83, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30C6},
+ {0xFF84, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30C8},
+ {0xFF85, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30CA},
+ {0xFF86, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30CB},
+ {0xFF87, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30CC},
+ {0xFF88, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30CD},
+ {0xFF89, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30CE},
+ {0xFF8A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30CF},
+ {0xFF8B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30D2},
+ {0xFF8C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30D5},
+ {0xFF8D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30D8},
+ {0xFF8E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30DB},
+ {0xFF8F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30DE},
+ {0xFF90, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30DF},
+ {0xFF91, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30E0},
+ {0xFF92, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30E1},
+ {0xFF93, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30E2},
+ {0xFF94, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30E4},
+ {0xFF95, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30E6},
+ {0xFF96, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30E8},
+ {0xFF97, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30E9},
+ {0xFF98, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30EA},
+ {0xFF99, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30EB},
+ {0xFF9A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30EC},
+ {0xFF9B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30ED},
+ {0xFF9C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30EF},
+ {0xFF9D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30F3},
+ {0xFF9E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3099},
+ {0xFF9F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x309A},
+ {0xFFA0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3164},
+ {0xFFA1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3131},
+ {0xFFA2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3132},
+ {0xFFA3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3133},
+ {0xFFA4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3134},
+ {0xFFA5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3135},
+ {0xFFA6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3136},
+ {0xFFA7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3137},
+ {0xFFA8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3138},
+ {0xFFA9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3139},
+ {0xFFAA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x313A},
+ {0xFFAB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x313B},
+ {0xFFAC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x313C},
+ {0xFFAD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x313D},
+ {0xFFAE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x313E},
+ {0xFFAF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x313F},
+ {0xFFB0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3140},
+ {0xFFB1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3141},
+ {0xFFB2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3142},
+ {0xFFB3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3143},
+ {0xFFB4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3144},
+ {0xFFB5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3145},
+ {0xFFB6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3146},
+ {0xFFB7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3147},
+ {0xFFB8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3148},
+ {0xFFB9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3149},
+ {0xFFBA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x314A},
+ {0xFFBB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x314B},
+ {0xFFBC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x314C},
+ {0xFFBD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x314D},
+ {0xFFBE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x314E},
+ {0xFFC2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x314F},
+ {0xFFC3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3150},
+ {0xFFC4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3151},
+ {0xFFC5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3152},
+ {0xFFC6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3153},
+ {0xFFC7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3154},
+ {0xFFCA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3155},
+ {0xFFCB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3156},
+ {0xFFCC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3157},
+ {0xFFCD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3158},
+ {0xFFCE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3159},
+ {0xFFCF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x315A},
+ {0xFFD2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x315B},
+ {0xFFD3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x315C},
+ {0xFFD4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x315D},
+ {0xFFD5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x315E},
+ {0xFFD6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x315F},
+ {0xFFD7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3160},
+ {0xFFDA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3161},
+ {0xFFDB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3162},
+ {0xFFDC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3163},
+ {0xFFE0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x00A2},
+ {0xFFE1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x00A3},
+ {0xFFE2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x00AC},
+ {0xFFE3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x00AF},
+ {0xFFE4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x00A6},
+ {0xFFE5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x00A5},
+ {0xFFE6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x20A9},
+ {0xFFE8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2502},
+ {0xFFE9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2190},
+ {0xFFEA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2191},
+ {0xFFEB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2192},
+ {0xFFEC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2193},
+ {0xFFED, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x25A0},
+ {0xFFEE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x25CB},
+ {0x101FD, 220, 0, 0},
+ {0x102E0, 220, 0, 0},
+ {0x10376, 230, 0, 0},
+ {0x10377, 230, 0, 0},
+ {0x10378, 230, 0, 0},
+ {0x10379, 230, 0, 0},
+ {0x1037A, 230, 0, 0},
+ {0x10781, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x02D0},
+ {0x10782, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x02D1},
+ {0x10783, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x00E6},
+ {0x10784, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0299},
+ {0x10785, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0253},
+ {0x10787, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x02A3},
+ {0x10788, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0xAB66},
+ {0x10789, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x02A5},
+ {0x1078A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x02A4},
+ {0x1078B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0256},
+ {0x1078C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0257},
+ {0x1078D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1D91},
+ {0x1078E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0258},
+ {0x1078F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x025E},
+ {0x10790, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x02A9},
+ {0x10791, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0264},
+ {0x10792, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0262},
+ {0x10793, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0260},
+ {0x10794, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x029B},
+ {0x10795, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0127},
+ {0x10796, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x029C},
+ {0x10797, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0267},
+ {0x10798, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0284},
+ {0x10799, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x02AA},
+ {0x1079A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x02AB},
+ {0x1079B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x026C},
+ {0x1079C, 0, 1 | DECOMP_COMPAT, 4776},
+ {0x1079D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0xA78E},
+ {0x1079E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x026E},
+ {0x1079F, 0, 1 | DECOMP_COMPAT, 4777},
+ {0x107A0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x028E},
+ {0x107A1, 0, 1 | DECOMP_COMPAT, 4778},
+ {0x107A2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x00F8},
+ {0x107A3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0276},
+ {0x107A4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0277},
+ {0x107A5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0071},
+ {0x107A6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x027A},
+ {0x107A7, 0, 1 | DECOMP_COMPAT, 4779},
+ {0x107A8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x027D},
+ {0x107A9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x027E},
+ {0x107AA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0280},
+ {0x107AB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x02A8},
+ {0x107AC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x02A6},
+ {0x107AD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0xAB67},
+ {0x107AE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x02A7},
+ {0x107AF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0288},
+ {0x107B0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2C71},
+ {0x107B2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x028F},
+ {0x107B3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x02A1},
+ {0x107B4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x02A2},
+ {0x107B5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0298},
+ {0x107B6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x01C0},
+ {0x107B7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x01C1},
+ {0x107B8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x01C2},
+ {0x107B9, 0, 1 | DECOMP_COMPAT, 4780},
+ {0x107BA, 0, 1 | DECOMP_COMPAT, 4781},
+ {0x10A0D, 220, 0, 0},
+ {0x10A0F, 230, 0, 0},
+ {0x10A38, 230, 0, 0},
+ {0x10A39, 1, 0, 0},
+ {0x10A3A, 220, 0, 0},
+ {0x10A3F, 9, 0, 0},
+ {0x10AE5, 230, 0, 0},
+ {0x10AE6, 220, 0, 0},
+ {0x10D24, 230, 0, 0},
+ {0x10D25, 230, 0, 0},
+ {0x10D26, 230, 0, 0},
+ {0x10D27, 230, 0, 0},
+ {0x10EAB, 230, 0, 0},
+ {0x10EAC, 230, 0, 0},
+ {0x10EFD, 220, 0, 0},
+ {0x10EFE, 220, 0, 0},
+ {0x10EFF, 220, 0, 0},
+ {0x10F46, 220, 0, 0},
+ {0x10F47, 220, 0, 0},
+ {0x10F48, 230, 0, 0},
+ {0x10F49, 230, 0, 0},
+ {0x10F4A, 230, 0, 0},
+ {0x10F4B, 220, 0, 0},
+ {0x10F4C, 230, 0, 0},
+ {0x10F4D, 220, 0, 0},
+ {0x10F4E, 220, 0, 0},
+ {0x10F4F, 220, 0, 0},
+ {0x10F50, 220, 0, 0},
+ {0x10F82, 230, 0, 0},
+ {0x10F83, 220, 0, 0},
+ {0x10F84, 230, 0, 0},
+ {0x10F85, 220, 0, 0},
+ {0x11046, 9, 0, 0},
+ {0x11070, 9, 0, 0},
+ {0x1107F, 9, 0, 0},
+ {0x1109A, 0, 2, 4782},
+ {0x1109C, 0, 2, 4784},
+ {0x110AB, 0, 2, 4786},
+ {0x110B9, 9, 0, 0},
+ {0x110BA, 7, 0, 0},
+ {0x11100, 230, 0, 0},
+ {0x11101, 230, 0, 0},
+ {0x11102, 230, 0, 0},
+ {0x1112E, 0, 2, 4788},
+ {0x1112F, 0, 2, 4790},
+ {0x11133, 9, 0, 0},
+ {0x11134, 9, 0, 0},
+ {0x11173, 7, 0, 0},
+ {0x111C0, 9, 0, 0},
+ {0x111CA, 7, 0, 0},
+ {0x11235, 9, 0, 0},
+ {0x11236, 7, 0, 0},
+ {0x112E9, 7, 0, 0},
+ {0x112EA, 9, 0, 0},
+ {0x1133B, 7, 0, 0},
+ {0x1133C, 7, 0, 0},
+ {0x1134B, 0, 2, 4792},
+ {0x1134C, 0, 2, 4794},
+ {0x1134D, 9, 0, 0},
+ {0x11366, 230, 0, 0},
+ {0x11367, 230, 0, 0},
+ {0x11368, 230, 0, 0},
+ {0x11369, 230, 0, 0},
+ {0x1136A, 230, 0, 0},
+ {0x1136B, 230, 0, 0},
+ {0x1136C, 230, 0, 0},
+ {0x11370, 230, 0, 0},
+ {0x11371, 230, 0, 0},
+ {0x11372, 230, 0, 0},
+ {0x11373, 230, 0, 0},
+ {0x11374, 230, 0, 0},
+ {0x11442, 9, 0, 0},
+ {0x11446, 7, 0, 0},
+ {0x1145E, 230, 0, 0},
+ {0x114BB, 0, 2, 4796},
+ {0x114BC, 0, 2, 4798},
+ {0x114BE, 0, 2, 4800},
+ {0x114C2, 9, 0, 0},
+ {0x114C3, 7, 0, 0},
+ {0x115BA, 0, 2, 4802},
+ {0x115BB, 0, 2, 4804},
+ {0x115BF, 9, 0, 0},
+ {0x115C0, 7, 0, 0},
+ {0x1163F, 9, 0, 0},
+ {0x116B6, 9, 0, 0},
+ {0x116B7, 7, 0, 0},
+ {0x1172B, 9, 0, 0},
+ {0x11839, 9, 0, 0},
+ {0x1183A, 7, 0, 0},
+ {0x11938, 0, 2, 4806},
+ {0x1193D, 9, 0, 0},
+ {0x1193E, 9, 0, 0},
+ {0x11943, 7, 0, 0},
+ {0x119E0, 9, 0, 0},
+ {0x11A34, 9, 0, 0},
+ {0x11A47, 9, 0, 0},
+ {0x11A99, 9, 0, 0},
+ {0x11C3F, 9, 0, 0},
+ {0x11D42, 7, 0, 0},
+ {0x11D44, 9, 0, 0},
+ {0x11D45, 9, 0, 0},
+ {0x11D97, 9, 0, 0},
+ {0x11F41, 9, 0, 0},
+ {0x11F42, 9, 0, 0},
+ {0x16AF0, 1, 0, 0},
+ {0x16AF1, 1, 0, 0},
+ {0x16AF2, 1, 0, 0},
+ {0x16AF3, 1, 0, 0},
+ {0x16AF4, 1, 0, 0},
+ {0x16B30, 230, 0, 0},
+ {0x16B31, 230, 0, 0},
+ {0x16B32, 230, 0, 0},
+ {0x16B33, 230, 0, 0},
+ {0x16B34, 230, 0, 0},
+ {0x16B35, 230, 0, 0},
+ {0x16B36, 230, 0, 0},
+ {0x16FF0, 6, 0, 0},
+ {0x16FF1, 6, 0, 0},
+ {0x1BC9E, 1, 0, 0},
+ {0x1D15E, 0, 2 | DECOMP_NO_COMPOSE, 4808}, /* in exclusion list */
+ {0x1D15F, 0, 2 | DECOMP_NO_COMPOSE, 4810}, /* in exclusion list */
+ {0x1D160, 0, 2 | DECOMP_NO_COMPOSE, 4812}, /* in exclusion list */
+ {0x1D161, 0, 2 | DECOMP_NO_COMPOSE, 4814}, /* in exclusion list */
+ {0x1D162, 0, 2 | DECOMP_NO_COMPOSE, 4816}, /* in exclusion list */
+ {0x1D163, 0, 2 | DECOMP_NO_COMPOSE, 4818}, /* in exclusion list */
+ {0x1D164, 0, 2 | DECOMP_NO_COMPOSE, 4820}, /* in exclusion list */
+ {0x1D165, 216, 0, 0},
+ {0x1D166, 216, 0, 0},
+ {0x1D167, 1, 0, 0},
+ {0x1D168, 1, 0, 0},
+ {0x1D169, 1, 0, 0},
+ {0x1D16D, 226, 0, 0},
+ {0x1D16E, 216, 0, 0},
+ {0x1D16F, 216, 0, 0},
+ {0x1D170, 216, 0, 0},
+ {0x1D171, 216, 0, 0},
+ {0x1D172, 216, 0, 0},
+ {0x1D17B, 220, 0, 0},
+ {0x1D17C, 220, 0, 0},
+ {0x1D17D, 220, 0, 0},
+ {0x1D17E, 220, 0, 0},
+ {0x1D17F, 220, 0, 0},
+ {0x1D180, 220, 0, 0},
+ {0x1D181, 220, 0, 0},
+ {0x1D182, 220, 0, 0},
+ {0x1D185, 230, 0, 0},
+ {0x1D186, 230, 0, 0},
+ {0x1D187, 230, 0, 0},
+ {0x1D188, 230, 0, 0},
+ {0x1D189, 230, 0, 0},
+ {0x1D18A, 220, 0, 0},
+ {0x1D18B, 220, 0, 0},
+ {0x1D1AA, 230, 0, 0},
+ {0x1D1AB, 230, 0, 0},
+ {0x1D1AC, 230, 0, 0},
+ {0x1D1AD, 230, 0, 0},
+ {0x1D1BB, 0, 2 | DECOMP_NO_COMPOSE, 4822}, /* in exclusion list */
+ {0x1D1BC, 0, 2 | DECOMP_NO_COMPOSE, 4824}, /* in exclusion list */
+ {0x1D1BD, 0, 2 | DECOMP_NO_COMPOSE, 4826}, /* in exclusion list */
+ {0x1D1BE, 0, 2 | DECOMP_NO_COMPOSE, 4828}, /* in exclusion list */
+ {0x1D1BF, 0, 2 | DECOMP_NO_COMPOSE, 4830}, /* in exclusion list */
+ {0x1D1C0, 0, 2 | DECOMP_NO_COMPOSE, 4832}, /* in exclusion list */
+ {0x1D242, 230, 0, 0},
+ {0x1D243, 230, 0, 0},
+ {0x1D244, 230, 0, 0},
+ {0x1D400, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0041},
+ {0x1D401, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0042},
+ {0x1D402, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0043},
+ {0x1D403, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0044},
+ {0x1D404, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0045},
+ {0x1D405, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0046},
+ {0x1D406, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0047},
+ {0x1D407, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0048},
+ {0x1D408, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0049},
+ {0x1D409, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004A},
+ {0x1D40A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004B},
+ {0x1D40B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004C},
+ {0x1D40C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004D},
+ {0x1D40D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004E},
+ {0x1D40E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004F},
+ {0x1D40F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0050},
+ {0x1D410, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0051},
+ {0x1D411, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0052},
+ {0x1D412, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0053},
+ {0x1D413, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0054},
+ {0x1D414, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0055},
+ {0x1D415, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0056},
+ {0x1D416, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0057},
+ {0x1D417, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0058},
+ {0x1D418, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0059},
+ {0x1D419, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005A},
+ {0x1D41A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0061},
+ {0x1D41B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0062},
+ {0x1D41C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0063},
+ {0x1D41D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0064},
+ {0x1D41E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0065},
+ {0x1D41F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0066},
+ {0x1D420, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0067},
+ {0x1D421, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0068},
+ {0x1D422, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0069},
+ {0x1D423, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006A},
+ {0x1D424, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006B},
+ {0x1D425, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006C},
+ {0x1D426, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006D},
+ {0x1D427, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006E},
+ {0x1D428, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006F},
+ {0x1D429, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0070},
+ {0x1D42A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0071},
+ {0x1D42B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0072},
+ {0x1D42C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0073},
+ {0x1D42D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0074},
+ {0x1D42E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0075},
+ {0x1D42F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0076},
+ {0x1D430, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0077},
+ {0x1D431, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0078},
+ {0x1D432, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0079},
+ {0x1D433, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007A},
+ {0x1D434, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0041},
+ {0x1D435, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0042},
+ {0x1D436, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0043},
+ {0x1D437, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0044},
+ {0x1D438, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0045},
+ {0x1D439, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0046},
+ {0x1D43A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0047},
+ {0x1D43B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0048},
+ {0x1D43C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0049},
+ {0x1D43D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004A},
+ {0x1D43E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004B},
+ {0x1D43F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004C},
+ {0x1D440, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004D},
+ {0x1D441, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004E},
+ {0x1D442, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004F},
+ {0x1D443, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0050},
+ {0x1D444, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0051},
+ {0x1D445, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0052},
+ {0x1D446, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0053},
+ {0x1D447, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0054},
+ {0x1D448, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0055},
+ {0x1D449, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0056},
+ {0x1D44A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0057},
+ {0x1D44B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0058},
+ {0x1D44C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0059},
+ {0x1D44D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005A},
+ {0x1D44E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0061},
+ {0x1D44F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0062},
+ {0x1D450, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0063},
+ {0x1D451, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0064},
+ {0x1D452, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0065},
+ {0x1D453, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0066},
+ {0x1D454, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0067},
+ {0x1D456, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0069},
+ {0x1D457, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006A},
+ {0x1D458, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006B},
+ {0x1D459, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006C},
+ {0x1D45A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006D},
+ {0x1D45B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006E},
+ {0x1D45C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006F},
+ {0x1D45D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0070},
+ {0x1D45E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0071},
+ {0x1D45F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0072},
+ {0x1D460, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0073},
+ {0x1D461, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0074},
+ {0x1D462, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0075},
+ {0x1D463, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0076},
+ {0x1D464, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0077},
+ {0x1D465, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0078},
+ {0x1D466, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0079},
+ {0x1D467, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007A},
+ {0x1D468, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0041},
+ {0x1D469, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0042},
+ {0x1D46A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0043},
+ {0x1D46B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0044},
+ {0x1D46C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0045},
+ {0x1D46D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0046},
+ {0x1D46E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0047},
+ {0x1D46F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0048},
+ {0x1D470, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0049},
+ {0x1D471, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004A},
+ {0x1D472, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004B},
+ {0x1D473, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004C},
+ {0x1D474, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004D},
+ {0x1D475, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004E},
+ {0x1D476, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004F},
+ {0x1D477, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0050},
+ {0x1D478, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0051},
+ {0x1D479, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0052},
+ {0x1D47A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0053},
+ {0x1D47B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0054},
+ {0x1D47C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0055},
+ {0x1D47D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0056},
+ {0x1D47E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0057},
+ {0x1D47F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0058},
+ {0x1D480, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0059},
+ {0x1D481, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005A},
+ {0x1D482, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0061},
+ {0x1D483, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0062},
+ {0x1D484, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0063},
+ {0x1D485, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0064},
+ {0x1D486, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0065},
+ {0x1D487, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0066},
+ {0x1D488, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0067},
+ {0x1D489, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0068},
+ {0x1D48A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0069},
+ {0x1D48B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006A},
+ {0x1D48C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006B},
+ {0x1D48D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006C},
+ {0x1D48E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006D},
+ {0x1D48F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006E},
+ {0x1D490, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006F},
+ {0x1D491, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0070},
+ {0x1D492, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0071},
+ {0x1D493, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0072},
+ {0x1D494, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0073},
+ {0x1D495, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0074},
+ {0x1D496, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0075},
+ {0x1D497, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0076},
+ {0x1D498, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0077},
+ {0x1D499, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0078},
+ {0x1D49A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0079},
+ {0x1D49B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007A},
+ {0x1D49C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0041},
+ {0x1D49E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0043},
+ {0x1D49F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0044},
+ {0x1D4A2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0047},
+ {0x1D4A5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004A},
+ {0x1D4A6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004B},
+ {0x1D4A9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004E},
+ {0x1D4AA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004F},
+ {0x1D4AB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0050},
+ {0x1D4AC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0051},
+ {0x1D4AE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0053},
+ {0x1D4AF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0054},
+ {0x1D4B0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0055},
+ {0x1D4B1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0056},
+ {0x1D4B2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0057},
+ {0x1D4B3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0058},
+ {0x1D4B4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0059},
+ {0x1D4B5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005A},
+ {0x1D4B6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0061},
+ {0x1D4B7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0062},
+ {0x1D4B8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0063},
+ {0x1D4B9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0064},
+ {0x1D4BB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0066},
+ {0x1D4BD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0068},
+ {0x1D4BE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0069},
+ {0x1D4BF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006A},
+ {0x1D4C0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006B},
+ {0x1D4C1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006C},
+ {0x1D4C2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006D},
+ {0x1D4C3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006E},
+ {0x1D4C5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0070},
+ {0x1D4C6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0071},
+ {0x1D4C7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0072},
+ {0x1D4C8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0073},
+ {0x1D4C9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0074},
+ {0x1D4CA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0075},
+ {0x1D4CB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0076},
+ {0x1D4CC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0077},
+ {0x1D4CD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0078},
+ {0x1D4CE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0079},
+ {0x1D4CF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007A},
+ {0x1D4D0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0041},
+ {0x1D4D1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0042},
+ {0x1D4D2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0043},
+ {0x1D4D3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0044},
+ {0x1D4D4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0045},
+ {0x1D4D5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0046},
+ {0x1D4D6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0047},
+ {0x1D4D7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0048},
+ {0x1D4D8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0049},
+ {0x1D4D9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004A},
+ {0x1D4DA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004B},
+ {0x1D4DB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004C},
+ {0x1D4DC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004D},
+ {0x1D4DD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004E},
+ {0x1D4DE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004F},
+ {0x1D4DF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0050},
+ {0x1D4E0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0051},
+ {0x1D4E1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0052},
+ {0x1D4E2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0053},
+ {0x1D4E3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0054},
+ {0x1D4E4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0055},
+ {0x1D4E5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0056},
+ {0x1D4E6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0057},
+ {0x1D4E7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0058},
+ {0x1D4E8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0059},
+ {0x1D4E9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005A},
+ {0x1D4EA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0061},
+ {0x1D4EB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0062},
+ {0x1D4EC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0063},
+ {0x1D4ED, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0064},
+ {0x1D4EE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0065},
+ {0x1D4EF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0066},
+ {0x1D4F0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0067},
+ {0x1D4F1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0068},
+ {0x1D4F2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0069},
+ {0x1D4F3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006A},
+ {0x1D4F4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006B},
+ {0x1D4F5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006C},
+ {0x1D4F6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006D},
+ {0x1D4F7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006E},
+ {0x1D4F8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006F},
+ {0x1D4F9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0070},
+ {0x1D4FA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0071},
+ {0x1D4FB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0072},
+ {0x1D4FC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0073},
+ {0x1D4FD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0074},
+ {0x1D4FE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0075},
+ {0x1D4FF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0076},
+ {0x1D500, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0077},
+ {0x1D501, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0078},
+ {0x1D502, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0079},
+ {0x1D503, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007A},
+ {0x1D504, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0041},
+ {0x1D505, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0042},
+ {0x1D507, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0044},
+ {0x1D508, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0045},
+ {0x1D509, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0046},
+ {0x1D50A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0047},
+ {0x1D50D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004A},
+ {0x1D50E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004B},
+ {0x1D50F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004C},
+ {0x1D510, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004D},
+ {0x1D511, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004E},
+ {0x1D512, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004F},
+ {0x1D513, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0050},
+ {0x1D514, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0051},
+ {0x1D516, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0053},
+ {0x1D517, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0054},
+ {0x1D518, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0055},
+ {0x1D519, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0056},
+ {0x1D51A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0057},
+ {0x1D51B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0058},
+ {0x1D51C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0059},
+ {0x1D51E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0061},
+ {0x1D51F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0062},
+ {0x1D520, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0063},
+ {0x1D521, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0064},
+ {0x1D522, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0065},
+ {0x1D523, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0066},
+ {0x1D524, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0067},
+ {0x1D525, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0068},
+ {0x1D526, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0069},
+ {0x1D527, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006A},
+ {0x1D528, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006B},
+ {0x1D529, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006C},
+ {0x1D52A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006D},
+ {0x1D52B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006E},
+ {0x1D52C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006F},
+ {0x1D52D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0070},
+ {0x1D52E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0071},
+ {0x1D52F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0072},
+ {0x1D530, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0073},
+ {0x1D531, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0074},
+ {0x1D532, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0075},
+ {0x1D533, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0076},
+ {0x1D534, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0077},
+ {0x1D535, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0078},
+ {0x1D536, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0079},
+ {0x1D537, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007A},
+ {0x1D538, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0041},
+ {0x1D539, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0042},
+ {0x1D53B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0044},
+ {0x1D53C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0045},
+ {0x1D53D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0046},
+ {0x1D53E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0047},
+ {0x1D540, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0049},
+ {0x1D541, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004A},
+ {0x1D542, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004B},
+ {0x1D543, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004C},
+ {0x1D544, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004D},
+ {0x1D546, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004F},
+ {0x1D54A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0053},
+ {0x1D54B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0054},
+ {0x1D54C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0055},
+ {0x1D54D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0056},
+ {0x1D54E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0057},
+ {0x1D54F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0058},
+ {0x1D550, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0059},
+ {0x1D552, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0061},
+ {0x1D553, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0062},
+ {0x1D554, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0063},
+ {0x1D555, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0064},
+ {0x1D556, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0065},
+ {0x1D557, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0066},
+ {0x1D558, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0067},
+ {0x1D559, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0068},
+ {0x1D55A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0069},
+ {0x1D55B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006A},
+ {0x1D55C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006B},
+ {0x1D55D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006C},
+ {0x1D55E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006D},
+ {0x1D55F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006E},
+ {0x1D560, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006F},
+ {0x1D561, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0070},
+ {0x1D562, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0071},
+ {0x1D563, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0072},
+ {0x1D564, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0073},
+ {0x1D565, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0074},
+ {0x1D566, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0075},
+ {0x1D567, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0076},
+ {0x1D568, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0077},
+ {0x1D569, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0078},
+ {0x1D56A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0079},
+ {0x1D56B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007A},
+ {0x1D56C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0041},
+ {0x1D56D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0042},
+ {0x1D56E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0043},
+ {0x1D56F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0044},
+ {0x1D570, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0045},
+ {0x1D571, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0046},
+ {0x1D572, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0047},
+ {0x1D573, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0048},
+ {0x1D574, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0049},
+ {0x1D575, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004A},
+ {0x1D576, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004B},
+ {0x1D577, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004C},
+ {0x1D578, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004D},
+ {0x1D579, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004E},
+ {0x1D57A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004F},
+ {0x1D57B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0050},
+ {0x1D57C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0051},
+ {0x1D57D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0052},
+ {0x1D57E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0053},
+ {0x1D57F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0054},
+ {0x1D580, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0055},
+ {0x1D581, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0056},
+ {0x1D582, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0057},
+ {0x1D583, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0058},
+ {0x1D584, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0059},
+ {0x1D585, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005A},
+ {0x1D586, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0061},
+ {0x1D587, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0062},
+ {0x1D588, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0063},
+ {0x1D589, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0064},
+ {0x1D58A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0065},
+ {0x1D58B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0066},
+ {0x1D58C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0067},
+ {0x1D58D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0068},
+ {0x1D58E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0069},
+ {0x1D58F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006A},
+ {0x1D590, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006B},
+ {0x1D591, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006C},
+ {0x1D592, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006D},
+ {0x1D593, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006E},
+ {0x1D594, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006F},
+ {0x1D595, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0070},
+ {0x1D596, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0071},
+ {0x1D597, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0072},
+ {0x1D598, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0073},
+ {0x1D599, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0074},
+ {0x1D59A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0075},
+ {0x1D59B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0076},
+ {0x1D59C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0077},
+ {0x1D59D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0078},
+ {0x1D59E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0079},
+ {0x1D59F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007A},
+ {0x1D5A0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0041},
+ {0x1D5A1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0042},
+ {0x1D5A2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0043},
+ {0x1D5A3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0044},
+ {0x1D5A4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0045},
+ {0x1D5A5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0046},
+ {0x1D5A6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0047},
+ {0x1D5A7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0048},
+ {0x1D5A8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0049},
+ {0x1D5A9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004A},
+ {0x1D5AA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004B},
+ {0x1D5AB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004C},
+ {0x1D5AC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004D},
+ {0x1D5AD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004E},
+ {0x1D5AE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004F},
+ {0x1D5AF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0050},
+ {0x1D5B0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0051},
+ {0x1D5B1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0052},
+ {0x1D5B2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0053},
+ {0x1D5B3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0054},
+ {0x1D5B4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0055},
+ {0x1D5B5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0056},
+ {0x1D5B6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0057},
+ {0x1D5B7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0058},
+ {0x1D5B8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0059},
+ {0x1D5B9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005A},
+ {0x1D5BA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0061},
+ {0x1D5BB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0062},
+ {0x1D5BC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0063},
+ {0x1D5BD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0064},
+ {0x1D5BE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0065},
+ {0x1D5BF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0066},
+ {0x1D5C0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0067},
+ {0x1D5C1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0068},
+ {0x1D5C2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0069},
+ {0x1D5C3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006A},
+ {0x1D5C4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006B},
+ {0x1D5C5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006C},
+ {0x1D5C6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006D},
+ {0x1D5C7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006E},
+ {0x1D5C8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006F},
+ {0x1D5C9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0070},
+ {0x1D5CA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0071},
+ {0x1D5CB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0072},
+ {0x1D5CC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0073},
+ {0x1D5CD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0074},
+ {0x1D5CE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0075},
+ {0x1D5CF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0076},
+ {0x1D5D0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0077},
+ {0x1D5D1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0078},
+ {0x1D5D2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0079},
+ {0x1D5D3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007A},
+ {0x1D5D4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0041},
+ {0x1D5D5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0042},
+ {0x1D5D6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0043},
+ {0x1D5D7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0044},
+ {0x1D5D8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0045},
+ {0x1D5D9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0046},
+ {0x1D5DA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0047},
+ {0x1D5DB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0048},
+ {0x1D5DC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0049},
+ {0x1D5DD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004A},
+ {0x1D5DE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004B},
+ {0x1D5DF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004C},
+ {0x1D5E0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004D},
+ {0x1D5E1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004E},
+ {0x1D5E2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004F},
+ {0x1D5E3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0050},
+ {0x1D5E4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0051},
+ {0x1D5E5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0052},
+ {0x1D5E6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0053},
+ {0x1D5E7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0054},
+ {0x1D5E8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0055},
+ {0x1D5E9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0056},
+ {0x1D5EA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0057},
+ {0x1D5EB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0058},
+ {0x1D5EC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0059},
+ {0x1D5ED, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005A},
+ {0x1D5EE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0061},
+ {0x1D5EF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0062},
+ {0x1D5F0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0063},
+ {0x1D5F1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0064},
+ {0x1D5F2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0065},
+ {0x1D5F3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0066},
+ {0x1D5F4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0067},
+ {0x1D5F5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0068},
+ {0x1D5F6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0069},
+ {0x1D5F7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006A},
+ {0x1D5F8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006B},
+ {0x1D5F9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006C},
+ {0x1D5FA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006D},
+ {0x1D5FB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006E},
+ {0x1D5FC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006F},
+ {0x1D5FD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0070},
+ {0x1D5FE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0071},
+ {0x1D5FF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0072},
+ {0x1D600, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0073},
+ {0x1D601, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0074},
+ {0x1D602, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0075},
+ {0x1D603, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0076},
+ {0x1D604, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0077},
+ {0x1D605, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0078},
+ {0x1D606, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0079},
+ {0x1D607, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007A},
+ {0x1D608, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0041},
+ {0x1D609, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0042},
+ {0x1D60A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0043},
+ {0x1D60B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0044},
+ {0x1D60C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0045},
+ {0x1D60D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0046},
+ {0x1D60E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0047},
+ {0x1D60F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0048},
+ {0x1D610, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0049},
+ {0x1D611, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004A},
+ {0x1D612, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004B},
+ {0x1D613, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004C},
+ {0x1D614, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004D},
+ {0x1D615, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004E},
+ {0x1D616, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004F},
+ {0x1D617, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0050},
+ {0x1D618, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0051},
+ {0x1D619, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0052},
+ {0x1D61A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0053},
+ {0x1D61B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0054},
+ {0x1D61C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0055},
+ {0x1D61D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0056},
+ {0x1D61E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0057},
+ {0x1D61F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0058},
+ {0x1D620, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0059},
+ {0x1D621, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005A},
+ {0x1D622, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0061},
+ {0x1D623, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0062},
+ {0x1D624, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0063},
+ {0x1D625, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0064},
+ {0x1D626, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0065},
+ {0x1D627, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0066},
+ {0x1D628, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0067},
+ {0x1D629, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0068},
+ {0x1D62A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0069},
+ {0x1D62B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006A},
+ {0x1D62C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006B},
+ {0x1D62D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006C},
+ {0x1D62E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006D},
+ {0x1D62F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006E},
+ {0x1D630, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006F},
+ {0x1D631, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0070},
+ {0x1D632, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0071},
+ {0x1D633, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0072},
+ {0x1D634, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0073},
+ {0x1D635, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0074},
+ {0x1D636, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0075},
+ {0x1D637, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0076},
+ {0x1D638, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0077},
+ {0x1D639, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0078},
+ {0x1D63A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0079},
+ {0x1D63B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007A},
+ {0x1D63C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0041},
+ {0x1D63D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0042},
+ {0x1D63E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0043},
+ {0x1D63F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0044},
+ {0x1D640, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0045},
+ {0x1D641, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0046},
+ {0x1D642, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0047},
+ {0x1D643, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0048},
+ {0x1D644, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0049},
+ {0x1D645, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004A},
+ {0x1D646, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004B},
+ {0x1D647, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004C},
+ {0x1D648, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004D},
+ {0x1D649, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004E},
+ {0x1D64A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004F},
+ {0x1D64B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0050},
+ {0x1D64C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0051},
+ {0x1D64D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0052},
+ {0x1D64E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0053},
+ {0x1D64F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0054},
+ {0x1D650, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0055},
+ {0x1D651, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0056},
+ {0x1D652, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0057},
+ {0x1D653, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0058},
+ {0x1D654, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0059},
+ {0x1D655, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005A},
+ {0x1D656, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0061},
+ {0x1D657, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0062},
+ {0x1D658, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0063},
+ {0x1D659, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0064},
+ {0x1D65A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0065},
+ {0x1D65B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0066},
+ {0x1D65C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0067},
+ {0x1D65D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0068},
+ {0x1D65E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0069},
+ {0x1D65F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006A},
+ {0x1D660, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006B},
+ {0x1D661, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006C},
+ {0x1D662, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006D},
+ {0x1D663, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006E},
+ {0x1D664, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006F},
+ {0x1D665, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0070},
+ {0x1D666, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0071},
+ {0x1D667, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0072},
+ {0x1D668, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0073},
+ {0x1D669, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0074},
+ {0x1D66A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0075},
+ {0x1D66B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0076},
+ {0x1D66C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0077},
+ {0x1D66D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0078},
+ {0x1D66E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0079},
+ {0x1D66F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007A},
+ {0x1D670, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0041},
+ {0x1D671, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0042},
+ {0x1D672, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0043},
+ {0x1D673, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0044},
+ {0x1D674, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0045},
+ {0x1D675, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0046},
+ {0x1D676, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0047},
+ {0x1D677, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0048},
+ {0x1D678, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0049},
+ {0x1D679, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004A},
+ {0x1D67A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004B},
+ {0x1D67B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004C},
+ {0x1D67C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004D},
+ {0x1D67D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004E},
+ {0x1D67E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004F},
+ {0x1D67F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0050},
+ {0x1D680, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0051},
+ {0x1D681, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0052},
+ {0x1D682, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0053},
+ {0x1D683, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0054},
+ {0x1D684, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0055},
+ {0x1D685, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0056},
+ {0x1D686, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0057},
+ {0x1D687, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0058},
+ {0x1D688, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0059},
+ {0x1D689, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005A},
+ {0x1D68A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0061},
+ {0x1D68B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0062},
+ {0x1D68C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0063},
+ {0x1D68D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0064},
+ {0x1D68E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0065},
+ {0x1D68F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0066},
+ {0x1D690, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0067},
+ {0x1D691, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0068},
+ {0x1D692, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0069},
+ {0x1D693, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006A},
+ {0x1D694, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006B},
+ {0x1D695, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006C},
+ {0x1D696, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006D},
+ {0x1D697, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006E},
+ {0x1D698, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006F},
+ {0x1D699, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0070},
+ {0x1D69A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0071},
+ {0x1D69B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0072},
+ {0x1D69C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0073},
+ {0x1D69D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0074},
+ {0x1D69E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0075},
+ {0x1D69F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0076},
+ {0x1D6A0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0077},
+ {0x1D6A1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0078},
+ {0x1D6A2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0079},
+ {0x1D6A3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007A},
+ {0x1D6A4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0131},
+ {0x1D6A5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0237},
+ {0x1D6A8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0391},
+ {0x1D6A9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0392},
+ {0x1D6AA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0393},
+ {0x1D6AB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0394},
+ {0x1D6AC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0395},
+ {0x1D6AD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0396},
+ {0x1D6AE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0397},
+ {0x1D6AF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0398},
+ {0x1D6B0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0399},
+ {0x1D6B1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039A},
+ {0x1D6B2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039B},
+ {0x1D6B3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039C},
+ {0x1D6B4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039D},
+ {0x1D6B5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039E},
+ {0x1D6B6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039F},
+ {0x1D6B7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A0},
+ {0x1D6B8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A1},
+ {0x1D6B9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03F4},
+ {0x1D6BA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A3},
+ {0x1D6BB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A4},
+ {0x1D6BC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A5},
+ {0x1D6BD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A6},
+ {0x1D6BE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A7},
+ {0x1D6BF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A8},
+ {0x1D6C0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A9},
+ {0x1D6C1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2207},
+ {0x1D6C2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B1},
+ {0x1D6C3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B2},
+ {0x1D6C4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B3},
+ {0x1D6C5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B4},
+ {0x1D6C6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B5},
+ {0x1D6C7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B6},
+ {0x1D6C8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B7},
+ {0x1D6C9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B8},
+ {0x1D6CA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B9},
+ {0x1D6CB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BA},
+ {0x1D6CC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BB},
+ {0x1D6CD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BC},
+ {0x1D6CE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BD},
+ {0x1D6CF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BE},
+ {0x1D6D0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BF},
+ {0x1D6D1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C0},
+ {0x1D6D2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C1},
+ {0x1D6D3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C2},
+ {0x1D6D4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C3},
+ {0x1D6D5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C4},
+ {0x1D6D6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C5},
+ {0x1D6D7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C6},
+ {0x1D6D8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C7},
+ {0x1D6D9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C8},
+ {0x1D6DA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C9},
+ {0x1D6DB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2202},
+ {0x1D6DC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03F5},
+ {0x1D6DD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03D1},
+ {0x1D6DE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03F0},
+ {0x1D6DF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03D5},
+ {0x1D6E0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03F1},
+ {0x1D6E1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03D6},
+ {0x1D6E2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0391},
+ {0x1D6E3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0392},
+ {0x1D6E4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0393},
+ {0x1D6E5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0394},
+ {0x1D6E6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0395},
+ {0x1D6E7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0396},
+ {0x1D6E8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0397},
+ {0x1D6E9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0398},
+ {0x1D6EA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0399},
+ {0x1D6EB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039A},
+ {0x1D6EC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039B},
+ {0x1D6ED, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039C},
+ {0x1D6EE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039D},
+ {0x1D6EF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039E},
+ {0x1D6F0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039F},
+ {0x1D6F1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A0},
+ {0x1D6F2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A1},
+ {0x1D6F3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03F4},
+ {0x1D6F4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A3},
+ {0x1D6F5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A4},
+ {0x1D6F6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A5},
+ {0x1D6F7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A6},
+ {0x1D6F8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A7},
+ {0x1D6F9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A8},
+ {0x1D6FA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A9},
+ {0x1D6FB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2207},
+ {0x1D6FC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B1},
+ {0x1D6FD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B2},
+ {0x1D6FE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B3},
+ {0x1D6FF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B4},
+ {0x1D700, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B5},
+ {0x1D701, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B6},
+ {0x1D702, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B7},
+ {0x1D703, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B8},
+ {0x1D704, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B9},
+ {0x1D705, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BA},
+ {0x1D706, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BB},
+ {0x1D707, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BC},
+ {0x1D708, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BD},
+ {0x1D709, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BE},
+ {0x1D70A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BF},
+ {0x1D70B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C0},
+ {0x1D70C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C1},
+ {0x1D70D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C2},
+ {0x1D70E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C3},
+ {0x1D70F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C4},
+ {0x1D710, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C5},
+ {0x1D711, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C6},
+ {0x1D712, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C7},
+ {0x1D713, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C8},
+ {0x1D714, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C9},
+ {0x1D715, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2202},
+ {0x1D716, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03F5},
+ {0x1D717, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03D1},
+ {0x1D718, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03F0},
+ {0x1D719, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03D5},
+ {0x1D71A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03F1},
+ {0x1D71B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03D6},
+ {0x1D71C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0391},
+ {0x1D71D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0392},
+ {0x1D71E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0393},
+ {0x1D71F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0394},
+ {0x1D720, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0395},
+ {0x1D721, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0396},
+ {0x1D722, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0397},
+ {0x1D723, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0398},
+ {0x1D724, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0399},
+ {0x1D725, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039A},
+ {0x1D726, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039B},
+ {0x1D727, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039C},
+ {0x1D728, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039D},
+ {0x1D729, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039E},
+ {0x1D72A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039F},
+ {0x1D72B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A0},
+ {0x1D72C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A1},
+ {0x1D72D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03F4},
+ {0x1D72E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A3},
+ {0x1D72F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A4},
+ {0x1D730, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A5},
+ {0x1D731, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A6},
+ {0x1D732, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A7},
+ {0x1D733, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A8},
+ {0x1D734, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A9},
+ {0x1D735, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2207},
+ {0x1D736, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B1},
+ {0x1D737, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B2},
+ {0x1D738, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B3},
+ {0x1D739, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B4},
+ {0x1D73A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B5},
+ {0x1D73B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B6},
+ {0x1D73C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B7},
+ {0x1D73D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B8},
+ {0x1D73E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B9},
+ {0x1D73F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BA},
+ {0x1D740, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BB},
+ {0x1D741, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BC},
+ {0x1D742, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BD},
+ {0x1D743, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BE},
+ {0x1D744, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BF},
+ {0x1D745, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C0},
+ {0x1D746, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C1},
+ {0x1D747, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C2},
+ {0x1D748, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C3},
+ {0x1D749, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C4},
+ {0x1D74A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C5},
+ {0x1D74B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C6},
+ {0x1D74C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C7},
+ {0x1D74D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C8},
+ {0x1D74E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C9},
+ {0x1D74F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2202},
+ {0x1D750, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03F5},
+ {0x1D751, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03D1},
+ {0x1D752, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03F0},
+ {0x1D753, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03D5},
+ {0x1D754, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03F1},
+ {0x1D755, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03D6},
+ {0x1D756, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0391},
+ {0x1D757, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0392},
+ {0x1D758, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0393},
+ {0x1D759, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0394},
+ {0x1D75A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0395},
+ {0x1D75B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0396},
+ {0x1D75C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0397},
+ {0x1D75D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0398},
+ {0x1D75E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0399},
+ {0x1D75F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039A},
+ {0x1D760, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039B},
+ {0x1D761, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039C},
+ {0x1D762, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039D},
+ {0x1D763, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039E},
+ {0x1D764, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039F},
+ {0x1D765, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A0},
+ {0x1D766, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A1},
+ {0x1D767, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03F4},
+ {0x1D768, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A3},
+ {0x1D769, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A4},
+ {0x1D76A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A5},
+ {0x1D76B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A6},
+ {0x1D76C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A7},
+ {0x1D76D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A8},
+ {0x1D76E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A9},
+ {0x1D76F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2207},
+ {0x1D770, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B1},
+ {0x1D771, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B2},
+ {0x1D772, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B3},
+ {0x1D773, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B4},
+ {0x1D774, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B5},
+ {0x1D775, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B6},
+ {0x1D776, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B7},
+ {0x1D777, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B8},
+ {0x1D778, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B9},
+ {0x1D779, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BA},
+ {0x1D77A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BB},
+ {0x1D77B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BC},
+ {0x1D77C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BD},
+ {0x1D77D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BE},
+ {0x1D77E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BF},
+ {0x1D77F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C0},
+ {0x1D780, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C1},
+ {0x1D781, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C2},
+ {0x1D782, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C3},
+ {0x1D783, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C4},
+ {0x1D784, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C5},
+ {0x1D785, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C6},
+ {0x1D786, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C7},
+ {0x1D787, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C8},
+ {0x1D788, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C9},
+ {0x1D789, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2202},
+ {0x1D78A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03F5},
+ {0x1D78B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03D1},
+ {0x1D78C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03F0},
+ {0x1D78D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03D5},
+ {0x1D78E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03F1},
+ {0x1D78F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03D6},
+ {0x1D790, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0391},
+ {0x1D791, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0392},
+ {0x1D792, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0393},
+ {0x1D793, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0394},
+ {0x1D794, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0395},
+ {0x1D795, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0396},
+ {0x1D796, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0397},
+ {0x1D797, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0398},
+ {0x1D798, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0399},
+ {0x1D799, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039A},
+ {0x1D79A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039B},
+ {0x1D79B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039C},
+ {0x1D79C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039D},
+ {0x1D79D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039E},
+ {0x1D79E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039F},
+ {0x1D79F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A0},
+ {0x1D7A0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A1},
+ {0x1D7A1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03F4},
+ {0x1D7A2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A3},
+ {0x1D7A3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A4},
+ {0x1D7A4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A5},
+ {0x1D7A5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A6},
+ {0x1D7A6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A7},
+ {0x1D7A7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A8},
+ {0x1D7A8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A9},
+ {0x1D7A9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2207},
+ {0x1D7AA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B1},
+ {0x1D7AB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B2},
+ {0x1D7AC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B3},
+ {0x1D7AD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B4},
+ {0x1D7AE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B5},
+ {0x1D7AF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B6},
+ {0x1D7B0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B7},
+ {0x1D7B1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B8},
+ {0x1D7B2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B9},
+ {0x1D7B3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BA},
+ {0x1D7B4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BB},
+ {0x1D7B5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BC},
+ {0x1D7B6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BD},
+ {0x1D7B7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BE},
+ {0x1D7B8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BF},
+ {0x1D7B9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C0},
+ {0x1D7BA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C1},
+ {0x1D7BB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C2},
+ {0x1D7BC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C3},
+ {0x1D7BD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C4},
+ {0x1D7BE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C5},
+ {0x1D7BF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C6},
+ {0x1D7C0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C7},
+ {0x1D7C1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C8},
+ {0x1D7C2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C9},
+ {0x1D7C3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2202},
+ {0x1D7C4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03F5},
+ {0x1D7C5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03D1},
+ {0x1D7C6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03F0},
+ {0x1D7C7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03D5},
+ {0x1D7C8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03F1},
+ {0x1D7C9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03D6},
+ {0x1D7CA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03DC},
+ {0x1D7CB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03DD},
+ {0x1D7CE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0030},
+ {0x1D7CF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0031},
+ {0x1D7D0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0032},
+ {0x1D7D1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0033},
+ {0x1D7D2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0034},
+ {0x1D7D3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0035},
+ {0x1D7D4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0036},
+ {0x1D7D5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0037},
+ {0x1D7D6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0038},
+ {0x1D7D7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0039},
+ {0x1D7D8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0030},
+ {0x1D7D9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0031},
+ {0x1D7DA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0032},
+ {0x1D7DB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0033},
+ {0x1D7DC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0034},
+ {0x1D7DD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0035},
+ {0x1D7DE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0036},
+ {0x1D7DF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0037},
+ {0x1D7E0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0038},
+ {0x1D7E1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0039},
+ {0x1D7E2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0030},
+ {0x1D7E3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0031},
+ {0x1D7E4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0032},
+ {0x1D7E5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0033},
+ {0x1D7E6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0034},
+ {0x1D7E7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0035},
+ {0x1D7E8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0036},
+ {0x1D7E9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0037},
+ {0x1D7EA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0038},
+ {0x1D7EB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0039},
+ {0x1D7EC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0030},
+ {0x1D7ED, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0031},
+ {0x1D7EE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0032},
+ {0x1D7EF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0033},
+ {0x1D7F0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0034},
+ {0x1D7F1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0035},
+ {0x1D7F2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0036},
+ {0x1D7F3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0037},
+ {0x1D7F4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0038},
+ {0x1D7F5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0039},
+ {0x1D7F6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0030},
+ {0x1D7F7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0031},
+ {0x1D7F8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0032},
+ {0x1D7F9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0033},
+ {0x1D7FA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0034},
+ {0x1D7FB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0035},
+ {0x1D7FC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0036},
+ {0x1D7FD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0037},
+ {0x1D7FE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0038},
+ {0x1D7FF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0039},
+ {0x1E000, 230, 0, 0},
+ {0x1E001, 230, 0, 0},
+ {0x1E002, 230, 0, 0},
+ {0x1E003, 230, 0, 0},
+ {0x1E004, 230, 0, 0},
+ {0x1E005, 230, 0, 0},
+ {0x1E006, 230, 0, 0},
+ {0x1E008, 230, 0, 0},
+ {0x1E009, 230, 0, 0},
+ {0x1E00A, 230, 0, 0},
+ {0x1E00B, 230, 0, 0},
+ {0x1E00C, 230, 0, 0},
+ {0x1E00D, 230, 0, 0},
+ {0x1E00E, 230, 0, 0},
+ {0x1E00F, 230, 0, 0},
+ {0x1E010, 230, 0, 0},
+ {0x1E011, 230, 0, 0},
+ {0x1E012, 230, 0, 0},
+ {0x1E013, 230, 0, 0},
+ {0x1E014, 230, 0, 0},
+ {0x1E015, 230, 0, 0},
+ {0x1E016, 230, 0, 0},
+ {0x1E017, 230, 0, 0},
+ {0x1E018, 230, 0, 0},
+ {0x1E01B, 230, 0, 0},
+ {0x1E01C, 230, 0, 0},
+ {0x1E01D, 230, 0, 0},
+ {0x1E01E, 230, 0, 0},
+ {0x1E01F, 230, 0, 0},
+ {0x1E020, 230, 0, 0},
+ {0x1E021, 230, 0, 0},
+ {0x1E023, 230, 0, 0},
+ {0x1E024, 230, 0, 0},
+ {0x1E026, 230, 0, 0},
+ {0x1E027, 230, 0, 0},
+ {0x1E028, 230, 0, 0},
+ {0x1E029, 230, 0, 0},
+ {0x1E02A, 230, 0, 0},
+ {0x1E030, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0430},
+ {0x1E031, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0431},
+ {0x1E032, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0432},
+ {0x1E033, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0433},
+ {0x1E034, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0434},
+ {0x1E035, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0435},
+ {0x1E036, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0436},
+ {0x1E037, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0437},
+ {0x1E038, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0438},
+ {0x1E039, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x043A},
+ {0x1E03A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x043B},
+ {0x1E03B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x043C},
+ {0x1E03C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x043E},
+ {0x1E03D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x043F},
+ {0x1E03E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0440},
+ {0x1E03F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0441},
+ {0x1E040, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0442},
+ {0x1E041, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0443},
+ {0x1E042, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0444},
+ {0x1E043, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0445},
+ {0x1E044, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0446},
+ {0x1E045, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0447},
+ {0x1E046, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0448},
+ {0x1E047, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x044B},
+ {0x1E048, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x044D},
+ {0x1E049, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x044E},
+ {0x1E04A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0xA689},
+ {0x1E04B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x04D9},
+ {0x1E04C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0456},
+ {0x1E04D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0458},
+ {0x1E04E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x04E9},
+ {0x1E04F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x04AF},
+ {0x1E050, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x04CF},
+ {0x1E051, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0430},
+ {0x1E052, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0431},
+ {0x1E053, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0432},
+ {0x1E054, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0433},
+ {0x1E055, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0434},
+ {0x1E056, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0435},
+ {0x1E057, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0436},
+ {0x1E058, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0437},
+ {0x1E059, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0438},
+ {0x1E05A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x043A},
+ {0x1E05B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x043B},
+ {0x1E05C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x043E},
+ {0x1E05D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x043F},
+ {0x1E05E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0441},
+ {0x1E05F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0443},
+ {0x1E060, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0444},
+ {0x1E061, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0445},
+ {0x1E062, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0446},
+ {0x1E063, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0447},
+ {0x1E064, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0448},
+ {0x1E065, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x044A},
+ {0x1E066, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x044B},
+ {0x1E067, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0491},
+ {0x1E068, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0456},
+ {0x1E069, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0455},
+ {0x1E06A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x045F},
+ {0x1E06B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x04AB},
+ {0x1E06C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0xA651},
+ {0x1E06D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x04B1},
+ {0x1E08F, 230, 0, 0},
+ {0x1E130, 230, 0, 0},
+ {0x1E131, 230, 0, 0},
+ {0x1E132, 230, 0, 0},
+ {0x1E133, 230, 0, 0},
+ {0x1E134, 230, 0, 0},
+ {0x1E135, 230, 0, 0},
+ {0x1E136, 230, 0, 0},
+ {0x1E2AE, 230, 0, 0},
+ {0x1E2EC, 230, 0, 0},
+ {0x1E2ED, 230, 0, 0},
+ {0x1E2EE, 230, 0, 0},
+ {0x1E2EF, 230, 0, 0},
+ {0x1E4EC, 232, 0, 0},
+ {0x1E4ED, 232, 0, 0},
+ {0x1E4EE, 220, 0, 0},
+ {0x1E4EF, 230, 0, 0},
+ {0x1E8D0, 220, 0, 0},
+ {0x1E8D1, 220, 0, 0},
+ {0x1E8D2, 220, 0, 0},
+ {0x1E8D3, 220, 0, 0},
+ {0x1E8D4, 220, 0, 0},
+ {0x1E8D5, 220, 0, 0},
+ {0x1E8D6, 220, 0, 0},
+ {0x1E944, 230, 0, 0},
+ {0x1E945, 230, 0, 0},
+ {0x1E946, 230, 0, 0},
+ {0x1E947, 230, 0, 0},
+ {0x1E948, 230, 0, 0},
+ {0x1E949, 230, 0, 0},
+ {0x1E94A, 7, 0, 0},
+ {0x1EE00, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0627},
+ {0x1EE01, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0628},
+ {0x1EE02, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062C},
+ {0x1EE03, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062F},
+ {0x1EE05, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0648},
+ {0x1EE06, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0632},
+ {0x1EE07, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062D},
+ {0x1EE08, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0637},
+ {0x1EE09, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x064A},
+ {0x1EE0A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0643},
+ {0x1EE0B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0644},
+ {0x1EE0C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0645},
+ {0x1EE0D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0646},
+ {0x1EE0E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0633},
+ {0x1EE0F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0639},
+ {0x1EE10, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0641},
+ {0x1EE11, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0635},
+ {0x1EE12, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0642},
+ {0x1EE13, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0631},
+ {0x1EE14, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0634},
+ {0x1EE15, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062A},
+ {0x1EE16, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062B},
+ {0x1EE17, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062E},
+ {0x1EE18, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0630},
+ {0x1EE19, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0636},
+ {0x1EE1A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0638},
+ {0x1EE1B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x063A},
+ {0x1EE1C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x066E},
+ {0x1EE1D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06BA},
+ {0x1EE1E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06A1},
+ {0x1EE1F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x066F},
+ {0x1EE21, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0628},
+ {0x1EE22, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062C},
+ {0x1EE24, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0647},
+ {0x1EE27, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062D},
+ {0x1EE29, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x064A},
+ {0x1EE2A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0643},
+ {0x1EE2B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0644},
+ {0x1EE2C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0645},
+ {0x1EE2D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0646},
+ {0x1EE2E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0633},
+ {0x1EE2F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0639},
+ {0x1EE30, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0641},
+ {0x1EE31, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0635},
+ {0x1EE32, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0642},
+ {0x1EE34, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0634},
+ {0x1EE35, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062A},
+ {0x1EE36, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062B},
+ {0x1EE37, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062E},
+ {0x1EE39, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0636},
+ {0x1EE3B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x063A},
+ {0x1EE42, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062C},
+ {0x1EE47, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062D},
+ {0x1EE49, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x064A},
+ {0x1EE4B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0644},
+ {0x1EE4D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0646},
+ {0x1EE4E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0633},
+ {0x1EE4F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0639},
+ {0x1EE51, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0635},
+ {0x1EE52, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0642},
+ {0x1EE54, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0634},
+ {0x1EE57, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062E},
+ {0x1EE59, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0636},
+ {0x1EE5B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x063A},
+ {0x1EE5D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06BA},
+ {0x1EE5F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x066F},
+ {0x1EE61, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0628},
+ {0x1EE62, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062C},
+ {0x1EE64, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0647},
+ {0x1EE67, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062D},
+ {0x1EE68, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0637},
+ {0x1EE69, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x064A},
+ {0x1EE6A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0643},
+ {0x1EE6C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0645},
+ {0x1EE6D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0646},
+ {0x1EE6E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0633},
+ {0x1EE6F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0639},
+ {0x1EE70, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0641},
+ {0x1EE71, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0635},
+ {0x1EE72, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0642},
+ {0x1EE74, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0634},
+ {0x1EE75, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062A},
+ {0x1EE76, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062B},
+ {0x1EE77, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062E},
+ {0x1EE79, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0636},
+ {0x1EE7A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0638},
+ {0x1EE7B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x063A},
+ {0x1EE7C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x066E},
+ {0x1EE7E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06A1},
+ {0x1EE80, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0627},
+ {0x1EE81, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0628},
+ {0x1EE82, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062C},
+ {0x1EE83, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062F},
+ {0x1EE84, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0647},
+ {0x1EE85, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0648},
+ {0x1EE86, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0632},
+ {0x1EE87, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062D},
+ {0x1EE88, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0637},
+ {0x1EE89, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x064A},
+ {0x1EE8B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0644},
+ {0x1EE8C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0645},
+ {0x1EE8D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0646},
+ {0x1EE8E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0633},
+ {0x1EE8F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0639},
+ {0x1EE90, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0641},
+ {0x1EE91, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0635},
+ {0x1EE92, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0642},
+ {0x1EE93, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0631},
+ {0x1EE94, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0634},
+ {0x1EE95, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062A},
+ {0x1EE96, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062B},
+ {0x1EE97, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062E},
+ {0x1EE98, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0630},
+ {0x1EE99, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0636},
+ {0x1EE9A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0638},
+ {0x1EE9B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x063A},
+ {0x1EEA1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0628},
+ {0x1EEA2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062C},
+ {0x1EEA3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062F},
+ {0x1EEA5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0648},
+ {0x1EEA6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0632},
+ {0x1EEA7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062D},
+ {0x1EEA8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0637},
+ {0x1EEA9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x064A},
+ {0x1EEAB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0644},
+ {0x1EEAC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0645},
+ {0x1EEAD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0646},
+ {0x1EEAE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0633},
+ {0x1EEAF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0639},
+ {0x1EEB0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0641},
+ {0x1EEB1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0635},
+ {0x1EEB2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0642},
+ {0x1EEB3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0631},
+ {0x1EEB4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0634},
+ {0x1EEB5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062A},
+ {0x1EEB6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062B},
+ {0x1EEB7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062E},
+ {0x1EEB8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0630},
+ {0x1EEB9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0636},
+ {0x1EEBA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0638},
+ {0x1EEBB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x063A},
+ {0x1F100, 0, 2 | DECOMP_COMPAT, 4834},
+ {0x1F101, 0, 2 | DECOMP_COMPAT, 4836},
+ {0x1F102, 0, 2 | DECOMP_COMPAT, 4838},
+ {0x1F103, 0, 2 | DECOMP_COMPAT, 4840},
+ {0x1F104, 0, 2 | DECOMP_COMPAT, 4842},
+ {0x1F105, 0, 2 | DECOMP_COMPAT, 4844},
+ {0x1F106, 0, 2 | DECOMP_COMPAT, 4846},
+ {0x1F107, 0, 2 | DECOMP_COMPAT, 4848},
+ {0x1F108, 0, 2 | DECOMP_COMPAT, 4850},
+ {0x1F109, 0, 2 | DECOMP_COMPAT, 4852},
+ {0x1F10A, 0, 2 | DECOMP_COMPAT, 4854},
+ {0x1F110, 0, 3 | DECOMP_COMPAT, 4856},
+ {0x1F111, 0, 3 | DECOMP_COMPAT, 4859},
+ {0x1F112, 0, 3 | DECOMP_COMPAT, 4862},
+ {0x1F113, 0, 3 | DECOMP_COMPAT, 4865},
+ {0x1F114, 0, 3 | DECOMP_COMPAT, 4868},
+ {0x1F115, 0, 3 | DECOMP_COMPAT, 4871},
+ {0x1F116, 0, 3 | DECOMP_COMPAT, 4874},
+ {0x1F117, 0, 3 | DECOMP_COMPAT, 4877},
+ {0x1F118, 0, 3 | DECOMP_COMPAT, 4880},
+ {0x1F119, 0, 3 | DECOMP_COMPAT, 4883},
+ {0x1F11A, 0, 3 | DECOMP_COMPAT, 4886},
+ {0x1F11B, 0, 3 | DECOMP_COMPAT, 4889},
+ {0x1F11C, 0, 3 | DECOMP_COMPAT, 4892},
+ {0x1F11D, 0, 3 | DECOMP_COMPAT, 4895},
+ {0x1F11E, 0, 3 | DECOMP_COMPAT, 4898},
+ {0x1F11F, 0, 3 | DECOMP_COMPAT, 4901},
+ {0x1F120, 0, 3 | DECOMP_COMPAT, 4904},
+ {0x1F121, 0, 3 | DECOMP_COMPAT, 4907},
+ {0x1F122, 0, 3 | DECOMP_COMPAT, 4910},
+ {0x1F123, 0, 3 | DECOMP_COMPAT, 4913},
+ {0x1F124, 0, 3 | DECOMP_COMPAT, 4916},
+ {0x1F125, 0, 3 | DECOMP_COMPAT, 4919},
+ {0x1F126, 0, 3 | DECOMP_COMPAT, 4922},
+ {0x1F127, 0, 3 | DECOMP_COMPAT, 4925},
+ {0x1F128, 0, 3 | DECOMP_COMPAT, 4928},
+ {0x1F129, 0, 3 | DECOMP_COMPAT, 4931},
+ {0x1F12A, 0, 3 | DECOMP_COMPAT, 4934},
+ {0x1F12B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0043},
+ {0x1F12C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0052},
+ {0x1F12D, 0, 2 | DECOMP_COMPAT, 4937},
+ {0x1F12E, 0, 2 | DECOMP_COMPAT, 4939},
+ {0x1F130, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0041},
+ {0x1F131, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0042},
+ {0x1F132, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0043},
+ {0x1F133, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0044},
+ {0x1F134, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0045},
+ {0x1F135, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0046},
+ {0x1F136, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0047},
+ {0x1F137, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0048},
+ {0x1F138, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0049},
+ {0x1F139, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004A},
+ {0x1F13A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004B},
+ {0x1F13B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004C},
+ {0x1F13C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004D},
+ {0x1F13D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004E},
+ {0x1F13E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004F},
+ {0x1F13F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0050},
+ {0x1F140, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0051},
+ {0x1F141, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0052},
+ {0x1F142, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0053},
+ {0x1F143, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0054},
+ {0x1F144, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0055},
+ {0x1F145, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0056},
+ {0x1F146, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0057},
+ {0x1F147, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0058},
+ {0x1F148, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0059},
+ {0x1F149, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005A},
+ {0x1F14A, 0, 2 | DECOMP_COMPAT, 4941},
+ {0x1F14B, 0, 2 | DECOMP_COMPAT, 4943},
+ {0x1F14C, 0, 2 | DECOMP_COMPAT, 4945},
+ {0x1F14D, 0, 2 | DECOMP_COMPAT, 4947},
+ {0x1F14E, 0, 3 | DECOMP_COMPAT, 4949},
+ {0x1F14F, 0, 2 | DECOMP_COMPAT, 4952},
+ {0x1F16A, 0, 2 | DECOMP_COMPAT, 4954},
+ {0x1F16B, 0, 2 | DECOMP_COMPAT, 4956},
+ {0x1F16C, 0, 2 | DECOMP_COMPAT, 4958},
+ {0x1F190, 0, 2 | DECOMP_COMPAT, 4960},
+ {0x1F200, 0, 2 | DECOMP_COMPAT, 4962},
+ {0x1F201, 0, 2 | DECOMP_COMPAT, 4964},
+ {0x1F202, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30B5},
+ {0x1F210, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x624B},
+ {0x1F211, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5B57},
+ {0x1F212, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x53CC},
+ {0x1F213, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30C7},
+ {0x1F214, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E8C},
+ {0x1F215, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x591A},
+ {0x1F216, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x89E3},
+ {0x1F217, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5929},
+ {0x1F218, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4EA4},
+ {0x1F219, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6620},
+ {0x1F21A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7121},
+ {0x1F21B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6599},
+ {0x1F21C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x524D},
+ {0x1F21D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5F8C},
+ {0x1F21E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x518D},
+ {0x1F21F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x65B0},
+ {0x1F220, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x521D},
+ {0x1F221, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7D42},
+ {0x1F222, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x751F},
+ {0x1F223, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8CA9},
+ {0x1F224, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x58F0},
+ {0x1F225, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5439},
+ {0x1F226, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6F14},
+ {0x1F227, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6295},
+ {0x1F228, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6355},
+ {0x1F229, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E00},
+ {0x1F22A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E09},
+ {0x1F22B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x904A},
+ {0x1F22C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5DE6},
+ {0x1F22D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E2D},
+ {0x1F22E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x53F3},
+ {0x1F22F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6307},
+ {0x1F230, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8D70},
+ {0x1F231, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6253},
+ {0x1F232, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7981},
+ {0x1F233, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7A7A},
+ {0x1F234, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5408},
+ {0x1F235, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6E80},
+ {0x1F236, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6709},
+ {0x1F237, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6708},
+ {0x1F238, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7533},
+ {0x1F239, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5272},
+ {0x1F23A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x55B6},
+ {0x1F23B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x914D},
+ {0x1F240, 0, 3 | DECOMP_COMPAT, 4966},
+ {0x1F241, 0, 3 | DECOMP_COMPAT, 4969},
+ {0x1F242, 0, 3 | DECOMP_COMPAT, 4972},
+ {0x1F243, 0, 3 | DECOMP_COMPAT, 4975},
+ {0x1F244, 0, 3 | DECOMP_COMPAT, 4978},
+ {0x1F245, 0, 3 | DECOMP_COMPAT, 4981},
+ {0x1F246, 0, 3 | DECOMP_COMPAT, 4984},
+ {0x1F247, 0, 3 | DECOMP_COMPAT, 4987},
+ {0x1F248, 0, 3 | DECOMP_COMPAT, 4990},
+ {0x1F250, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5F97},
+ {0x1F251, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x53EF},
+ {0x1FBF0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0030},
+ {0x1FBF1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0031},
+ {0x1FBF2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0032},
+ {0x1FBF3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0033},
+ {0x1FBF4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0034},
+ {0x1FBF5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0035},
+ {0x1FBF6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0036},
+ {0x1FBF7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0037},
+ {0x1FBF8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0038},
+ {0x1FBF9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0039},
+ {0x2F800, 0, 1 | DECOMP_INLINE, 0x4E3D},
+ {0x2F801, 0, 1 | DECOMP_INLINE, 0x4E38},
+ {0x2F802, 0, 1 | DECOMP_INLINE, 0x4E41},
+ {0x2F803, 0, 1, 4993},
+ {0x2F804, 0, 1 | DECOMP_INLINE, 0x4F60},
+ {0x2F805, 0, 1 | DECOMP_INLINE, 0x4FAE},
+ {0x2F806, 0, 1 | DECOMP_INLINE, 0x4FBB},
+ {0x2F807, 0, 1 | DECOMP_INLINE, 0x5002},
+ {0x2F808, 0, 1 | DECOMP_INLINE, 0x507A},
+ {0x2F809, 0, 1 | DECOMP_INLINE, 0x5099},
+ {0x2F80A, 0, 1 | DECOMP_INLINE, 0x50E7},
+ {0x2F80B, 0, 1 | DECOMP_INLINE, 0x50CF},
+ {0x2F80C, 0, 1 | DECOMP_INLINE, 0x349E},
+ {0x2F80D, 0, 1, 4994},
+ {0x2F80E, 0, 1 | DECOMP_INLINE, 0x514D},
+ {0x2F80F, 0, 1 | DECOMP_INLINE, 0x5154},
+ {0x2F810, 0, 1 | DECOMP_INLINE, 0x5164},
+ {0x2F811, 0, 1 | DECOMP_INLINE, 0x5177},
+ {0x2F812, 0, 1, 4995},
+ {0x2F813, 0, 1 | DECOMP_INLINE, 0x34B9},
+ {0x2F814, 0, 1 | DECOMP_INLINE, 0x5167},
+ {0x2F815, 0, 1 | DECOMP_INLINE, 0x518D},
+ {0x2F816, 0, 1, 4996},
+ {0x2F817, 0, 1 | DECOMP_INLINE, 0x5197},
+ {0x2F818, 0, 1 | DECOMP_INLINE, 0x51A4},
+ {0x2F819, 0, 1 | DECOMP_INLINE, 0x4ECC},
+ {0x2F81A, 0, 1 | DECOMP_INLINE, 0x51AC},
+ {0x2F81B, 0, 1 | DECOMP_INLINE, 0x51B5},
+ {0x2F81C, 0, 1, 4997},
+ {0x2F81D, 0, 1 | DECOMP_INLINE, 0x51F5},
+ {0x2F81E, 0, 1 | DECOMP_INLINE, 0x5203},
+ {0x2F81F, 0, 1 | DECOMP_INLINE, 0x34DF},
+ {0x2F820, 0, 1 | DECOMP_INLINE, 0x523B},
+ {0x2F821, 0, 1 | DECOMP_INLINE, 0x5246},
+ {0x2F822, 0, 1 | DECOMP_INLINE, 0x5272},
+ {0x2F823, 0, 1 | DECOMP_INLINE, 0x5277},
+ {0x2F824, 0, 1 | DECOMP_INLINE, 0x3515},
+ {0x2F825, 0, 1 | DECOMP_INLINE, 0x52C7},
+ {0x2F826, 0, 1 | DECOMP_INLINE, 0x52C9},
+ {0x2F827, 0, 1 | DECOMP_INLINE, 0x52E4},
+ {0x2F828, 0, 1 | DECOMP_INLINE, 0x52FA},
+ {0x2F829, 0, 1 | DECOMP_INLINE, 0x5305},
+ {0x2F82A, 0, 1 | DECOMP_INLINE, 0x5306},
+ {0x2F82B, 0, 1 | DECOMP_INLINE, 0x5317},
+ {0x2F82C, 0, 1 | DECOMP_INLINE, 0x5349},
+ {0x2F82D, 0, 1 | DECOMP_INLINE, 0x5351},
+ {0x2F82E, 0, 1 | DECOMP_INLINE, 0x535A},
+ {0x2F82F, 0, 1 | DECOMP_INLINE, 0x5373},
+ {0x2F830, 0, 1 | DECOMP_INLINE, 0x537D},
+ {0x2F831, 0, 1 | DECOMP_INLINE, 0x537F},
+ {0x2F832, 0, 1 | DECOMP_INLINE, 0x537F},
+ {0x2F833, 0, 1 | DECOMP_INLINE, 0x537F},
+ {0x2F834, 0, 1, 4998},
+ {0x2F835, 0, 1 | DECOMP_INLINE, 0x7070},
+ {0x2F836, 0, 1 | DECOMP_INLINE, 0x53CA},
+ {0x2F837, 0, 1 | DECOMP_INLINE, 0x53DF},
+ {0x2F838, 0, 1, 4999},
+ {0x2F839, 0, 1 | DECOMP_INLINE, 0x53EB},
+ {0x2F83A, 0, 1 | DECOMP_INLINE, 0x53F1},
+ {0x2F83B, 0, 1 | DECOMP_INLINE, 0x5406},
+ {0x2F83C, 0, 1 | DECOMP_INLINE, 0x549E},
+ {0x2F83D, 0, 1 | DECOMP_INLINE, 0x5438},
+ {0x2F83E, 0, 1 | DECOMP_INLINE, 0x5448},
+ {0x2F83F, 0, 1 | DECOMP_INLINE, 0x5468},
+ {0x2F840, 0, 1 | DECOMP_INLINE, 0x54A2},
+ {0x2F841, 0, 1 | DECOMP_INLINE, 0x54F6},
+ {0x2F842, 0, 1 | DECOMP_INLINE, 0x5510},
+ {0x2F843, 0, 1 | DECOMP_INLINE, 0x5553},
+ {0x2F844, 0, 1 | DECOMP_INLINE, 0x5563},
+ {0x2F845, 0, 1 | DECOMP_INLINE, 0x5584},
+ {0x2F846, 0, 1 | DECOMP_INLINE, 0x5584},
+ {0x2F847, 0, 1 | DECOMP_INLINE, 0x5599},
+ {0x2F848, 0, 1 | DECOMP_INLINE, 0x55AB},
+ {0x2F849, 0, 1 | DECOMP_INLINE, 0x55B3},
+ {0x2F84A, 0, 1 | DECOMP_INLINE, 0x55C2},
+ {0x2F84B, 0, 1 | DECOMP_INLINE, 0x5716},
+ {0x2F84C, 0, 1 | DECOMP_INLINE, 0x5606},
+ {0x2F84D, 0, 1 | DECOMP_INLINE, 0x5717},
+ {0x2F84E, 0, 1 | DECOMP_INLINE, 0x5651},
+ {0x2F84F, 0, 1 | DECOMP_INLINE, 0x5674},
+ {0x2F850, 0, 1 | DECOMP_INLINE, 0x5207},
+ {0x2F851, 0, 1 | DECOMP_INLINE, 0x58EE},
+ {0x2F852, 0, 1 | DECOMP_INLINE, 0x57CE},
+ {0x2F853, 0, 1 | DECOMP_INLINE, 0x57F4},
+ {0x2F854, 0, 1 | DECOMP_INLINE, 0x580D},
+ {0x2F855, 0, 1 | DECOMP_INLINE, 0x578B},
+ {0x2F856, 0, 1 | DECOMP_INLINE, 0x5832},
+ {0x2F857, 0, 1 | DECOMP_INLINE, 0x5831},
+ {0x2F858, 0, 1 | DECOMP_INLINE, 0x58AC},
+ {0x2F859, 0, 1, 5000},
+ {0x2F85A, 0, 1 | DECOMP_INLINE, 0x58F2},
+ {0x2F85B, 0, 1 | DECOMP_INLINE, 0x58F7},
+ {0x2F85C, 0, 1 | DECOMP_INLINE, 0x5906},
+ {0x2F85D, 0, 1 | DECOMP_INLINE, 0x591A},
+ {0x2F85E, 0, 1 | DECOMP_INLINE, 0x5922},
+ {0x2F85F, 0, 1 | DECOMP_INLINE, 0x5962},
+ {0x2F860, 0, 1, 5001},
+ {0x2F861, 0, 1, 5002},
+ {0x2F862, 0, 1 | DECOMP_INLINE, 0x59EC},
+ {0x2F863, 0, 1 | DECOMP_INLINE, 0x5A1B},
+ {0x2F864, 0, 1 | DECOMP_INLINE, 0x5A27},
+ {0x2F865, 0, 1 | DECOMP_INLINE, 0x59D8},
+ {0x2F866, 0, 1 | DECOMP_INLINE, 0x5A66},
+ {0x2F867, 0, 1 | DECOMP_INLINE, 0x36EE},
+ {0x2F868, 0, 1 | DECOMP_INLINE, 0x36FC},
+ {0x2F869, 0, 1 | DECOMP_INLINE, 0x5B08},
+ {0x2F86A, 0, 1 | DECOMP_INLINE, 0x5B3E},
+ {0x2F86B, 0, 1 | DECOMP_INLINE, 0x5B3E},
+ {0x2F86C, 0, 1, 5003},
+ {0x2F86D, 0, 1 | DECOMP_INLINE, 0x5BC3},
+ {0x2F86E, 0, 1 | DECOMP_INLINE, 0x5BD8},
+ {0x2F86F, 0, 1 | DECOMP_INLINE, 0x5BE7},
+ {0x2F870, 0, 1 | DECOMP_INLINE, 0x5BF3},
+ {0x2F871, 0, 1, 5004},
+ {0x2F872, 0, 1 | DECOMP_INLINE, 0x5BFF},
+ {0x2F873, 0, 1 | DECOMP_INLINE, 0x5C06},
+ {0x2F874, 0, 1 | DECOMP_INLINE, 0x5F53},
+ {0x2F875, 0, 1 | DECOMP_INLINE, 0x5C22},
+ {0x2F876, 0, 1 | DECOMP_INLINE, 0x3781},
+ {0x2F877, 0, 1 | DECOMP_INLINE, 0x5C60},
+ {0x2F878, 0, 1 | DECOMP_INLINE, 0x5C6E},
+ {0x2F879, 0, 1 | DECOMP_INLINE, 0x5CC0},
+ {0x2F87A, 0, 1 | DECOMP_INLINE, 0x5C8D},
+ {0x2F87B, 0, 1, 5005},
+ {0x2F87C, 0, 1 | DECOMP_INLINE, 0x5D43},
+ {0x2F87D, 0, 1, 5006},
+ {0x2F87E, 0, 1 | DECOMP_INLINE, 0x5D6E},
+ {0x2F87F, 0, 1 | DECOMP_INLINE, 0x5D6B},
+ {0x2F880, 0, 1 | DECOMP_INLINE, 0x5D7C},
+ {0x2F881, 0, 1 | DECOMP_INLINE, 0x5DE1},
+ {0x2F882, 0, 1 | DECOMP_INLINE, 0x5DE2},
+ {0x2F883, 0, 1 | DECOMP_INLINE, 0x382F},
+ {0x2F884, 0, 1 | DECOMP_INLINE, 0x5DFD},
+ {0x2F885, 0, 1 | DECOMP_INLINE, 0x5E28},
+ {0x2F886, 0, 1 | DECOMP_INLINE, 0x5E3D},
+ {0x2F887, 0, 1 | DECOMP_INLINE, 0x5E69},
+ {0x2F888, 0, 1 | DECOMP_INLINE, 0x3862},
+ {0x2F889, 0, 1, 5007},
+ {0x2F88A, 0, 1 | DECOMP_INLINE, 0x387C},
+ {0x2F88B, 0, 1 | DECOMP_INLINE, 0x5EB0},
+ {0x2F88C, 0, 1 | DECOMP_INLINE, 0x5EB3},
+ {0x2F88D, 0, 1 | DECOMP_INLINE, 0x5EB6},
+ {0x2F88E, 0, 1 | DECOMP_INLINE, 0x5ECA},
+ {0x2F88F, 0, 1, 5008},
+ {0x2F890, 0, 1 | DECOMP_INLINE, 0x5EFE},
+ {0x2F891, 0, 1, 5009},
+ {0x2F892, 0, 1, 5010},
+ {0x2F893, 0, 1 | DECOMP_INLINE, 0x8201},
+ {0x2F894, 0, 1 | DECOMP_INLINE, 0x5F22},
+ {0x2F895, 0, 1 | DECOMP_INLINE, 0x5F22},
+ {0x2F896, 0, 1 | DECOMP_INLINE, 0x38C7},
+ {0x2F897, 0, 1, 5011},
+ {0x2F898, 0, 1, 5012},
+ {0x2F899, 0, 1 | DECOMP_INLINE, 0x5F62},
+ {0x2F89A, 0, 1 | DECOMP_INLINE, 0x5F6B},
+ {0x2F89B, 0, 1 | DECOMP_INLINE, 0x38E3},
+ {0x2F89C, 0, 1 | DECOMP_INLINE, 0x5F9A},
+ {0x2F89D, 0, 1 | DECOMP_INLINE, 0x5FCD},
+ {0x2F89E, 0, 1 | DECOMP_INLINE, 0x5FD7},
+ {0x2F89F, 0, 1 | DECOMP_INLINE, 0x5FF9},
+ {0x2F8A0, 0, 1 | DECOMP_INLINE, 0x6081},
+ {0x2F8A1, 0, 1 | DECOMP_INLINE, 0x393A},
+ {0x2F8A2, 0, 1 | DECOMP_INLINE, 0x391C},
+ {0x2F8A3, 0, 1 | DECOMP_INLINE, 0x6094},
+ {0x2F8A4, 0, 1, 5013},
+ {0x2F8A5, 0, 1 | DECOMP_INLINE, 0x60C7},
+ {0x2F8A6, 0, 1 | DECOMP_INLINE, 0x6148},
+ {0x2F8A7, 0, 1 | DECOMP_INLINE, 0x614C},
+ {0x2F8A8, 0, 1 | DECOMP_INLINE, 0x614E},
+ {0x2F8A9, 0, 1 | DECOMP_INLINE, 0x614C},
+ {0x2F8AA, 0, 1 | DECOMP_INLINE, 0x617A},
+ {0x2F8AB, 0, 1 | DECOMP_INLINE, 0x618E},
+ {0x2F8AC, 0, 1 | DECOMP_INLINE, 0x61B2},
+ {0x2F8AD, 0, 1 | DECOMP_INLINE, 0x61A4},
+ {0x2F8AE, 0, 1 | DECOMP_INLINE, 0x61AF},
+ {0x2F8AF, 0, 1 | DECOMP_INLINE, 0x61DE},
+ {0x2F8B0, 0, 1 | DECOMP_INLINE, 0x61F2},
+ {0x2F8B1, 0, 1 | DECOMP_INLINE, 0x61F6},
+ {0x2F8B2, 0, 1 | DECOMP_INLINE, 0x6210},
+ {0x2F8B3, 0, 1 | DECOMP_INLINE, 0x621B},
+ {0x2F8B4, 0, 1 | DECOMP_INLINE, 0x625D},
+ {0x2F8B5, 0, 1 | DECOMP_INLINE, 0x62B1},
+ {0x2F8B6, 0, 1 | DECOMP_INLINE, 0x62D4},
+ {0x2F8B7, 0, 1 | DECOMP_INLINE, 0x6350},
+ {0x2F8B8, 0, 1, 5014},
+ {0x2F8B9, 0, 1 | DECOMP_INLINE, 0x633D},
+ {0x2F8BA, 0, 1 | DECOMP_INLINE, 0x62FC},
+ {0x2F8BB, 0, 1 | DECOMP_INLINE, 0x6368},
+ {0x2F8BC, 0, 1 | DECOMP_INLINE, 0x6383},
+ {0x2F8BD, 0, 1 | DECOMP_INLINE, 0x63E4},
+ {0x2F8BE, 0, 1, 5015},
+ {0x2F8BF, 0, 1 | DECOMP_INLINE, 0x6422},
+ {0x2F8C0, 0, 1 | DECOMP_INLINE, 0x63C5},
+ {0x2F8C1, 0, 1 | DECOMP_INLINE, 0x63A9},
+ {0x2F8C2, 0, 1 | DECOMP_INLINE, 0x3A2E},
+ {0x2F8C3, 0, 1 | DECOMP_INLINE, 0x6469},
+ {0x2F8C4, 0, 1 | DECOMP_INLINE, 0x647E},
+ {0x2F8C5, 0, 1 | DECOMP_INLINE, 0x649D},
+ {0x2F8C6, 0, 1 | DECOMP_INLINE, 0x6477},
+ {0x2F8C7, 0, 1 | DECOMP_INLINE, 0x3A6C},
+ {0x2F8C8, 0, 1 | DECOMP_INLINE, 0x654F},
+ {0x2F8C9, 0, 1 | DECOMP_INLINE, 0x656C},
+ {0x2F8CA, 0, 1, 5016},
+ {0x2F8CB, 0, 1 | DECOMP_INLINE, 0x65E3},
+ {0x2F8CC, 0, 1 | DECOMP_INLINE, 0x66F8},
+ {0x2F8CD, 0, 1 | DECOMP_INLINE, 0x6649},
+ {0x2F8CE, 0, 1 | DECOMP_INLINE, 0x3B19},
+ {0x2F8CF, 0, 1 | DECOMP_INLINE, 0x6691},
+ {0x2F8D0, 0, 1 | DECOMP_INLINE, 0x3B08},
+ {0x2F8D1, 0, 1 | DECOMP_INLINE, 0x3AE4},
+ {0x2F8D2, 0, 1 | DECOMP_INLINE, 0x5192},
+ {0x2F8D3, 0, 1 | DECOMP_INLINE, 0x5195},
+ {0x2F8D4, 0, 1 | DECOMP_INLINE, 0x6700},
+ {0x2F8D5, 0, 1 | DECOMP_INLINE, 0x669C},
+ {0x2F8D6, 0, 1 | DECOMP_INLINE, 0x80AD},
+ {0x2F8D7, 0, 1 | DECOMP_INLINE, 0x43D9},
+ {0x2F8D8, 0, 1 | DECOMP_INLINE, 0x6717},
+ {0x2F8D9, 0, 1 | DECOMP_INLINE, 0x671B},
+ {0x2F8DA, 0, 1 | DECOMP_INLINE, 0x6721},
+ {0x2F8DB, 0, 1 | DECOMP_INLINE, 0x675E},
+ {0x2F8DC, 0, 1 | DECOMP_INLINE, 0x6753},
+ {0x2F8DD, 0, 1, 5017},
+ {0x2F8DE, 0, 1 | DECOMP_INLINE, 0x3B49},
+ {0x2F8DF, 0, 1 | DECOMP_INLINE, 0x67FA},
+ {0x2F8E0, 0, 1 | DECOMP_INLINE, 0x6785},
+ {0x2F8E1, 0, 1 | DECOMP_INLINE, 0x6852},
+ {0x2F8E2, 0, 1 | DECOMP_INLINE, 0x6885},
+ {0x2F8E3, 0, 1, 5018},
+ {0x2F8E4, 0, 1 | DECOMP_INLINE, 0x688E},
+ {0x2F8E5, 0, 1 | DECOMP_INLINE, 0x681F},
+ {0x2F8E6, 0, 1 | DECOMP_INLINE, 0x6914},
+ {0x2F8E7, 0, 1 | DECOMP_INLINE, 0x3B9D},
+ {0x2F8E8, 0, 1 | DECOMP_INLINE, 0x6942},
+ {0x2F8E9, 0, 1 | DECOMP_INLINE, 0x69A3},
+ {0x2F8EA, 0, 1 | DECOMP_INLINE, 0x69EA},
+ {0x2F8EB, 0, 1 | DECOMP_INLINE, 0x6AA8},
+ {0x2F8EC, 0, 1, 5019},
+ {0x2F8ED, 0, 1 | DECOMP_INLINE, 0x6ADB},
+ {0x2F8EE, 0, 1 | DECOMP_INLINE, 0x3C18},
+ {0x2F8EF, 0, 1 | DECOMP_INLINE, 0x6B21},
+ {0x2F8F0, 0, 1, 5020},
+ {0x2F8F1, 0, 1 | DECOMP_INLINE, 0x6B54},
+ {0x2F8F2, 0, 1 | DECOMP_INLINE, 0x3C4E},
+ {0x2F8F3, 0, 1 | DECOMP_INLINE, 0x6B72},
+ {0x2F8F4, 0, 1 | DECOMP_INLINE, 0x6B9F},
+ {0x2F8F5, 0, 1 | DECOMP_INLINE, 0x6BBA},
+ {0x2F8F6, 0, 1 | DECOMP_INLINE, 0x6BBB},
+ {0x2F8F7, 0, 1, 5021},
+ {0x2F8F8, 0, 1, 5022},
+ {0x2F8F9, 0, 1, 5023},
+ {0x2F8FA, 0, 1 | DECOMP_INLINE, 0x6C4E},
+ {0x2F8FB, 0, 1, 5024},
+ {0x2F8FC, 0, 1 | DECOMP_INLINE, 0x6CBF},
+ {0x2F8FD, 0, 1 | DECOMP_INLINE, 0x6CCD},
+ {0x2F8FE, 0, 1 | DECOMP_INLINE, 0x6C67},
+ {0x2F8FF, 0, 1 | DECOMP_INLINE, 0x6D16},
+ {0x2F900, 0, 1 | DECOMP_INLINE, 0x6D3E},
+ {0x2F901, 0, 1 | DECOMP_INLINE, 0x6D77},
+ {0x2F902, 0, 1 | DECOMP_INLINE, 0x6D41},
+ {0x2F903, 0, 1 | DECOMP_INLINE, 0x6D69},
+ {0x2F904, 0, 1 | DECOMP_INLINE, 0x6D78},
+ {0x2F905, 0, 1 | DECOMP_INLINE, 0x6D85},
+ {0x2F906, 0, 1, 5025},
+ {0x2F907, 0, 1 | DECOMP_INLINE, 0x6D34},
+ {0x2F908, 0, 1 | DECOMP_INLINE, 0x6E2F},
+ {0x2F909, 0, 1 | DECOMP_INLINE, 0x6E6E},
+ {0x2F90A, 0, 1 | DECOMP_INLINE, 0x3D33},
+ {0x2F90B, 0, 1 | DECOMP_INLINE, 0x6ECB},
+ {0x2F90C, 0, 1 | DECOMP_INLINE, 0x6EC7},
+ {0x2F90D, 0, 1, 5026},
+ {0x2F90E, 0, 1 | DECOMP_INLINE, 0x6DF9},
+ {0x2F90F, 0, 1 | DECOMP_INLINE, 0x6F6E},
+ {0x2F910, 0, 1, 5027},
+ {0x2F911, 0, 1, 5028},
+ {0x2F912, 0, 1 | DECOMP_INLINE, 0x6FC6},
+ {0x2F913, 0, 1 | DECOMP_INLINE, 0x7039},
+ {0x2F914, 0, 1 | DECOMP_INLINE, 0x701E},
+ {0x2F915, 0, 1 | DECOMP_INLINE, 0x701B},
+ {0x2F916, 0, 1 | DECOMP_INLINE, 0x3D96},
+ {0x2F917, 0, 1 | DECOMP_INLINE, 0x704A},
+ {0x2F918, 0, 1 | DECOMP_INLINE, 0x707D},
+ {0x2F919, 0, 1 | DECOMP_INLINE, 0x7077},
+ {0x2F91A, 0, 1 | DECOMP_INLINE, 0x70AD},
+ {0x2F91B, 0, 1, 5029},
+ {0x2F91C, 0, 1 | DECOMP_INLINE, 0x7145},
+ {0x2F91D, 0, 1, 5030},
+ {0x2F91E, 0, 1 | DECOMP_INLINE, 0x719C},
+ {0x2F91F, 0, 1, 5031},
+ {0x2F920, 0, 1 | DECOMP_INLINE, 0x7228},
+ {0x2F921, 0, 1 | DECOMP_INLINE, 0x7235},
+ {0x2F922, 0, 1 | DECOMP_INLINE, 0x7250},
+ {0x2F923, 0, 1, 5032},
+ {0x2F924, 0, 1 | DECOMP_INLINE, 0x7280},
+ {0x2F925, 0, 1 | DECOMP_INLINE, 0x7295},
+ {0x2F926, 0, 1, 5033},
+ {0x2F927, 0, 1, 5034},
+ {0x2F928, 0, 1 | DECOMP_INLINE, 0x737A},
+ {0x2F929, 0, 1 | DECOMP_INLINE, 0x738B},
+ {0x2F92A, 0, 1 | DECOMP_INLINE, 0x3EAC},
+ {0x2F92B, 0, 1 | DECOMP_INLINE, 0x73A5},
+ {0x2F92C, 0, 1 | DECOMP_INLINE, 0x3EB8},
+ {0x2F92D, 0, 1 | DECOMP_INLINE, 0x3EB8},
+ {0x2F92E, 0, 1 | DECOMP_INLINE, 0x7447},
+ {0x2F92F, 0, 1 | DECOMP_INLINE, 0x745C},
+ {0x2F930, 0, 1 | DECOMP_INLINE, 0x7471},
+ {0x2F931, 0, 1 | DECOMP_INLINE, 0x7485},
+ {0x2F932, 0, 1 | DECOMP_INLINE, 0x74CA},
+ {0x2F933, 0, 1 | DECOMP_INLINE, 0x3F1B},
+ {0x2F934, 0, 1 | DECOMP_INLINE, 0x7524},
+ {0x2F935, 0, 1, 5035},
+ {0x2F936, 0, 1 | DECOMP_INLINE, 0x753E},
+ {0x2F937, 0, 1, 5036},
+ {0x2F938, 0, 1 | DECOMP_INLINE, 0x7570},
+ {0x2F939, 0, 1, 5037},
+ {0x2F93A, 0, 1 | DECOMP_INLINE, 0x7610},
+ {0x2F93B, 0, 1, 5038},
+ {0x2F93C, 0, 1, 5039},
+ {0x2F93D, 0, 1, 5040},
+ {0x2F93E, 0, 1 | DECOMP_INLINE, 0x3FFC},
+ {0x2F93F, 0, 1 | DECOMP_INLINE, 0x4008},
+ {0x2F940, 0, 1 | DECOMP_INLINE, 0x76F4},
+ {0x2F941, 0, 1, 5041},
+ {0x2F942, 0, 1, 5042},
+ {0x2F943, 0, 1, 5043},
+ {0x2F944, 0, 1, 5044},
+ {0x2F945, 0, 1 | DECOMP_INLINE, 0x771E},
+ {0x2F946, 0, 1 | DECOMP_INLINE, 0x771F},
+ {0x2F947, 0, 1 | DECOMP_INLINE, 0x771F},
+ {0x2F948, 0, 1 | DECOMP_INLINE, 0x774A},
+ {0x2F949, 0, 1 | DECOMP_INLINE, 0x4039},
+ {0x2F94A, 0, 1 | DECOMP_INLINE, 0x778B},
+ {0x2F94B, 0, 1 | DECOMP_INLINE, 0x4046},
+ {0x2F94C, 0, 1 | DECOMP_INLINE, 0x4096},
+ {0x2F94D, 0, 1, 5045},
+ {0x2F94E, 0, 1 | DECOMP_INLINE, 0x784E},
+ {0x2F94F, 0, 1 | DECOMP_INLINE, 0x788C},
+ {0x2F950, 0, 1 | DECOMP_INLINE, 0x78CC},
+ {0x2F951, 0, 1 | DECOMP_INLINE, 0x40E3},
+ {0x2F952, 0, 1, 5046},
+ {0x2F953, 0, 1 | DECOMP_INLINE, 0x7956},
+ {0x2F954, 0, 1, 5047},
+ {0x2F955, 0, 1, 5048},
+ {0x2F956, 0, 1 | DECOMP_INLINE, 0x798F},
+ {0x2F957, 0, 1 | DECOMP_INLINE, 0x79EB},
+ {0x2F958, 0, 1 | DECOMP_INLINE, 0x412F},
+ {0x2F959, 0, 1 | DECOMP_INLINE, 0x7A40},
+ {0x2F95A, 0, 1 | DECOMP_INLINE, 0x7A4A},
+ {0x2F95B, 0, 1 | DECOMP_INLINE, 0x7A4F},
+ {0x2F95C, 0, 1, 5049},
+ {0x2F95D, 0, 1, 5050},
+ {0x2F95E, 0, 1, 5051},
+ {0x2F95F, 0, 1 | DECOMP_INLINE, 0x7AEE},
+ {0x2F960, 0, 1 | DECOMP_INLINE, 0x4202},
+ {0x2F961, 0, 1, 5052},
+ {0x2F962, 0, 1 | DECOMP_INLINE, 0x7BC6},
+ {0x2F963, 0, 1 | DECOMP_INLINE, 0x7BC9},
+ {0x2F964, 0, 1 | DECOMP_INLINE, 0x4227},
+ {0x2F965, 0, 1, 5053},
+ {0x2F966, 0, 1 | DECOMP_INLINE, 0x7CD2},
+ {0x2F967, 0, 1 | DECOMP_INLINE, 0x42A0},
+ {0x2F968, 0, 1 | DECOMP_INLINE, 0x7CE8},
+ {0x2F969, 0, 1 | DECOMP_INLINE, 0x7CE3},
+ {0x2F96A, 0, 1 | DECOMP_INLINE, 0x7D00},
+ {0x2F96B, 0, 1, 5054},
+ {0x2F96C, 0, 1 | DECOMP_INLINE, 0x7D63},
+ {0x2F96D, 0, 1 | DECOMP_INLINE, 0x4301},
+ {0x2F96E, 0, 1 | DECOMP_INLINE, 0x7DC7},
+ {0x2F96F, 0, 1 | DECOMP_INLINE, 0x7E02},
+ {0x2F970, 0, 1 | DECOMP_INLINE, 0x7E45},
+ {0x2F971, 0, 1 | DECOMP_INLINE, 0x4334},
+ {0x2F972, 0, 1, 5055},
+ {0x2F973, 0, 1, 5056},
+ {0x2F974, 0, 1 | DECOMP_INLINE, 0x4359},
+ {0x2F975, 0, 1, 5057},
+ {0x2F976, 0, 1 | DECOMP_INLINE, 0x7F7A},
+ {0x2F977, 0, 1, 5058},
+ {0x2F978, 0, 1 | DECOMP_INLINE, 0x7F95},
+ {0x2F979, 0, 1 | DECOMP_INLINE, 0x7FFA},
+ {0x2F97A, 0, 1 | DECOMP_INLINE, 0x8005},
+ {0x2F97B, 0, 1, 5059},
+ {0x2F97C, 0, 1, 5060},
+ {0x2F97D, 0, 1 | DECOMP_INLINE, 0x8060},
+ {0x2F97E, 0, 1, 5061},
+ {0x2F97F, 0, 1 | DECOMP_INLINE, 0x8070},
+ {0x2F980, 0, 1, 5062},
+ {0x2F981, 0, 1 | DECOMP_INLINE, 0x43D5},
+ {0x2F982, 0, 1 | DECOMP_INLINE, 0x80B2},
+ {0x2F983, 0, 1 | DECOMP_INLINE, 0x8103},
+ {0x2F984, 0, 1 | DECOMP_INLINE, 0x440B},
+ {0x2F985, 0, 1 | DECOMP_INLINE, 0x813E},
+ {0x2F986, 0, 1 | DECOMP_INLINE, 0x5AB5},
+ {0x2F987, 0, 1, 5063},
+ {0x2F988, 0, 1, 5064},
+ {0x2F989, 0, 1, 5065},
+ {0x2F98A, 0, 1, 5066},
+ {0x2F98B, 0, 1 | DECOMP_INLINE, 0x8201},
+ {0x2F98C, 0, 1 | DECOMP_INLINE, 0x8204},
+ {0x2F98D, 0, 1 | DECOMP_INLINE, 0x8F9E},
+ {0x2F98E, 0, 1 | DECOMP_INLINE, 0x446B},
+ {0x2F98F, 0, 1 | DECOMP_INLINE, 0x8291},
+ {0x2F990, 0, 1 | DECOMP_INLINE, 0x828B},
+ {0x2F991, 0, 1 | DECOMP_INLINE, 0x829D},
+ {0x2F992, 0, 1 | DECOMP_INLINE, 0x52B3},
+ {0x2F993, 0, 1 | DECOMP_INLINE, 0x82B1},
+ {0x2F994, 0, 1 | DECOMP_INLINE, 0x82B3},
+ {0x2F995, 0, 1 | DECOMP_INLINE, 0x82BD},
+ {0x2F996, 0, 1 | DECOMP_INLINE, 0x82E6},
+ {0x2F997, 0, 1, 5067},
+ {0x2F998, 0, 1 | DECOMP_INLINE, 0x82E5},
+ {0x2F999, 0, 1 | DECOMP_INLINE, 0x831D},
+ {0x2F99A, 0, 1 | DECOMP_INLINE, 0x8363},
+ {0x2F99B, 0, 1 | DECOMP_INLINE, 0x83AD},
+ {0x2F99C, 0, 1 | DECOMP_INLINE, 0x8323},
+ {0x2F99D, 0, 1 | DECOMP_INLINE, 0x83BD},
+ {0x2F99E, 0, 1 | DECOMP_INLINE, 0x83E7},
+ {0x2F99F, 0, 1 | DECOMP_INLINE, 0x8457},
+ {0x2F9A0, 0, 1 | DECOMP_INLINE, 0x8353},
+ {0x2F9A1, 0, 1 | DECOMP_INLINE, 0x83CA},
+ {0x2F9A2, 0, 1 | DECOMP_INLINE, 0x83CC},
+ {0x2F9A3, 0, 1 | DECOMP_INLINE, 0x83DC},
+ {0x2F9A4, 0, 1, 5068},
+ {0x2F9A5, 0, 1, 5069},
+ {0x2F9A6, 0, 1, 5070},
+ {0x2F9A7, 0, 1 | DECOMP_INLINE, 0x452B},
+ {0x2F9A8, 0, 1 | DECOMP_INLINE, 0x84F1},
+ {0x2F9A9, 0, 1 | DECOMP_INLINE, 0x84F3},
+ {0x2F9AA, 0, 1 | DECOMP_INLINE, 0x8516},
+ {0x2F9AB, 0, 1, 5071},
+ {0x2F9AC, 0, 1 | DECOMP_INLINE, 0x8564},
+ {0x2F9AD, 0, 1, 5072},
+ {0x2F9AE, 0, 1 | DECOMP_INLINE, 0x455D},
+ {0x2F9AF, 0, 1 | DECOMP_INLINE, 0x4561},
+ {0x2F9B0, 0, 1, 5073},
+ {0x2F9B1, 0, 1, 5074},
+ {0x2F9B2, 0, 1 | DECOMP_INLINE, 0x456B},
+ {0x2F9B3, 0, 1 | DECOMP_INLINE, 0x8650},
+ {0x2F9B4, 0, 1 | DECOMP_INLINE, 0x865C},
+ {0x2F9B5, 0, 1 | DECOMP_INLINE, 0x8667},
+ {0x2F9B6, 0, 1 | DECOMP_INLINE, 0x8669},
+ {0x2F9B7, 0, 1 | DECOMP_INLINE, 0x86A9},
+ {0x2F9B8, 0, 1 | DECOMP_INLINE, 0x8688},
+ {0x2F9B9, 0, 1 | DECOMP_INLINE, 0x870E},
+ {0x2F9BA, 0, 1 | DECOMP_INLINE, 0x86E2},
+ {0x2F9BB, 0, 1 | DECOMP_INLINE, 0x8779},
+ {0x2F9BC, 0, 1 | DECOMP_INLINE, 0x8728},
+ {0x2F9BD, 0, 1 | DECOMP_INLINE, 0x876B},
+ {0x2F9BE, 0, 1 | DECOMP_INLINE, 0x8786},
+ {0x2F9BF, 0, 1 | DECOMP_INLINE, 0x45D7},
+ {0x2F9C0, 0, 1 | DECOMP_INLINE, 0x87E1},
+ {0x2F9C1, 0, 1 | DECOMP_INLINE, 0x8801},
+ {0x2F9C2, 0, 1 | DECOMP_INLINE, 0x45F9},
+ {0x2F9C3, 0, 1 | DECOMP_INLINE, 0x8860},
+ {0x2F9C4, 0, 1 | DECOMP_INLINE, 0x8863},
+ {0x2F9C5, 0, 1, 5075},
+ {0x2F9C6, 0, 1 | DECOMP_INLINE, 0x88D7},
+ {0x2F9C7, 0, 1 | DECOMP_INLINE, 0x88DE},
+ {0x2F9C8, 0, 1 | DECOMP_INLINE, 0x4635},
+ {0x2F9C9, 0, 1 | DECOMP_INLINE, 0x88FA},
+ {0x2F9CA, 0, 1 | DECOMP_INLINE, 0x34BB},
+ {0x2F9CB, 0, 1, 5076},
+ {0x2F9CC, 0, 1, 5077},
+ {0x2F9CD, 0, 1 | DECOMP_INLINE, 0x46BE},
+ {0x2F9CE, 0, 1 | DECOMP_INLINE, 0x46C7},
+ {0x2F9CF, 0, 1 | DECOMP_INLINE, 0x8AA0},
+ {0x2F9D0, 0, 1 | DECOMP_INLINE, 0x8AED},
+ {0x2F9D1, 0, 1 | DECOMP_INLINE, 0x8B8A},
+ {0x2F9D2, 0, 1 | DECOMP_INLINE, 0x8C55},
+ {0x2F9D3, 0, 1, 5078},
+ {0x2F9D4, 0, 1 | DECOMP_INLINE, 0x8CAB},
+ {0x2F9D5, 0, 1 | DECOMP_INLINE, 0x8CC1},
+ {0x2F9D6, 0, 1 | DECOMP_INLINE, 0x8D1B},
+ {0x2F9D7, 0, 1 | DECOMP_INLINE, 0x8D77},
+ {0x2F9D8, 0, 1, 5079},
+ {0x2F9D9, 0, 1, 5080},
+ {0x2F9DA, 0, 1 | DECOMP_INLINE, 0x8DCB},
+ {0x2F9DB, 0, 1 | DECOMP_INLINE, 0x8DBC},
+ {0x2F9DC, 0, 1 | DECOMP_INLINE, 0x8DF0},
+ {0x2F9DD, 0, 1, 5081},
+ {0x2F9DE, 0, 1 | DECOMP_INLINE, 0x8ED4},
+ {0x2F9DF, 0, 1 | DECOMP_INLINE, 0x8F38},
+ {0x2F9E0, 0, 1, 5082},
+ {0x2F9E1, 0, 1, 5083},
+ {0x2F9E2, 0, 1 | DECOMP_INLINE, 0x9094},
+ {0x2F9E3, 0, 1 | DECOMP_INLINE, 0x90F1},
+ {0x2F9E4, 0, 1 | DECOMP_INLINE, 0x9111},
+ {0x2F9E5, 0, 1, 5084},
+ {0x2F9E6, 0, 1 | DECOMP_INLINE, 0x911B},
+ {0x2F9E7, 0, 1 | DECOMP_INLINE, 0x9238},
+ {0x2F9E8, 0, 1 | DECOMP_INLINE, 0x92D7},
+ {0x2F9E9, 0, 1 | DECOMP_INLINE, 0x92D8},
+ {0x2F9EA, 0, 1 | DECOMP_INLINE, 0x927C},
+ {0x2F9EB, 0, 1 | DECOMP_INLINE, 0x93F9},
+ {0x2F9EC, 0, 1 | DECOMP_INLINE, 0x9415},
+ {0x2F9ED, 0, 1, 5085},
+ {0x2F9EE, 0, 1 | DECOMP_INLINE, 0x958B},
+ {0x2F9EF, 0, 1 | DECOMP_INLINE, 0x4995},
+ {0x2F9F0, 0, 1 | DECOMP_INLINE, 0x95B7},
+ {0x2F9F1, 0, 1, 5086},
+ {0x2F9F2, 0, 1 | DECOMP_INLINE, 0x49E6},
+ {0x2F9F3, 0, 1 | DECOMP_INLINE, 0x96C3},
+ {0x2F9F4, 0, 1 | DECOMP_INLINE, 0x5DB2},
+ {0x2F9F5, 0, 1 | DECOMP_INLINE, 0x9723},
+ {0x2F9F6, 0, 1, 5087},
+ {0x2F9F7, 0, 1, 5088},
+ {0x2F9F8, 0, 1 | DECOMP_INLINE, 0x4A6E},
+ {0x2F9F9, 0, 1 | DECOMP_INLINE, 0x4A76},
+ {0x2F9FA, 0, 1 | DECOMP_INLINE, 0x97E0},
+ {0x2F9FB, 0, 1, 5089},
+ {0x2F9FC, 0, 1 | DECOMP_INLINE, 0x4AB2},
+ {0x2F9FD, 0, 1, 5090},
+ {0x2F9FE, 0, 1 | DECOMP_INLINE, 0x980B},
+ {0x2F9FF, 0, 1 | DECOMP_INLINE, 0x980B},
+ {0x2FA00, 0, 1 | DECOMP_INLINE, 0x9829},
+ {0x2FA01, 0, 1, 5091},
+ {0x2FA02, 0, 1 | DECOMP_INLINE, 0x98E2},
+ {0x2FA03, 0, 1 | DECOMP_INLINE, 0x4B33},
+ {0x2FA04, 0, 1 | DECOMP_INLINE, 0x9929},
+ {0x2FA05, 0, 1 | DECOMP_INLINE, 0x99A7},
+ {0x2FA06, 0, 1 | DECOMP_INLINE, 0x99C2},
+ {0x2FA07, 0, 1 | DECOMP_INLINE, 0x99FE},
+ {0x2FA08, 0, 1 | DECOMP_INLINE, 0x4BCE},
+ {0x2FA09, 0, 1, 5092},
+ {0x2FA0A, 0, 1 | DECOMP_INLINE, 0x9B12},
+ {0x2FA0B, 0, 1 | DECOMP_INLINE, 0x9C40},
+ {0x2FA0C, 0, 1 | DECOMP_INLINE, 0x9CFD},
+ {0x2FA0D, 0, 1 | DECOMP_INLINE, 0x4CCE},
+ {0x2FA0E, 0, 1 | DECOMP_INLINE, 0x4CED},
+ {0x2FA0F, 0, 1 | DECOMP_INLINE, 0x9D67},
+ {0x2FA10, 0, 1, 5093},
+ {0x2FA11, 0, 1 | DECOMP_INLINE, 0x4CF8},
+ {0x2FA12, 0, 1, 5094},
+ {0x2FA13, 0, 1, 5095},
+ {0x2FA14, 0, 1, 5096},
+ {0x2FA15, 0, 1 | DECOMP_INLINE, 0x9EBB},
+ {0x2FA16, 0, 1 | DECOMP_INLINE, 0x4D56},
+ {0x2FA17, 0, 1 | DECOMP_INLINE, 0x9EF9},
+ {0x2FA18, 0, 1 | DECOMP_INLINE, 0x9EFE},
+ {0x2FA19, 0, 1 | DECOMP_INLINE, 0x9F05},
+ {0x2FA1A, 0, 1 | DECOMP_INLINE, 0x9F0F},
+ {0x2FA1B, 0, 1 | DECOMP_INLINE, 0x9F16},
+ {0x2FA1C, 0, 1 | DECOMP_INLINE, 0x9F3B},
+ {0x2FA1D, 0, 1, 5097}
+
+};
+
+/* codepoints array */
+static const uint32 UnicodeDecomp_codepoints[5098] =
+{
+ /* 0 */ 0x0020, 0x0308,
+ /* 2 */ 0x0020, 0x0304,
+ /* 4 */ 0x0020, 0x0301,
+ /* 6 */ 0x0020, 0x0327,
+ /* 8 */ 0x0031, 0x2044, 0x0034,
+ /* 11 */ 0x0031, 0x2044, 0x0032,
+ /* 14 */ 0x0033, 0x2044, 0x0034,
+ /* 17 */ 0x0041, 0x0300,
+ /* 19 */ 0x0041, 0x0301,
+ /* 21 */ 0x0041, 0x0302,
+ /* 23 */ 0x0041, 0x0303,
+ /* 25 */ 0x0041, 0x0308,
+ /* 27 */ 0x0041, 0x030A,
+ /* 29 */ 0x0043, 0x0327,
+ /* 31 */ 0x0045, 0x0300,
+ /* 33 */ 0x0045, 0x0301,
+ /* 35 */ 0x0045, 0x0302,
+ /* 37 */ 0x0045, 0x0308,
+ /* 39 */ 0x0049, 0x0300,
+ /* 41 */ 0x0049, 0x0301,
+ /* 43 */ 0x0049, 0x0302,
+ /* 45 */ 0x0049, 0x0308,
+ /* 47 */ 0x004E, 0x0303,
+ /* 49 */ 0x004F, 0x0300,
+ /* 51 */ 0x004F, 0x0301,
+ /* 53 */ 0x004F, 0x0302,
+ /* 55 */ 0x004F, 0x0303,
+ /* 57 */ 0x004F, 0x0308,
+ /* 59 */ 0x0055, 0x0300,
+ /* 61 */ 0x0055, 0x0301,
+ /* 63 */ 0x0055, 0x0302,
+ /* 65 */ 0x0055, 0x0308,
+ /* 67 */ 0x0059, 0x0301,
+ /* 69 */ 0x0061, 0x0300,
+ /* 71 */ 0x0061, 0x0301,
+ /* 73 */ 0x0061, 0x0302,
+ /* 75 */ 0x0061, 0x0303,
+ /* 77 */ 0x0061, 0x0308,
+ /* 79 */ 0x0061, 0x030A,
+ /* 81 */ 0x0063, 0x0327,
+ /* 83 */ 0x0065, 0x0300,
+ /* 85 */ 0x0065, 0x0301,
+ /* 87 */ 0x0065, 0x0302,
+ /* 89 */ 0x0065, 0x0308,
+ /* 91 */ 0x0069, 0x0300,
+ /* 93 */ 0x0069, 0x0301,
+ /* 95 */ 0x0069, 0x0302,
+ /* 97 */ 0x0069, 0x0308,
+ /* 99 */ 0x006E, 0x0303,
+ /* 101 */ 0x006F, 0x0300,
+ /* 103 */ 0x006F, 0x0301,
+ /* 105 */ 0x006F, 0x0302,
+ /* 107 */ 0x006F, 0x0303,
+ /* 109 */ 0x006F, 0x0308,
+ /* 111 */ 0x0075, 0x0300,
+ /* 113 */ 0x0075, 0x0301,
+ /* 115 */ 0x0075, 0x0302,
+ /* 117 */ 0x0075, 0x0308,
+ /* 119 */ 0x0079, 0x0301,
+ /* 121 */ 0x0079, 0x0308,
+ /* 123 */ 0x0041, 0x0304,
+ /* 125 */ 0x0061, 0x0304,
+ /* 127 */ 0x0041, 0x0306,
+ /* 129 */ 0x0061, 0x0306,
+ /* 131 */ 0x0041, 0x0328,
+ /* 133 */ 0x0061, 0x0328,
+ /* 135 */ 0x0043, 0x0301,
+ /* 137 */ 0x0063, 0x0301,
+ /* 139 */ 0x0043, 0x0302,
+ /* 141 */ 0x0063, 0x0302,
+ /* 143 */ 0x0043, 0x0307,
+ /* 145 */ 0x0063, 0x0307,
+ /* 147 */ 0x0043, 0x030C,
+ /* 149 */ 0x0063, 0x030C,
+ /* 151 */ 0x0044, 0x030C,
+ /* 153 */ 0x0064, 0x030C,
+ /* 155 */ 0x0045, 0x0304,
+ /* 157 */ 0x0065, 0x0304,
+ /* 159 */ 0x0045, 0x0306,
+ /* 161 */ 0x0065, 0x0306,
+ /* 163 */ 0x0045, 0x0307,
+ /* 165 */ 0x0065, 0x0307,
+ /* 167 */ 0x0045, 0x0328,
+ /* 169 */ 0x0065, 0x0328,
+ /* 171 */ 0x0045, 0x030C,
+ /* 173 */ 0x0065, 0x030C,
+ /* 175 */ 0x0047, 0x0302,
+ /* 177 */ 0x0067, 0x0302,
+ /* 179 */ 0x0047, 0x0306,
+ /* 181 */ 0x0067, 0x0306,
+ /* 183 */ 0x0047, 0x0307,
+ /* 185 */ 0x0067, 0x0307,
+ /* 187 */ 0x0047, 0x0327,
+ /* 189 */ 0x0067, 0x0327,
+ /* 191 */ 0x0048, 0x0302,
+ /* 193 */ 0x0068, 0x0302,
+ /* 195 */ 0x0049, 0x0303,
+ /* 197 */ 0x0069, 0x0303,
+ /* 199 */ 0x0049, 0x0304,
+ /* 201 */ 0x0069, 0x0304,
+ /* 203 */ 0x0049, 0x0306,
+ /* 205 */ 0x0069, 0x0306,
+ /* 207 */ 0x0049, 0x0328,
+ /* 209 */ 0x0069, 0x0328,
+ /* 211 */ 0x0049, 0x0307,
+ /* 213 */ 0x0049, 0x004A,
+ /* 215 */ 0x0069, 0x006A,
+ /* 217 */ 0x004A, 0x0302,
+ /* 219 */ 0x006A, 0x0302,
+ /* 221 */ 0x004B, 0x0327,
+ /* 223 */ 0x006B, 0x0327,
+ /* 225 */ 0x004C, 0x0301,
+ /* 227 */ 0x006C, 0x0301,
+ /* 229 */ 0x004C, 0x0327,
+ /* 231 */ 0x006C, 0x0327,
+ /* 233 */ 0x004C, 0x030C,
+ /* 235 */ 0x006C, 0x030C,
+ /* 237 */ 0x004C, 0x00B7,
+ /* 239 */ 0x006C, 0x00B7,
+ /* 241 */ 0x004E, 0x0301,
+ /* 243 */ 0x006E, 0x0301,
+ /* 245 */ 0x004E, 0x0327,
+ /* 247 */ 0x006E, 0x0327,
+ /* 249 */ 0x004E, 0x030C,
+ /* 251 */ 0x006E, 0x030C,
+ /* 253 */ 0x02BC, 0x006E,
+ /* 255 */ 0x004F, 0x0304,
+ /* 257 */ 0x006F, 0x0304,
+ /* 259 */ 0x004F, 0x0306,
+ /* 261 */ 0x006F, 0x0306,
+ /* 263 */ 0x004F, 0x030B,
+ /* 265 */ 0x006F, 0x030B,
+ /* 267 */ 0x0052, 0x0301,
+ /* 269 */ 0x0072, 0x0301,
+ /* 271 */ 0x0052, 0x0327,
+ /* 273 */ 0x0072, 0x0327,
+ /* 275 */ 0x0052, 0x030C,
+ /* 277 */ 0x0072, 0x030C,
+ /* 279 */ 0x0053, 0x0301,
+ /* 281 */ 0x0073, 0x0301,
+ /* 283 */ 0x0053, 0x0302,
+ /* 285 */ 0x0073, 0x0302,
+ /* 287 */ 0x0053, 0x0327,
+ /* 289 */ 0x0073, 0x0327,
+ /* 291 */ 0x0053, 0x030C,
+ /* 293 */ 0x0073, 0x030C,
+ /* 295 */ 0x0054, 0x0327,
+ /* 297 */ 0x0074, 0x0327,
+ /* 299 */ 0x0054, 0x030C,
+ /* 301 */ 0x0074, 0x030C,
+ /* 303 */ 0x0055, 0x0303,
+ /* 305 */ 0x0075, 0x0303,
+ /* 307 */ 0x0055, 0x0304,
+ /* 309 */ 0x0075, 0x0304,
+ /* 311 */ 0x0055, 0x0306,
+ /* 313 */ 0x0075, 0x0306,
+ /* 315 */ 0x0055, 0x030A,
+ /* 317 */ 0x0075, 0x030A,
+ /* 319 */ 0x0055, 0x030B,
+ /* 321 */ 0x0075, 0x030B,
+ /* 323 */ 0x0055, 0x0328,
+ /* 325 */ 0x0075, 0x0328,
+ /* 327 */ 0x0057, 0x0302,
+ /* 329 */ 0x0077, 0x0302,
+ /* 331 */ 0x0059, 0x0302,
+ /* 333 */ 0x0079, 0x0302,
+ /* 335 */ 0x0059, 0x0308,
+ /* 337 */ 0x005A, 0x0301,
+ /* 339 */ 0x007A, 0x0301,
+ /* 341 */ 0x005A, 0x0307,
+ /* 343 */ 0x007A, 0x0307,
+ /* 345 */ 0x005A, 0x030C,
+ /* 347 */ 0x007A, 0x030C,
+ /* 349 */ 0x004F, 0x031B,
+ /* 351 */ 0x006F, 0x031B,
+ /* 353 */ 0x0055, 0x031B,
+ /* 355 */ 0x0075, 0x031B,
+ /* 357 */ 0x0044, 0x017D,
+ /* 359 */ 0x0044, 0x017E,
+ /* 361 */ 0x0064, 0x017E,
+ /* 363 */ 0x004C, 0x004A,
+ /* 365 */ 0x004C, 0x006A,
+ /* 367 */ 0x006C, 0x006A,
+ /* 369 */ 0x004E, 0x004A,
+ /* 371 */ 0x004E, 0x006A,
+ /* 373 */ 0x006E, 0x006A,
+ /* 375 */ 0x0041, 0x030C,
+ /* 377 */ 0x0061, 0x030C,
+ /* 379 */ 0x0049, 0x030C,
+ /* 381 */ 0x0069, 0x030C,
+ /* 383 */ 0x004F, 0x030C,
+ /* 385 */ 0x006F, 0x030C,
+ /* 387 */ 0x0055, 0x030C,
+ /* 389 */ 0x0075, 0x030C,
+ /* 391 */ 0x00DC, 0x0304,
+ /* 393 */ 0x00FC, 0x0304,
+ /* 395 */ 0x00DC, 0x0301,
+ /* 397 */ 0x00FC, 0x0301,
+ /* 399 */ 0x00DC, 0x030C,
+ /* 401 */ 0x00FC, 0x030C,
+ /* 403 */ 0x00DC, 0x0300,
+ /* 405 */ 0x00FC, 0x0300,
+ /* 407 */ 0x00C4, 0x0304,
+ /* 409 */ 0x00E4, 0x0304,
+ /* 411 */ 0x0226, 0x0304,
+ /* 413 */ 0x0227, 0x0304,
+ /* 415 */ 0x00C6, 0x0304,
+ /* 417 */ 0x00E6, 0x0304,
+ /* 419 */ 0x0047, 0x030C,
+ /* 421 */ 0x0067, 0x030C,
+ /* 423 */ 0x004B, 0x030C,
+ /* 425 */ 0x006B, 0x030C,
+ /* 427 */ 0x004F, 0x0328,
+ /* 429 */ 0x006F, 0x0328,
+ /* 431 */ 0x01EA, 0x0304,
+ /* 433 */ 0x01EB, 0x0304,
+ /* 435 */ 0x01B7, 0x030C,
+ /* 437 */ 0x0292, 0x030C,
+ /* 439 */ 0x006A, 0x030C,
+ /* 441 */ 0x0044, 0x005A,
+ /* 443 */ 0x0044, 0x007A,
+ /* 445 */ 0x0064, 0x007A,
+ /* 447 */ 0x0047, 0x0301,
+ /* 449 */ 0x0067, 0x0301,
+ /* 451 */ 0x004E, 0x0300,
+ /* 453 */ 0x006E, 0x0300,
+ /* 455 */ 0x00C5, 0x0301,
+ /* 457 */ 0x00E5, 0x0301,
+ /* 459 */ 0x00C6, 0x0301,
+ /* 461 */ 0x00E6, 0x0301,
+ /* 463 */ 0x00D8, 0x0301,
+ /* 465 */ 0x00F8, 0x0301,
+ /* 467 */ 0x0041, 0x030F,
+ /* 469 */ 0x0061, 0x030F,
+ /* 471 */ 0x0041, 0x0311,
+ /* 473 */ 0x0061, 0x0311,
+ /* 475 */ 0x0045, 0x030F,
+ /* 477 */ 0x0065, 0x030F,
+ /* 479 */ 0x0045, 0x0311,
+ /* 481 */ 0x0065, 0x0311,
+ /* 483 */ 0x0049, 0x030F,
+ /* 485 */ 0x0069, 0x030F,
+ /* 487 */ 0x0049, 0x0311,
+ /* 489 */ 0x0069, 0x0311,
+ /* 491 */ 0x004F, 0x030F,
+ /* 493 */ 0x006F, 0x030F,
+ /* 495 */ 0x004F, 0x0311,
+ /* 497 */ 0x006F, 0x0311,
+ /* 499 */ 0x0052, 0x030F,
+ /* 501 */ 0x0072, 0x030F,
+ /* 503 */ 0x0052, 0x0311,
+ /* 505 */ 0x0072, 0x0311,
+ /* 507 */ 0x0055, 0x030F,
+ /* 509 */ 0x0075, 0x030F,
+ /* 511 */ 0x0055, 0x0311,
+ /* 513 */ 0x0075, 0x0311,
+ /* 515 */ 0x0053, 0x0326,
+ /* 517 */ 0x0073, 0x0326,
+ /* 519 */ 0x0054, 0x0326,
+ /* 521 */ 0x0074, 0x0326,
+ /* 523 */ 0x0048, 0x030C,
+ /* 525 */ 0x0068, 0x030C,
+ /* 527 */ 0x0041, 0x0307,
+ /* 529 */ 0x0061, 0x0307,
+ /* 531 */ 0x0045, 0x0327,
+ /* 533 */ 0x0065, 0x0327,
+ /* 535 */ 0x00D6, 0x0304,
+ /* 537 */ 0x00F6, 0x0304,
+ /* 539 */ 0x00D5, 0x0304,
+ /* 541 */ 0x00F5, 0x0304,
+ /* 543 */ 0x004F, 0x0307,
+ /* 545 */ 0x006F, 0x0307,
+ /* 547 */ 0x022E, 0x0304,
+ /* 549 */ 0x022F, 0x0304,
+ /* 551 */ 0x0059, 0x0304,
+ /* 553 */ 0x0079, 0x0304,
+ /* 555 */ 0x0020, 0x0306,
+ /* 557 */ 0x0020, 0x0307,
+ /* 559 */ 0x0020, 0x030A,
+ /* 561 */ 0x0020, 0x0328,
+ /* 563 */ 0x0020, 0x0303,
+ /* 565 */ 0x0020, 0x030B,
+ /* 567 */ 0x0308, 0x0301,
+ /* 569 */ 0x0020, 0x0345,
+ /* 571 */ 0x0020, 0x0301,
+ /* 573 */ 0x00A8, 0x0301,
+ /* 575 */ 0x0391, 0x0301,
+ /* 577 */ 0x0395, 0x0301,
+ /* 579 */ 0x0397, 0x0301,
+ /* 581 */ 0x0399, 0x0301,
+ /* 583 */ 0x039F, 0x0301,
+ /* 585 */ 0x03A5, 0x0301,
+ /* 587 */ 0x03A9, 0x0301,
+ /* 589 */ 0x03CA, 0x0301,
+ /* 591 */ 0x0399, 0x0308,
+ /* 593 */ 0x03A5, 0x0308,
+ /* 595 */ 0x03B1, 0x0301,
+ /* 597 */ 0x03B5, 0x0301,
+ /* 599 */ 0x03B7, 0x0301,
+ /* 601 */ 0x03B9, 0x0301,
+ /* 603 */ 0x03CB, 0x0301,
+ /* 605 */ 0x03B9, 0x0308,
+ /* 607 */ 0x03C5, 0x0308,
+ /* 609 */ 0x03BF, 0x0301,
+ /* 611 */ 0x03C5, 0x0301,
+ /* 613 */ 0x03C9, 0x0301,
+ /* 615 */ 0x03D2, 0x0301,
+ /* 617 */ 0x03D2, 0x0308,
+ /* 619 */ 0x0415, 0x0300,
+ /* 621 */ 0x0415, 0x0308,
+ /* 623 */ 0x0413, 0x0301,
+ /* 625 */ 0x0406, 0x0308,
+ /* 627 */ 0x041A, 0x0301,
+ /* 629 */ 0x0418, 0x0300,
+ /* 631 */ 0x0423, 0x0306,
+ /* 633 */ 0x0418, 0x0306,
+ /* 635 */ 0x0438, 0x0306,
+ /* 637 */ 0x0435, 0x0300,
+ /* 639 */ 0x0435, 0x0308,
+ /* 641 */ 0x0433, 0x0301,
+ /* 643 */ 0x0456, 0x0308,
+ /* 645 */ 0x043A, 0x0301,
+ /* 647 */ 0x0438, 0x0300,
+ /* 649 */ 0x0443, 0x0306,
+ /* 651 */ 0x0474, 0x030F,
+ /* 653 */ 0x0475, 0x030F,
+ /* 655 */ 0x0416, 0x0306,
+ /* 657 */ 0x0436, 0x0306,
+ /* 659 */ 0x0410, 0x0306,
+ /* 661 */ 0x0430, 0x0306,
+ /* 663 */ 0x0410, 0x0308,
+ /* 665 */ 0x0430, 0x0308,
+ /* 667 */ 0x0415, 0x0306,
+ /* 669 */ 0x0435, 0x0306,
+ /* 671 */ 0x04D8, 0x0308,
+ /* 673 */ 0x04D9, 0x0308,
+ /* 675 */ 0x0416, 0x0308,
+ /* 677 */ 0x0436, 0x0308,
+ /* 679 */ 0x0417, 0x0308,
+ /* 681 */ 0x0437, 0x0308,
+ /* 683 */ 0x0418, 0x0304,
+ /* 685 */ 0x0438, 0x0304,
+ /* 687 */ 0x0418, 0x0308,
+ /* 689 */ 0x0438, 0x0308,
+ /* 691 */ 0x041E, 0x0308,
+ /* 693 */ 0x043E, 0x0308,
+ /* 695 */ 0x04E8, 0x0308,
+ /* 697 */ 0x04E9, 0x0308,
+ /* 699 */ 0x042D, 0x0308,
+ /* 701 */ 0x044D, 0x0308,
+ /* 703 */ 0x0423, 0x0304,
+ /* 705 */ 0x0443, 0x0304,
+ /* 707 */ 0x0423, 0x0308,
+ /* 709 */ 0x0443, 0x0308,
+ /* 711 */ 0x0423, 0x030B,
+ /* 713 */ 0x0443, 0x030B,
+ /* 715 */ 0x0427, 0x0308,
+ /* 717 */ 0x0447, 0x0308,
+ /* 719 */ 0x042B, 0x0308,
+ /* 721 */ 0x044B, 0x0308,
+ /* 723 */ 0x0565, 0x0582,
+ /* 725 */ 0x0627, 0x0653,
+ /* 727 */ 0x0627, 0x0654,
+ /* 729 */ 0x0648, 0x0654,
+ /* 731 */ 0x0627, 0x0655,
+ /* 733 */ 0x064A, 0x0654,
+ /* 735 */ 0x0627, 0x0674,
+ /* 737 */ 0x0648, 0x0674,
+ /* 739 */ 0x06C7, 0x0674,
+ /* 741 */ 0x064A, 0x0674,
+ /* 743 */ 0x06D5, 0x0654,
+ /* 745 */ 0x06C1, 0x0654,
+ /* 747 */ 0x06D2, 0x0654,
+ /* 749 */ 0x0928, 0x093C,
+ /* 751 */ 0x0930, 0x093C,
+ /* 753 */ 0x0933, 0x093C,
+ /* 755 */ 0x0915, 0x093C,
+ /* 757 */ 0x0916, 0x093C,
+ /* 759 */ 0x0917, 0x093C,
+ /* 761 */ 0x091C, 0x093C,
+ /* 763 */ 0x0921, 0x093C,
+ /* 765 */ 0x0922, 0x093C,
+ /* 767 */ 0x092B, 0x093C,
+ /* 769 */ 0x092F, 0x093C,
+ /* 771 */ 0x09C7, 0x09BE,
+ /* 773 */ 0x09C7, 0x09D7,
+ /* 775 */ 0x09A1, 0x09BC,
+ /* 777 */ 0x09A2, 0x09BC,
+ /* 779 */ 0x09AF, 0x09BC,
+ /* 781 */ 0x0A32, 0x0A3C,
+ /* 783 */ 0x0A38, 0x0A3C,
+ /* 785 */ 0x0A16, 0x0A3C,
+ /* 787 */ 0x0A17, 0x0A3C,
+ /* 789 */ 0x0A1C, 0x0A3C,
+ /* 791 */ 0x0A2B, 0x0A3C,
+ /* 793 */ 0x0B47, 0x0B56,
+ /* 795 */ 0x0B47, 0x0B3E,
+ /* 797 */ 0x0B47, 0x0B57,
+ /* 799 */ 0x0B21, 0x0B3C,
+ /* 801 */ 0x0B22, 0x0B3C,
+ /* 803 */ 0x0B92, 0x0BD7,
+ /* 805 */ 0x0BC6, 0x0BBE,
+ /* 807 */ 0x0BC7, 0x0BBE,
+ /* 809 */ 0x0BC6, 0x0BD7,
+ /* 811 */ 0x0C46, 0x0C56,
+ /* 813 */ 0x0CBF, 0x0CD5,
+ /* 815 */ 0x0CC6, 0x0CD5,
+ /* 817 */ 0x0CC6, 0x0CD6,
+ /* 819 */ 0x0CC6, 0x0CC2,
+ /* 821 */ 0x0CCA, 0x0CD5,
+ /* 823 */ 0x0D46, 0x0D3E,
+ /* 825 */ 0x0D47, 0x0D3E,
+ /* 827 */ 0x0D46, 0x0D57,
+ /* 829 */ 0x0DD9, 0x0DCA,
+ /* 831 */ 0x0DD9, 0x0DCF,
+ /* 833 */ 0x0DDC, 0x0DCA,
+ /* 835 */ 0x0DD9, 0x0DDF,
+ /* 837 */ 0x0E4D, 0x0E32,
+ /* 839 */ 0x0ECD, 0x0EB2,
+ /* 841 */ 0x0EAB, 0x0E99,
+ /* 843 */ 0x0EAB, 0x0EA1,
+ /* 845 */ 0x0F42, 0x0FB7,
+ /* 847 */ 0x0F4C, 0x0FB7,
+ /* 849 */ 0x0F51, 0x0FB7,
+ /* 851 */ 0x0F56, 0x0FB7,
+ /* 853 */ 0x0F5B, 0x0FB7,
+ /* 855 */ 0x0F40, 0x0FB5,
+ /* 857 */ 0x0F71, 0x0F72,
+ /* 859 */ 0x0F71, 0x0F74,
+ /* 861 */ 0x0FB2, 0x0F80,
+ /* 863 */ 0x0FB2, 0x0F81,
+ /* 865 */ 0x0FB3, 0x0F80,
+ /* 867 */ 0x0FB3, 0x0F81,
+ /* 869 */ 0x0F71, 0x0F80,
+ /* 871 */ 0x0F92, 0x0FB7,
+ /* 873 */ 0x0F9C, 0x0FB7,
+ /* 875 */ 0x0FA1, 0x0FB7,
+ /* 877 */ 0x0FA6, 0x0FB7,
+ /* 879 */ 0x0FAB, 0x0FB7,
+ /* 881 */ 0x0F90, 0x0FB5,
+ /* 883 */ 0x1025, 0x102E,
+ /* 885 */ 0x1B05, 0x1B35,
+ /* 887 */ 0x1B07, 0x1B35,
+ /* 889 */ 0x1B09, 0x1B35,
+ /* 891 */ 0x1B0B, 0x1B35,
+ /* 893 */ 0x1B0D, 0x1B35,
+ /* 895 */ 0x1B11, 0x1B35,
+ /* 897 */ 0x1B3A, 0x1B35,
+ /* 899 */ 0x1B3C, 0x1B35,
+ /* 901 */ 0x1B3E, 0x1B35,
+ /* 903 */ 0x1B3F, 0x1B35,
+ /* 905 */ 0x1B42, 0x1B35,
+ /* 907 */ 0x0041, 0x0325,
+ /* 909 */ 0x0061, 0x0325,
+ /* 911 */ 0x0042, 0x0307,
+ /* 913 */ 0x0062, 0x0307,
+ /* 915 */ 0x0042, 0x0323,
+ /* 917 */ 0x0062, 0x0323,
+ /* 919 */ 0x0042, 0x0331,
+ /* 921 */ 0x0062, 0x0331,
+ /* 923 */ 0x00C7, 0x0301,
+ /* 925 */ 0x00E7, 0x0301,
+ /* 927 */ 0x0044, 0x0307,
+ /* 929 */ 0x0064, 0x0307,
+ /* 931 */ 0x0044, 0x0323,
+ /* 933 */ 0x0064, 0x0323,
+ /* 935 */ 0x0044, 0x0331,
+ /* 937 */ 0x0064, 0x0331,
+ /* 939 */ 0x0044, 0x0327,
+ /* 941 */ 0x0064, 0x0327,
+ /* 943 */ 0x0044, 0x032D,
+ /* 945 */ 0x0064, 0x032D,
+ /* 947 */ 0x0112, 0x0300,
+ /* 949 */ 0x0113, 0x0300,
+ /* 951 */ 0x0112, 0x0301,
+ /* 953 */ 0x0113, 0x0301,
+ /* 955 */ 0x0045, 0x032D,
+ /* 957 */ 0x0065, 0x032D,
+ /* 959 */ 0x0045, 0x0330,
+ /* 961 */ 0x0065, 0x0330,
+ /* 963 */ 0x0228, 0x0306,
+ /* 965 */ 0x0229, 0x0306,
+ /* 967 */ 0x0046, 0x0307,
+ /* 969 */ 0x0066, 0x0307,
+ /* 971 */ 0x0047, 0x0304,
+ /* 973 */ 0x0067, 0x0304,
+ /* 975 */ 0x0048, 0x0307,
+ /* 977 */ 0x0068, 0x0307,
+ /* 979 */ 0x0048, 0x0323,
+ /* 981 */ 0x0068, 0x0323,
+ /* 983 */ 0x0048, 0x0308,
+ /* 985 */ 0x0068, 0x0308,
+ /* 987 */ 0x0048, 0x0327,
+ /* 989 */ 0x0068, 0x0327,
+ /* 991 */ 0x0048, 0x032E,
+ /* 993 */ 0x0068, 0x032E,
+ /* 995 */ 0x0049, 0x0330,
+ /* 997 */ 0x0069, 0x0330,
+ /* 999 */ 0x00CF, 0x0301,
+ /* 1001 */ 0x00EF, 0x0301,
+ /* 1003 */ 0x004B, 0x0301,
+ /* 1005 */ 0x006B, 0x0301,
+ /* 1007 */ 0x004B, 0x0323,
+ /* 1009 */ 0x006B, 0x0323,
+ /* 1011 */ 0x004B, 0x0331,
+ /* 1013 */ 0x006B, 0x0331,
+ /* 1015 */ 0x004C, 0x0323,
+ /* 1017 */ 0x006C, 0x0323,
+ /* 1019 */ 0x1E36, 0x0304,
+ /* 1021 */ 0x1E37, 0x0304,
+ /* 1023 */ 0x004C, 0x0331,
+ /* 1025 */ 0x006C, 0x0331,
+ /* 1027 */ 0x004C, 0x032D,
+ /* 1029 */ 0x006C, 0x032D,
+ /* 1031 */ 0x004D, 0x0301,
+ /* 1033 */ 0x006D, 0x0301,
+ /* 1035 */ 0x004D, 0x0307,
+ /* 1037 */ 0x006D, 0x0307,
+ /* 1039 */ 0x004D, 0x0323,
+ /* 1041 */ 0x006D, 0x0323,
+ /* 1043 */ 0x004E, 0x0307,
+ /* 1045 */ 0x006E, 0x0307,
+ /* 1047 */ 0x004E, 0x0323,
+ /* 1049 */ 0x006E, 0x0323,
+ /* 1051 */ 0x004E, 0x0331,
+ /* 1053 */ 0x006E, 0x0331,
+ /* 1055 */ 0x004E, 0x032D,
+ /* 1057 */ 0x006E, 0x032D,
+ /* 1059 */ 0x00D5, 0x0301,
+ /* 1061 */ 0x00F5, 0x0301,
+ /* 1063 */ 0x00D5, 0x0308,
+ /* 1065 */ 0x00F5, 0x0308,
+ /* 1067 */ 0x014C, 0x0300,
+ /* 1069 */ 0x014D, 0x0300,
+ /* 1071 */ 0x014C, 0x0301,
+ /* 1073 */ 0x014D, 0x0301,
+ /* 1075 */ 0x0050, 0x0301,
+ /* 1077 */ 0x0070, 0x0301,
+ /* 1079 */ 0x0050, 0x0307,
+ /* 1081 */ 0x0070, 0x0307,
+ /* 1083 */ 0x0052, 0x0307,
+ /* 1085 */ 0x0072, 0x0307,
+ /* 1087 */ 0x0052, 0x0323,
+ /* 1089 */ 0x0072, 0x0323,
+ /* 1091 */ 0x1E5A, 0x0304,
+ /* 1093 */ 0x1E5B, 0x0304,
+ /* 1095 */ 0x0052, 0x0331,
+ /* 1097 */ 0x0072, 0x0331,
+ /* 1099 */ 0x0053, 0x0307,
+ /* 1101 */ 0x0073, 0x0307,
+ /* 1103 */ 0x0053, 0x0323,
+ /* 1105 */ 0x0073, 0x0323,
+ /* 1107 */ 0x015A, 0x0307,
+ /* 1109 */ 0x015B, 0x0307,
+ /* 1111 */ 0x0160, 0x0307,
+ /* 1113 */ 0x0161, 0x0307,
+ /* 1115 */ 0x1E62, 0x0307,
+ /* 1117 */ 0x1E63, 0x0307,
+ /* 1119 */ 0x0054, 0x0307,
+ /* 1121 */ 0x0074, 0x0307,
+ /* 1123 */ 0x0054, 0x0323,
+ /* 1125 */ 0x0074, 0x0323,
+ /* 1127 */ 0x0054, 0x0331,
+ /* 1129 */ 0x0074, 0x0331,
+ /* 1131 */ 0x0054, 0x032D,
+ /* 1133 */ 0x0074, 0x032D,
+ /* 1135 */ 0x0055, 0x0324,
+ /* 1137 */ 0x0075, 0x0324,
+ /* 1139 */ 0x0055, 0x0330,
+ /* 1141 */ 0x0075, 0x0330,
+ /* 1143 */ 0x0055, 0x032D,
+ /* 1145 */ 0x0075, 0x032D,
+ /* 1147 */ 0x0168, 0x0301,
+ /* 1149 */ 0x0169, 0x0301,
+ /* 1151 */ 0x016A, 0x0308,
+ /* 1153 */ 0x016B, 0x0308,
+ /* 1155 */ 0x0056, 0x0303,
+ /* 1157 */ 0x0076, 0x0303,
+ /* 1159 */ 0x0056, 0x0323,
+ /* 1161 */ 0x0076, 0x0323,
+ /* 1163 */ 0x0057, 0x0300,
+ /* 1165 */ 0x0077, 0x0300,
+ /* 1167 */ 0x0057, 0x0301,
+ /* 1169 */ 0x0077, 0x0301,
+ /* 1171 */ 0x0057, 0x0308,
+ /* 1173 */ 0x0077, 0x0308,
+ /* 1175 */ 0x0057, 0x0307,
+ /* 1177 */ 0x0077, 0x0307,
+ /* 1179 */ 0x0057, 0x0323,
+ /* 1181 */ 0x0077, 0x0323,
+ /* 1183 */ 0x0058, 0x0307,
+ /* 1185 */ 0x0078, 0x0307,
+ /* 1187 */ 0x0058, 0x0308,
+ /* 1189 */ 0x0078, 0x0308,
+ /* 1191 */ 0x0059, 0x0307,
+ /* 1193 */ 0x0079, 0x0307,
+ /* 1195 */ 0x005A, 0x0302,
+ /* 1197 */ 0x007A, 0x0302,
+ /* 1199 */ 0x005A, 0x0323,
+ /* 1201 */ 0x007A, 0x0323,
+ /* 1203 */ 0x005A, 0x0331,
+ /* 1205 */ 0x007A, 0x0331,
+ /* 1207 */ 0x0068, 0x0331,
+ /* 1209 */ 0x0074, 0x0308,
+ /* 1211 */ 0x0077, 0x030A,
+ /* 1213 */ 0x0079, 0x030A,
+ /* 1215 */ 0x0061, 0x02BE,
+ /* 1217 */ 0x017F, 0x0307,
+ /* 1219 */ 0x0041, 0x0323,
+ /* 1221 */ 0x0061, 0x0323,
+ /* 1223 */ 0x0041, 0x0309,
+ /* 1225 */ 0x0061, 0x0309,
+ /* 1227 */ 0x00C2, 0x0301,
+ /* 1229 */ 0x00E2, 0x0301,
+ /* 1231 */ 0x00C2, 0x0300,
+ /* 1233 */ 0x00E2, 0x0300,
+ /* 1235 */ 0x00C2, 0x0309,
+ /* 1237 */ 0x00E2, 0x0309,
+ /* 1239 */ 0x00C2, 0x0303,
+ /* 1241 */ 0x00E2, 0x0303,
+ /* 1243 */ 0x1EA0, 0x0302,
+ /* 1245 */ 0x1EA1, 0x0302,
+ /* 1247 */ 0x0102, 0x0301,
+ /* 1249 */ 0x0103, 0x0301,
+ /* 1251 */ 0x0102, 0x0300,
+ /* 1253 */ 0x0103, 0x0300,
+ /* 1255 */ 0x0102, 0x0309,
+ /* 1257 */ 0x0103, 0x0309,
+ /* 1259 */ 0x0102, 0x0303,
+ /* 1261 */ 0x0103, 0x0303,
+ /* 1263 */ 0x1EA0, 0x0306,
+ /* 1265 */ 0x1EA1, 0x0306,
+ /* 1267 */ 0x0045, 0x0323,
+ /* 1269 */ 0x0065, 0x0323,
+ /* 1271 */ 0x0045, 0x0309,
+ /* 1273 */ 0x0065, 0x0309,
+ /* 1275 */ 0x0045, 0x0303,
+ /* 1277 */ 0x0065, 0x0303,
+ /* 1279 */ 0x00CA, 0x0301,
+ /* 1281 */ 0x00EA, 0x0301,
+ /* 1283 */ 0x00CA, 0x0300,
+ /* 1285 */ 0x00EA, 0x0300,
+ /* 1287 */ 0x00CA, 0x0309,
+ /* 1289 */ 0x00EA, 0x0309,
+ /* 1291 */ 0x00CA, 0x0303,
+ /* 1293 */ 0x00EA, 0x0303,
+ /* 1295 */ 0x1EB8, 0x0302,
+ /* 1297 */ 0x1EB9, 0x0302,
+ /* 1299 */ 0x0049, 0x0309,
+ /* 1301 */ 0x0069, 0x0309,
+ /* 1303 */ 0x0049, 0x0323,
+ /* 1305 */ 0x0069, 0x0323,
+ /* 1307 */ 0x004F, 0x0323,
+ /* 1309 */ 0x006F, 0x0323,
+ /* 1311 */ 0x004F, 0x0309,
+ /* 1313 */ 0x006F, 0x0309,
+ /* 1315 */ 0x00D4, 0x0301,
+ /* 1317 */ 0x00F4, 0x0301,
+ /* 1319 */ 0x00D4, 0x0300,
+ /* 1321 */ 0x00F4, 0x0300,
+ /* 1323 */ 0x00D4, 0x0309,
+ /* 1325 */ 0x00F4, 0x0309,
+ /* 1327 */ 0x00D4, 0x0303,
+ /* 1329 */ 0x00F4, 0x0303,
+ /* 1331 */ 0x1ECC, 0x0302,
+ /* 1333 */ 0x1ECD, 0x0302,
+ /* 1335 */ 0x01A0, 0x0301,
+ /* 1337 */ 0x01A1, 0x0301,
+ /* 1339 */ 0x01A0, 0x0300,
+ /* 1341 */ 0x01A1, 0x0300,
+ /* 1343 */ 0x01A0, 0x0309,
+ /* 1345 */ 0x01A1, 0x0309,
+ /* 1347 */ 0x01A0, 0x0303,
+ /* 1349 */ 0x01A1, 0x0303,
+ /* 1351 */ 0x01A0, 0x0323,
+ /* 1353 */ 0x01A1, 0x0323,
+ /* 1355 */ 0x0055, 0x0323,
+ /* 1357 */ 0x0075, 0x0323,
+ /* 1359 */ 0x0055, 0x0309,
+ /* 1361 */ 0x0075, 0x0309,
+ /* 1363 */ 0x01AF, 0x0301,
+ /* 1365 */ 0x01B0, 0x0301,
+ /* 1367 */ 0x01AF, 0x0300,
+ /* 1369 */ 0x01B0, 0x0300,
+ /* 1371 */ 0x01AF, 0x0309,
+ /* 1373 */ 0x01B0, 0x0309,
+ /* 1375 */ 0x01AF, 0x0303,
+ /* 1377 */ 0x01B0, 0x0303,
+ /* 1379 */ 0x01AF, 0x0323,
+ /* 1381 */ 0x01B0, 0x0323,
+ /* 1383 */ 0x0059, 0x0300,
+ /* 1385 */ 0x0079, 0x0300,
+ /* 1387 */ 0x0059, 0x0323,
+ /* 1389 */ 0x0079, 0x0323,
+ /* 1391 */ 0x0059, 0x0309,
+ /* 1393 */ 0x0079, 0x0309,
+ /* 1395 */ 0x0059, 0x0303,
+ /* 1397 */ 0x0079, 0x0303,
+ /* 1399 */ 0x03B1, 0x0313,
+ /* 1401 */ 0x03B1, 0x0314,
+ /* 1403 */ 0x1F00, 0x0300,
+ /* 1405 */ 0x1F01, 0x0300,
+ /* 1407 */ 0x1F00, 0x0301,
+ /* 1409 */ 0x1F01, 0x0301,
+ /* 1411 */ 0x1F00, 0x0342,
+ /* 1413 */ 0x1F01, 0x0342,
+ /* 1415 */ 0x0391, 0x0313,
+ /* 1417 */ 0x0391, 0x0314,
+ /* 1419 */ 0x1F08, 0x0300,
+ /* 1421 */ 0x1F09, 0x0300,
+ /* 1423 */ 0x1F08, 0x0301,
+ /* 1425 */ 0x1F09, 0x0301,
+ /* 1427 */ 0x1F08, 0x0342,
+ /* 1429 */ 0x1F09, 0x0342,
+ /* 1431 */ 0x03B5, 0x0313,
+ /* 1433 */ 0x03B5, 0x0314,
+ /* 1435 */ 0x1F10, 0x0300,
+ /* 1437 */ 0x1F11, 0x0300,
+ /* 1439 */ 0x1F10, 0x0301,
+ /* 1441 */ 0x1F11, 0x0301,
+ /* 1443 */ 0x0395, 0x0313,
+ /* 1445 */ 0x0395, 0x0314,
+ /* 1447 */ 0x1F18, 0x0300,
+ /* 1449 */ 0x1F19, 0x0300,
+ /* 1451 */ 0x1F18, 0x0301,
+ /* 1453 */ 0x1F19, 0x0301,
+ /* 1455 */ 0x03B7, 0x0313,
+ /* 1457 */ 0x03B7, 0x0314,
+ /* 1459 */ 0x1F20, 0x0300,
+ /* 1461 */ 0x1F21, 0x0300,
+ /* 1463 */ 0x1F20, 0x0301,
+ /* 1465 */ 0x1F21, 0x0301,
+ /* 1467 */ 0x1F20, 0x0342,
+ /* 1469 */ 0x1F21, 0x0342,
+ /* 1471 */ 0x0397, 0x0313,
+ /* 1473 */ 0x0397, 0x0314,
+ /* 1475 */ 0x1F28, 0x0300,
+ /* 1477 */ 0x1F29, 0x0300,
+ /* 1479 */ 0x1F28, 0x0301,
+ /* 1481 */ 0x1F29, 0x0301,
+ /* 1483 */ 0x1F28, 0x0342,
+ /* 1485 */ 0x1F29, 0x0342,
+ /* 1487 */ 0x03B9, 0x0313,
+ /* 1489 */ 0x03B9, 0x0314,
+ /* 1491 */ 0x1F30, 0x0300,
+ /* 1493 */ 0x1F31, 0x0300,
+ /* 1495 */ 0x1F30, 0x0301,
+ /* 1497 */ 0x1F31, 0x0301,
+ /* 1499 */ 0x1F30, 0x0342,
+ /* 1501 */ 0x1F31, 0x0342,
+ /* 1503 */ 0x0399, 0x0313,
+ /* 1505 */ 0x0399, 0x0314,
+ /* 1507 */ 0x1F38, 0x0300,
+ /* 1509 */ 0x1F39, 0x0300,
+ /* 1511 */ 0x1F38, 0x0301,
+ /* 1513 */ 0x1F39, 0x0301,
+ /* 1515 */ 0x1F38, 0x0342,
+ /* 1517 */ 0x1F39, 0x0342,
+ /* 1519 */ 0x03BF, 0x0313,
+ /* 1521 */ 0x03BF, 0x0314,
+ /* 1523 */ 0x1F40, 0x0300,
+ /* 1525 */ 0x1F41, 0x0300,
+ /* 1527 */ 0x1F40, 0x0301,
+ /* 1529 */ 0x1F41, 0x0301,
+ /* 1531 */ 0x039F, 0x0313,
+ /* 1533 */ 0x039F, 0x0314,
+ /* 1535 */ 0x1F48, 0x0300,
+ /* 1537 */ 0x1F49, 0x0300,
+ /* 1539 */ 0x1F48, 0x0301,
+ /* 1541 */ 0x1F49, 0x0301,
+ /* 1543 */ 0x03C5, 0x0313,
+ /* 1545 */ 0x03C5, 0x0314,
+ /* 1547 */ 0x1F50, 0x0300,
+ /* 1549 */ 0x1F51, 0x0300,
+ /* 1551 */ 0x1F50, 0x0301,
+ /* 1553 */ 0x1F51, 0x0301,
+ /* 1555 */ 0x1F50, 0x0342,
+ /* 1557 */ 0x1F51, 0x0342,
+ /* 1559 */ 0x03A5, 0x0314,
+ /* 1561 */ 0x1F59, 0x0300,
+ /* 1563 */ 0x1F59, 0x0301,
+ /* 1565 */ 0x1F59, 0x0342,
+ /* 1567 */ 0x03C9, 0x0313,
+ /* 1569 */ 0x03C9, 0x0314,
+ /* 1571 */ 0x1F60, 0x0300,
+ /* 1573 */ 0x1F61, 0x0300,
+ /* 1575 */ 0x1F60, 0x0301,
+ /* 1577 */ 0x1F61, 0x0301,
+ /* 1579 */ 0x1F60, 0x0342,
+ /* 1581 */ 0x1F61, 0x0342,
+ /* 1583 */ 0x03A9, 0x0313,
+ /* 1585 */ 0x03A9, 0x0314,
+ /* 1587 */ 0x1F68, 0x0300,
+ /* 1589 */ 0x1F69, 0x0300,
+ /* 1591 */ 0x1F68, 0x0301,
+ /* 1593 */ 0x1F69, 0x0301,
+ /* 1595 */ 0x1F68, 0x0342,
+ /* 1597 */ 0x1F69, 0x0342,
+ /* 1599 */ 0x03B1, 0x0300,
+ /* 1601 */ 0x03B5, 0x0300,
+ /* 1603 */ 0x03B7, 0x0300,
+ /* 1605 */ 0x03B9, 0x0300,
+ /* 1607 */ 0x03BF, 0x0300,
+ /* 1609 */ 0x03C5, 0x0300,
+ /* 1611 */ 0x03C9, 0x0300,
+ /* 1613 */ 0x1F00, 0x0345,
+ /* 1615 */ 0x1F01, 0x0345,
+ /* 1617 */ 0x1F02, 0x0345,
+ /* 1619 */ 0x1F03, 0x0345,
+ /* 1621 */ 0x1F04, 0x0345,
+ /* 1623 */ 0x1F05, 0x0345,
+ /* 1625 */ 0x1F06, 0x0345,
+ /* 1627 */ 0x1F07, 0x0345,
+ /* 1629 */ 0x1F08, 0x0345,
+ /* 1631 */ 0x1F09, 0x0345,
+ /* 1633 */ 0x1F0A, 0x0345,
+ /* 1635 */ 0x1F0B, 0x0345,
+ /* 1637 */ 0x1F0C, 0x0345,
+ /* 1639 */ 0x1F0D, 0x0345,
+ /* 1641 */ 0x1F0E, 0x0345,
+ /* 1643 */ 0x1F0F, 0x0345,
+ /* 1645 */ 0x1F20, 0x0345,
+ /* 1647 */ 0x1F21, 0x0345,
+ /* 1649 */ 0x1F22, 0x0345,
+ /* 1651 */ 0x1F23, 0x0345,
+ /* 1653 */ 0x1F24, 0x0345,
+ /* 1655 */ 0x1F25, 0x0345,
+ /* 1657 */ 0x1F26, 0x0345,
+ /* 1659 */ 0x1F27, 0x0345,
+ /* 1661 */ 0x1F28, 0x0345,
+ /* 1663 */ 0x1F29, 0x0345,
+ /* 1665 */ 0x1F2A, 0x0345,
+ /* 1667 */ 0x1F2B, 0x0345,
+ /* 1669 */ 0x1F2C, 0x0345,
+ /* 1671 */ 0x1F2D, 0x0345,
+ /* 1673 */ 0x1F2E, 0x0345,
+ /* 1675 */ 0x1F2F, 0x0345,
+ /* 1677 */ 0x1F60, 0x0345,
+ /* 1679 */ 0x1F61, 0x0345,
+ /* 1681 */ 0x1F62, 0x0345,
+ /* 1683 */ 0x1F63, 0x0345,
+ /* 1685 */ 0x1F64, 0x0345,
+ /* 1687 */ 0x1F65, 0x0345,
+ /* 1689 */ 0x1F66, 0x0345,
+ /* 1691 */ 0x1F67, 0x0345,
+ /* 1693 */ 0x1F68, 0x0345,
+ /* 1695 */ 0x1F69, 0x0345,
+ /* 1697 */ 0x1F6A, 0x0345,
+ /* 1699 */ 0x1F6B, 0x0345,
+ /* 1701 */ 0x1F6C, 0x0345,
+ /* 1703 */ 0x1F6D, 0x0345,
+ /* 1705 */ 0x1F6E, 0x0345,
+ /* 1707 */ 0x1F6F, 0x0345,
+ /* 1709 */ 0x03B1, 0x0306,
+ /* 1711 */ 0x03B1, 0x0304,
+ /* 1713 */ 0x1F70, 0x0345,
+ /* 1715 */ 0x03B1, 0x0345,
+ /* 1717 */ 0x03AC, 0x0345,
+ /* 1719 */ 0x03B1, 0x0342,
+ /* 1721 */ 0x1FB6, 0x0345,
+ /* 1723 */ 0x0391, 0x0306,
+ /* 1725 */ 0x0391, 0x0304,
+ /* 1727 */ 0x0391, 0x0300,
+ /* 1729 */ 0x0391, 0x0345,
+ /* 1731 */ 0x0020, 0x0313,
+ /* 1733 */ 0x0020, 0x0313,
+ /* 1735 */ 0x0020, 0x0342,
+ /* 1737 */ 0x00A8, 0x0342,
+ /* 1739 */ 0x1F74, 0x0345,
+ /* 1741 */ 0x03B7, 0x0345,
+ /* 1743 */ 0x03AE, 0x0345,
+ /* 1745 */ 0x03B7, 0x0342,
+ /* 1747 */ 0x1FC6, 0x0345,
+ /* 1749 */ 0x0395, 0x0300,
+ /* 1751 */ 0x0397, 0x0300,
+ /* 1753 */ 0x0397, 0x0345,
+ /* 1755 */ 0x1FBF, 0x0300,
+ /* 1757 */ 0x1FBF, 0x0301,
+ /* 1759 */ 0x1FBF, 0x0342,
+ /* 1761 */ 0x03B9, 0x0306,
+ /* 1763 */ 0x03B9, 0x0304,
+ /* 1765 */ 0x03CA, 0x0300,
+ /* 1767 */ 0x03B9, 0x0342,
+ /* 1769 */ 0x03CA, 0x0342,
+ /* 1771 */ 0x0399, 0x0306,
+ /* 1773 */ 0x0399, 0x0304,
+ /* 1775 */ 0x0399, 0x0300,
+ /* 1777 */ 0x1FFE, 0x0300,
+ /* 1779 */ 0x1FFE, 0x0301,
+ /* 1781 */ 0x1FFE, 0x0342,
+ /* 1783 */ 0x03C5, 0x0306,
+ /* 1785 */ 0x03C5, 0x0304,
+ /* 1787 */ 0x03CB, 0x0300,
+ /* 1789 */ 0x03C1, 0x0313,
+ /* 1791 */ 0x03C1, 0x0314,
+ /* 1793 */ 0x03C5, 0x0342,
+ /* 1795 */ 0x03CB, 0x0342,
+ /* 1797 */ 0x03A5, 0x0306,
+ /* 1799 */ 0x03A5, 0x0304,
+ /* 1801 */ 0x03A5, 0x0300,
+ /* 1803 */ 0x03A1, 0x0314,
+ /* 1805 */ 0x00A8, 0x0300,
+ /* 1807 */ 0x1F7C, 0x0345,
+ /* 1809 */ 0x03C9, 0x0345,
+ /* 1811 */ 0x03CE, 0x0345,
+ /* 1813 */ 0x03C9, 0x0342,
+ /* 1815 */ 0x1FF6, 0x0345,
+ /* 1817 */ 0x039F, 0x0300,
+ /* 1819 */ 0x03A9, 0x0300,
+ /* 1821 */ 0x03A9, 0x0345,
+ /* 1823 */ 0x0020, 0x0314,
+ /* 1825 */ 0x0020, 0x0333,
+ /* 1827 */ 0x002E, 0x002E,
+ /* 1829 */ 0x002E, 0x002E, 0x002E,
+ /* 1832 */ 0x2032, 0x2032,
+ /* 1834 */ 0x2032, 0x2032, 0x2032,
+ /* 1837 */ 0x2035, 0x2035,
+ /* 1839 */ 0x2035, 0x2035, 0x2035,
+ /* 1842 */ 0x0021, 0x0021,
+ /* 1844 */ 0x0020, 0x0305,
+ /* 1846 */ 0x003F, 0x003F,
+ /* 1848 */ 0x003F, 0x0021,
+ /* 1850 */ 0x0021, 0x003F,
+ /* 1852 */ 0x2032, 0x2032, 0x2032, 0x2032,
+ /* 1856 */ 0x0052, 0x0073,
+ /* 1858 */ 0x0061, 0x002F, 0x0063,
+ /* 1861 */ 0x0061, 0x002F, 0x0073,
+ /* 1864 */ 0x00B0, 0x0043,
+ /* 1866 */ 0x0063, 0x002F, 0x006F,
+ /* 1869 */ 0x0063, 0x002F, 0x0075,
+ /* 1872 */ 0x00B0, 0x0046,
+ /* 1874 */ 0x004E, 0x006F,
+ /* 1876 */ 0x0053, 0x004D,
+ /* 1878 */ 0x0054, 0x0045, 0x004C,
+ /* 1881 */ 0x0054, 0x004D,
+ /* 1883 */ 0x0046, 0x0041, 0x0058,
+ /* 1886 */ 0x0031, 0x2044, 0x0037,
+ /* 1889 */ 0x0031, 0x2044, 0x0039,
+ /* 1892 */ 0x0031, 0x2044, 0x0031, 0x0030,
+ /* 1896 */ 0x0031, 0x2044, 0x0033,
+ /* 1899 */ 0x0032, 0x2044, 0x0033,
+ /* 1902 */ 0x0031, 0x2044, 0x0035,
+ /* 1905 */ 0x0032, 0x2044, 0x0035,
+ /* 1908 */ 0x0033, 0x2044, 0x0035,
+ /* 1911 */ 0x0034, 0x2044, 0x0035,
+ /* 1914 */ 0x0031, 0x2044, 0x0036,
+ /* 1917 */ 0x0035, 0x2044, 0x0036,
+ /* 1920 */ 0x0031, 0x2044, 0x0038,
+ /* 1923 */ 0x0033, 0x2044, 0x0038,
+ /* 1926 */ 0x0035, 0x2044, 0x0038,
+ /* 1929 */ 0x0037, 0x2044, 0x0038,
+ /* 1932 */ 0x0031, 0x2044,
+ /* 1934 */ 0x0049, 0x0049,
+ /* 1936 */ 0x0049, 0x0049, 0x0049,
+ /* 1939 */ 0x0049, 0x0056,
+ /* 1941 */ 0x0056, 0x0049,
+ /* 1943 */ 0x0056, 0x0049, 0x0049,
+ /* 1946 */ 0x0056, 0x0049, 0x0049, 0x0049,
+ /* 1950 */ 0x0049, 0x0058,
+ /* 1952 */ 0x0058, 0x0049,
+ /* 1954 */ 0x0058, 0x0049, 0x0049,
+ /* 1957 */ 0x0069, 0x0069,
+ /* 1959 */ 0x0069, 0x0069, 0x0069,
+ /* 1962 */ 0x0069, 0x0076,
+ /* 1964 */ 0x0076, 0x0069,
+ /* 1966 */ 0x0076, 0x0069, 0x0069,
+ /* 1969 */ 0x0076, 0x0069, 0x0069, 0x0069,
+ /* 1973 */ 0x0069, 0x0078,
+ /* 1975 */ 0x0078, 0x0069,
+ /* 1977 */ 0x0078, 0x0069, 0x0069,
+ /* 1980 */ 0x0030, 0x2044, 0x0033,
+ /* 1983 */ 0x2190, 0x0338,
+ /* 1985 */ 0x2192, 0x0338,
+ /* 1987 */ 0x2194, 0x0338,
+ /* 1989 */ 0x21D0, 0x0338,
+ /* 1991 */ 0x21D4, 0x0338,
+ /* 1993 */ 0x21D2, 0x0338,
+ /* 1995 */ 0x2203, 0x0338,
+ /* 1997 */ 0x2208, 0x0338,
+ /* 1999 */ 0x220B, 0x0338,
+ /* 2001 */ 0x2223, 0x0338,
+ /* 2003 */ 0x2225, 0x0338,
+ /* 2005 */ 0x222B, 0x222B,
+ /* 2007 */ 0x222B, 0x222B, 0x222B,
+ /* 2010 */ 0x222E, 0x222E,
+ /* 2012 */ 0x222E, 0x222E, 0x222E,
+ /* 2015 */ 0x223C, 0x0338,
+ /* 2017 */ 0x2243, 0x0338,
+ /* 2019 */ 0x2245, 0x0338,
+ /* 2021 */ 0x2248, 0x0338,
+ /* 2023 */ 0x003D, 0x0338,
+ /* 2025 */ 0x2261, 0x0338,
+ /* 2027 */ 0x224D, 0x0338,
+ /* 2029 */ 0x003C, 0x0338,
+ /* 2031 */ 0x003E, 0x0338,
+ /* 2033 */ 0x2264, 0x0338,
+ /* 2035 */ 0x2265, 0x0338,
+ /* 2037 */ 0x2272, 0x0338,
+ /* 2039 */ 0x2273, 0x0338,
+ /* 2041 */ 0x2276, 0x0338,
+ /* 2043 */ 0x2277, 0x0338,
+ /* 2045 */ 0x227A, 0x0338,
+ /* 2047 */ 0x227B, 0x0338,
+ /* 2049 */ 0x2282, 0x0338,
+ /* 2051 */ 0x2283, 0x0338,
+ /* 2053 */ 0x2286, 0x0338,
+ /* 2055 */ 0x2287, 0x0338,
+ /* 2057 */ 0x22A2, 0x0338,
+ /* 2059 */ 0x22A8, 0x0338,
+ /* 2061 */ 0x22A9, 0x0338,
+ /* 2063 */ 0x22AB, 0x0338,
+ /* 2065 */ 0x227C, 0x0338,
+ /* 2067 */ 0x227D, 0x0338,
+ /* 2069 */ 0x2291, 0x0338,
+ /* 2071 */ 0x2292, 0x0338,
+ /* 2073 */ 0x22B2, 0x0338,
+ /* 2075 */ 0x22B3, 0x0338,
+ /* 2077 */ 0x22B4, 0x0338,
+ /* 2079 */ 0x22B5, 0x0338,
+ /* 2081 */ 0x0031, 0x0030,
+ /* 2083 */ 0x0031, 0x0031,
+ /* 2085 */ 0x0031, 0x0032,
+ /* 2087 */ 0x0031, 0x0033,
+ /* 2089 */ 0x0031, 0x0034,
+ /* 2091 */ 0x0031, 0x0035,
+ /* 2093 */ 0x0031, 0x0036,
+ /* 2095 */ 0x0031, 0x0037,
+ /* 2097 */ 0x0031, 0x0038,
+ /* 2099 */ 0x0031, 0x0039,
+ /* 2101 */ 0x0032, 0x0030,
+ /* 2103 */ 0x0028, 0x0031, 0x0029,
+ /* 2106 */ 0x0028, 0x0032, 0x0029,
+ /* 2109 */ 0x0028, 0x0033, 0x0029,
+ /* 2112 */ 0x0028, 0x0034, 0x0029,
+ /* 2115 */ 0x0028, 0x0035, 0x0029,
+ /* 2118 */ 0x0028, 0x0036, 0x0029,
+ /* 2121 */ 0x0028, 0x0037, 0x0029,
+ /* 2124 */ 0x0028, 0x0038, 0x0029,
+ /* 2127 */ 0x0028, 0x0039, 0x0029,
+ /* 2130 */ 0x0028, 0x0031, 0x0030, 0x0029,
+ /* 2134 */ 0x0028, 0x0031, 0x0031, 0x0029,
+ /* 2138 */ 0x0028, 0x0031, 0x0032, 0x0029,
+ /* 2142 */ 0x0028, 0x0031, 0x0033, 0x0029,
+ /* 2146 */ 0x0028, 0x0031, 0x0034, 0x0029,
+ /* 2150 */ 0x0028, 0x0031, 0x0035, 0x0029,
+ /* 2154 */ 0x0028, 0x0031, 0x0036, 0x0029,
+ /* 2158 */ 0x0028, 0x0031, 0x0037, 0x0029,
+ /* 2162 */ 0x0028, 0x0031, 0x0038, 0x0029,
+ /* 2166 */ 0x0028, 0x0031, 0x0039, 0x0029,
+ /* 2170 */ 0x0028, 0x0032, 0x0030, 0x0029,
+ /* 2174 */ 0x0031, 0x002E,
+ /* 2176 */ 0x0032, 0x002E,
+ /* 2178 */ 0x0033, 0x002E,
+ /* 2180 */ 0x0034, 0x002E,
+ /* 2182 */ 0x0035, 0x002E,
+ /* 2184 */ 0x0036, 0x002E,
+ /* 2186 */ 0x0037, 0x002E,
+ /* 2188 */ 0x0038, 0x002E,
+ /* 2190 */ 0x0039, 0x002E,
+ /* 2192 */ 0x0031, 0x0030, 0x002E,
+ /* 2195 */ 0x0031, 0x0031, 0x002E,
+ /* 2198 */ 0x0031, 0x0032, 0x002E,
+ /* 2201 */ 0x0031, 0x0033, 0x002E,
+ /* 2204 */ 0x0031, 0x0034, 0x002E,
+ /* 2207 */ 0x0031, 0x0035, 0x002E,
+ /* 2210 */ 0x0031, 0x0036, 0x002E,
+ /* 2213 */ 0x0031, 0x0037, 0x002E,
+ /* 2216 */ 0x0031, 0x0038, 0x002E,
+ /* 2219 */ 0x0031, 0x0039, 0x002E,
+ /* 2222 */ 0x0032, 0x0030, 0x002E,
+ /* 2225 */ 0x0028, 0x0061, 0x0029,
+ /* 2228 */ 0x0028, 0x0062, 0x0029,
+ /* 2231 */ 0x0028, 0x0063, 0x0029,
+ /* 2234 */ 0x0028, 0x0064, 0x0029,
+ /* 2237 */ 0x0028, 0x0065, 0x0029,
+ /* 2240 */ 0x0028, 0x0066, 0x0029,
+ /* 2243 */ 0x0028, 0x0067, 0x0029,
+ /* 2246 */ 0x0028, 0x0068, 0x0029,
+ /* 2249 */ 0x0028, 0x0069, 0x0029,
+ /* 2252 */ 0x0028, 0x006A, 0x0029,
+ /* 2255 */ 0x0028, 0x006B, 0x0029,
+ /* 2258 */ 0x0028, 0x006C, 0x0029,
+ /* 2261 */ 0x0028, 0x006D, 0x0029,
+ /* 2264 */ 0x0028, 0x006E, 0x0029,
+ /* 2267 */ 0x0028, 0x006F, 0x0029,
+ /* 2270 */ 0x0028, 0x0070, 0x0029,
+ /* 2273 */ 0x0028, 0x0071, 0x0029,
+ /* 2276 */ 0x0028, 0x0072, 0x0029,
+ /* 2279 */ 0x0028, 0x0073, 0x0029,
+ /* 2282 */ 0x0028, 0x0074, 0x0029,
+ /* 2285 */ 0x0028, 0x0075, 0x0029,
+ /* 2288 */ 0x0028, 0x0076, 0x0029,
+ /* 2291 */ 0x0028, 0x0077, 0x0029,
+ /* 2294 */ 0x0028, 0x0078, 0x0029,
+ /* 2297 */ 0x0028, 0x0079, 0x0029,
+ /* 2300 */ 0x0028, 0x007A, 0x0029,
+ /* 2303 */ 0x222B, 0x222B, 0x222B, 0x222B,
+ /* 2307 */ 0x003A, 0x003A, 0x003D,
+ /* 2310 */ 0x003D, 0x003D,
+ /* 2312 */ 0x003D, 0x003D, 0x003D,
+ /* 2315 */ 0x2ADD, 0x0338,
+ /* 2317 */ 0x304B, 0x3099,
+ /* 2319 */ 0x304D, 0x3099,
+ /* 2321 */ 0x304F, 0x3099,
+ /* 2323 */ 0x3051, 0x3099,
+ /* 2325 */ 0x3053, 0x3099,
+ /* 2327 */ 0x3055, 0x3099,
+ /* 2329 */ 0x3057, 0x3099,
+ /* 2331 */ 0x3059, 0x3099,
+ /* 2333 */ 0x305B, 0x3099,
+ /* 2335 */ 0x305D, 0x3099,
+ /* 2337 */ 0x305F, 0x3099,
+ /* 2339 */ 0x3061, 0x3099,
+ /* 2341 */ 0x3064, 0x3099,
+ /* 2343 */ 0x3066, 0x3099,
+ /* 2345 */ 0x3068, 0x3099,
+ /* 2347 */ 0x306F, 0x3099,
+ /* 2349 */ 0x306F, 0x309A,
+ /* 2351 */ 0x3072, 0x3099,
+ /* 2353 */ 0x3072, 0x309A,
+ /* 2355 */ 0x3075, 0x3099,
+ /* 2357 */ 0x3075, 0x309A,
+ /* 2359 */ 0x3078, 0x3099,
+ /* 2361 */ 0x3078, 0x309A,
+ /* 2363 */ 0x307B, 0x3099,
+ /* 2365 */ 0x307B, 0x309A,
+ /* 2367 */ 0x3046, 0x3099,
+ /* 2369 */ 0x0020, 0x3099,
+ /* 2371 */ 0x0020, 0x309A,
+ /* 2373 */ 0x309D, 0x3099,
+ /* 2375 */ 0x3088, 0x308A,
+ /* 2377 */ 0x30AB, 0x3099,
+ /* 2379 */ 0x30AD, 0x3099,
+ /* 2381 */ 0x30AF, 0x3099,
+ /* 2383 */ 0x30B1, 0x3099,
+ /* 2385 */ 0x30B3, 0x3099,
+ /* 2387 */ 0x30B5, 0x3099,
+ /* 2389 */ 0x30B7, 0x3099,
+ /* 2391 */ 0x30B9, 0x3099,
+ /* 2393 */ 0x30BB, 0x3099,
+ /* 2395 */ 0x30BD, 0x3099,
+ /* 2397 */ 0x30BF, 0x3099,
+ /* 2399 */ 0x30C1, 0x3099,
+ /* 2401 */ 0x30C4, 0x3099,
+ /* 2403 */ 0x30C6, 0x3099,
+ /* 2405 */ 0x30C8, 0x3099,
+ /* 2407 */ 0x30CF, 0x3099,
+ /* 2409 */ 0x30CF, 0x309A,
+ /* 2411 */ 0x30D2, 0x3099,
+ /* 2413 */ 0x30D2, 0x309A,
+ /* 2415 */ 0x30D5, 0x3099,
+ /* 2417 */ 0x30D5, 0x309A,
+ /* 2419 */ 0x30D8, 0x3099,
+ /* 2421 */ 0x30D8, 0x309A,
+ /* 2423 */ 0x30DB, 0x3099,
+ /* 2425 */ 0x30DB, 0x309A,
+ /* 2427 */ 0x30A6, 0x3099,
+ /* 2429 */ 0x30EF, 0x3099,
+ /* 2431 */ 0x30F0, 0x3099,
+ /* 2433 */ 0x30F1, 0x3099,
+ /* 2435 */ 0x30F2, 0x3099,
+ /* 2437 */ 0x30FD, 0x3099,
+ /* 2439 */ 0x30B3, 0x30C8,
+ /* 2441 */ 0x0028, 0x1100, 0x0029,
+ /* 2444 */ 0x0028, 0x1102, 0x0029,
+ /* 2447 */ 0x0028, 0x1103, 0x0029,
+ /* 2450 */ 0x0028, 0x1105, 0x0029,
+ /* 2453 */ 0x0028, 0x1106, 0x0029,
+ /* 2456 */ 0x0028, 0x1107, 0x0029,
+ /* 2459 */ 0x0028, 0x1109, 0x0029,
+ /* 2462 */ 0x0028, 0x110B, 0x0029,
+ /* 2465 */ 0x0028, 0x110C, 0x0029,
+ /* 2468 */ 0x0028, 0x110E, 0x0029,
+ /* 2471 */ 0x0028, 0x110F, 0x0029,
+ /* 2474 */ 0x0028, 0x1110, 0x0029,
+ /* 2477 */ 0x0028, 0x1111, 0x0029,
+ /* 2480 */ 0x0028, 0x1112, 0x0029,
+ /* 2483 */ 0x0028, 0x1100, 0x1161, 0x0029,
+ /* 2487 */ 0x0028, 0x1102, 0x1161, 0x0029,
+ /* 2491 */ 0x0028, 0x1103, 0x1161, 0x0029,
+ /* 2495 */ 0x0028, 0x1105, 0x1161, 0x0029,
+ /* 2499 */ 0x0028, 0x1106, 0x1161, 0x0029,
+ /* 2503 */ 0x0028, 0x1107, 0x1161, 0x0029,
+ /* 2507 */ 0x0028, 0x1109, 0x1161, 0x0029,
+ /* 2511 */ 0x0028, 0x110B, 0x1161, 0x0029,
+ /* 2515 */ 0x0028, 0x110C, 0x1161, 0x0029,
+ /* 2519 */ 0x0028, 0x110E, 0x1161, 0x0029,
+ /* 2523 */ 0x0028, 0x110F, 0x1161, 0x0029,
+ /* 2527 */ 0x0028, 0x1110, 0x1161, 0x0029,
+ /* 2531 */ 0x0028, 0x1111, 0x1161, 0x0029,
+ /* 2535 */ 0x0028, 0x1112, 0x1161, 0x0029,
+ /* 2539 */ 0x0028, 0x110C, 0x116E, 0x0029,
+ /* 2543 */ 0x0028, 0x110B, 0x1169, 0x110C, 0x1165, 0x11AB, 0x0029,
+ /* 2550 */ 0x0028, 0x110B, 0x1169, 0x1112, 0x116E, 0x0029,
+ /* 2556 */ 0x0028, 0x4E00, 0x0029,
+ /* 2559 */ 0x0028, 0x4E8C, 0x0029,
+ /* 2562 */ 0x0028, 0x4E09, 0x0029,
+ /* 2565 */ 0x0028, 0x56DB, 0x0029,
+ /* 2568 */ 0x0028, 0x4E94, 0x0029,
+ /* 2571 */ 0x0028, 0x516D, 0x0029,
+ /* 2574 */ 0x0028, 0x4E03, 0x0029,
+ /* 2577 */ 0x0028, 0x516B, 0x0029,
+ /* 2580 */ 0x0028, 0x4E5D, 0x0029,
+ /* 2583 */ 0x0028, 0x5341, 0x0029,
+ /* 2586 */ 0x0028, 0x6708, 0x0029,
+ /* 2589 */ 0x0028, 0x706B, 0x0029,
+ /* 2592 */ 0x0028, 0x6C34, 0x0029,
+ /* 2595 */ 0x0028, 0x6728, 0x0029,
+ /* 2598 */ 0x0028, 0x91D1, 0x0029,
+ /* 2601 */ 0x0028, 0x571F, 0x0029,
+ /* 2604 */ 0x0028, 0x65E5, 0x0029,
+ /* 2607 */ 0x0028, 0x682A, 0x0029,
+ /* 2610 */ 0x0028, 0x6709, 0x0029,
+ /* 2613 */ 0x0028, 0x793E, 0x0029,
+ /* 2616 */ 0x0028, 0x540D, 0x0029,
+ /* 2619 */ 0x0028, 0x7279, 0x0029,
+ /* 2622 */ 0x0028, 0x8CA1, 0x0029,
+ /* 2625 */ 0x0028, 0x795D, 0x0029,
+ /* 2628 */ 0x0028, 0x52B4, 0x0029,
+ /* 2631 */ 0x0028, 0x4EE3, 0x0029,
+ /* 2634 */ 0x0028, 0x547C, 0x0029,
+ /* 2637 */ 0x0028, 0x5B66, 0x0029,
+ /* 2640 */ 0x0028, 0x76E3, 0x0029,
+ /* 2643 */ 0x0028, 0x4F01, 0x0029,
+ /* 2646 */ 0x0028, 0x8CC7, 0x0029,
+ /* 2649 */ 0x0028, 0x5354, 0x0029,
+ /* 2652 */ 0x0028, 0x796D, 0x0029,
+ /* 2655 */ 0x0028, 0x4F11, 0x0029,
+ /* 2658 */ 0x0028, 0x81EA, 0x0029,
+ /* 2661 */ 0x0028, 0x81F3, 0x0029,
+ /* 2664 */ 0x0050, 0x0054, 0x0045,
+ /* 2667 */ 0x0032, 0x0031,
+ /* 2669 */ 0x0032, 0x0032,
+ /* 2671 */ 0x0032, 0x0033,
+ /* 2673 */ 0x0032, 0x0034,
+ /* 2675 */ 0x0032, 0x0035,
+ /* 2677 */ 0x0032, 0x0036,
+ /* 2679 */ 0x0032, 0x0037,
+ /* 2681 */ 0x0032, 0x0038,
+ /* 2683 */ 0x0032, 0x0039,
+ /* 2685 */ 0x0033, 0x0030,
+ /* 2687 */ 0x0033, 0x0031,
+ /* 2689 */ 0x0033, 0x0032,
+ /* 2691 */ 0x0033, 0x0033,
+ /* 2693 */ 0x0033, 0x0034,
+ /* 2695 */ 0x0033, 0x0035,
+ /* 2697 */ 0x1100, 0x1161,
+ /* 2699 */ 0x1102, 0x1161,
+ /* 2701 */ 0x1103, 0x1161,
+ /* 2703 */ 0x1105, 0x1161,
+ /* 2705 */ 0x1106, 0x1161,
+ /* 2707 */ 0x1107, 0x1161,
+ /* 2709 */ 0x1109, 0x1161,
+ /* 2711 */ 0x110B, 0x1161,
+ /* 2713 */ 0x110C, 0x1161,
+ /* 2715 */ 0x110E, 0x1161,
+ /* 2717 */ 0x110F, 0x1161,
+ /* 2719 */ 0x1110, 0x1161,
+ /* 2721 */ 0x1111, 0x1161,
+ /* 2723 */ 0x1112, 0x1161,
+ /* 2725 */ 0x110E, 0x1161, 0x11B7, 0x1100, 0x1169,
+ /* 2730 */ 0x110C, 0x116E, 0x110B, 0x1174,
+ /* 2734 */ 0x110B, 0x116E,
+ /* 2736 */ 0x0033, 0x0036,
+ /* 2738 */ 0x0033, 0x0037,
+ /* 2740 */ 0x0033, 0x0038,
+ /* 2742 */ 0x0033, 0x0039,
+ /* 2744 */ 0x0034, 0x0030,
+ /* 2746 */ 0x0034, 0x0031,
+ /* 2748 */ 0x0034, 0x0032,
+ /* 2750 */ 0x0034, 0x0033,
+ /* 2752 */ 0x0034, 0x0034,
+ /* 2754 */ 0x0034, 0x0035,
+ /* 2756 */ 0x0034, 0x0036,
+ /* 2758 */ 0x0034, 0x0037,
+ /* 2760 */ 0x0034, 0x0038,
+ /* 2762 */ 0x0034, 0x0039,
+ /* 2764 */ 0x0035, 0x0030,
+ /* 2766 */ 0x0031, 0x6708,
+ /* 2768 */ 0x0032, 0x6708,
+ /* 2770 */ 0x0033, 0x6708,
+ /* 2772 */ 0x0034, 0x6708,
+ /* 2774 */ 0x0035, 0x6708,
+ /* 2776 */ 0x0036, 0x6708,
+ /* 2778 */ 0x0037, 0x6708,
+ /* 2780 */ 0x0038, 0x6708,
+ /* 2782 */ 0x0039, 0x6708,
+ /* 2784 */ 0x0031, 0x0030, 0x6708,
+ /* 2787 */ 0x0031, 0x0031, 0x6708,
+ /* 2790 */ 0x0031, 0x0032, 0x6708,
+ /* 2793 */ 0x0048, 0x0067,
+ /* 2795 */ 0x0065, 0x0072, 0x0067,
+ /* 2798 */ 0x0065, 0x0056,
+ /* 2800 */ 0x004C, 0x0054, 0x0044,
+ /* 2803 */ 0x4EE4, 0x548C,
+ /* 2805 */ 0x30A2, 0x30D1, 0x30FC, 0x30C8,
+ /* 2809 */ 0x30A2, 0x30EB, 0x30D5, 0x30A1,
+ /* 2813 */ 0x30A2, 0x30F3, 0x30DA, 0x30A2,
+ /* 2817 */ 0x30A2, 0x30FC, 0x30EB,
+ /* 2820 */ 0x30A4, 0x30CB, 0x30F3, 0x30B0,
+ /* 2824 */ 0x30A4, 0x30F3, 0x30C1,
+ /* 2827 */ 0x30A6, 0x30A9, 0x30F3,
+ /* 2830 */ 0x30A8, 0x30B9, 0x30AF, 0x30FC, 0x30C9,
+ /* 2835 */ 0x30A8, 0x30FC, 0x30AB, 0x30FC,
+ /* 2839 */ 0x30AA, 0x30F3, 0x30B9,
+ /* 2842 */ 0x30AA, 0x30FC, 0x30E0,
+ /* 2845 */ 0x30AB, 0x30A4, 0x30EA,
+ /* 2848 */ 0x30AB, 0x30E9, 0x30C3, 0x30C8,
+ /* 2852 */ 0x30AB, 0x30ED, 0x30EA, 0x30FC,
+ /* 2856 */ 0x30AC, 0x30ED, 0x30F3,
+ /* 2859 */ 0x30AC, 0x30F3, 0x30DE,
+ /* 2862 */ 0x30AE, 0x30AC,
+ /* 2864 */ 0x30AE, 0x30CB, 0x30FC,
+ /* 2867 */ 0x30AD, 0x30E5, 0x30EA, 0x30FC,
+ /* 2871 */ 0x30AE, 0x30EB, 0x30C0, 0x30FC,
+ /* 2875 */ 0x30AD, 0x30ED,
+ /* 2877 */ 0x30AD, 0x30ED, 0x30B0, 0x30E9, 0x30E0,
+ /* 2882 */ 0x30AD, 0x30ED, 0x30E1, 0x30FC, 0x30C8, 0x30EB,
+ /* 2888 */ 0x30AD, 0x30ED, 0x30EF, 0x30C3, 0x30C8,
+ /* 2893 */ 0x30B0, 0x30E9, 0x30E0,
+ /* 2896 */ 0x30B0, 0x30E9, 0x30E0, 0x30C8, 0x30F3,
+ /* 2901 */ 0x30AF, 0x30EB, 0x30BC, 0x30A4, 0x30ED,
+ /* 2906 */ 0x30AF, 0x30ED, 0x30FC, 0x30CD,
+ /* 2910 */ 0x30B1, 0x30FC, 0x30B9,
+ /* 2913 */ 0x30B3, 0x30EB, 0x30CA,
+ /* 2916 */ 0x30B3, 0x30FC, 0x30DD,
+ /* 2919 */ 0x30B5, 0x30A4, 0x30AF, 0x30EB,
+ /* 2923 */ 0x30B5, 0x30F3, 0x30C1, 0x30FC, 0x30E0,
+ /* 2928 */ 0x30B7, 0x30EA, 0x30F3, 0x30B0,
+ /* 2932 */ 0x30BB, 0x30F3, 0x30C1,
+ /* 2935 */ 0x30BB, 0x30F3, 0x30C8,
+ /* 2938 */ 0x30C0, 0x30FC, 0x30B9,
+ /* 2941 */ 0x30C7, 0x30B7,
+ /* 2943 */ 0x30C9, 0x30EB,
+ /* 2945 */ 0x30C8, 0x30F3,
+ /* 2947 */ 0x30CA, 0x30CE,
+ /* 2949 */ 0x30CE, 0x30C3, 0x30C8,
+ /* 2952 */ 0x30CF, 0x30A4, 0x30C4,
+ /* 2955 */ 0x30D1, 0x30FC, 0x30BB, 0x30F3, 0x30C8,
+ /* 2960 */ 0x30D1, 0x30FC, 0x30C4,
+ /* 2963 */ 0x30D0, 0x30FC, 0x30EC, 0x30EB,
+ /* 2967 */ 0x30D4, 0x30A2, 0x30B9, 0x30C8, 0x30EB,
+ /* 2972 */ 0x30D4, 0x30AF, 0x30EB,
+ /* 2975 */ 0x30D4, 0x30B3,
+ /* 2977 */ 0x30D3, 0x30EB,
+ /* 2979 */ 0x30D5, 0x30A1, 0x30E9, 0x30C3, 0x30C9,
+ /* 2984 */ 0x30D5, 0x30A3, 0x30FC, 0x30C8,
+ /* 2988 */ 0x30D6, 0x30C3, 0x30B7, 0x30A7, 0x30EB,
+ /* 2993 */ 0x30D5, 0x30E9, 0x30F3,
+ /* 2996 */ 0x30D8, 0x30AF, 0x30BF, 0x30FC, 0x30EB,
+ /* 3001 */ 0x30DA, 0x30BD,
+ /* 3003 */ 0x30DA, 0x30CB, 0x30D2,
+ /* 3006 */ 0x30D8, 0x30EB, 0x30C4,
+ /* 3009 */ 0x30DA, 0x30F3, 0x30B9,
+ /* 3012 */ 0x30DA, 0x30FC, 0x30B8,
+ /* 3015 */ 0x30D9, 0x30FC, 0x30BF,
+ /* 3018 */ 0x30DD, 0x30A4, 0x30F3, 0x30C8,
+ /* 3022 */ 0x30DC, 0x30EB, 0x30C8,
+ /* 3025 */ 0x30DB, 0x30F3,
+ /* 3027 */ 0x30DD, 0x30F3, 0x30C9,
+ /* 3030 */ 0x30DB, 0x30FC, 0x30EB,
+ /* 3033 */ 0x30DB, 0x30FC, 0x30F3,
+ /* 3036 */ 0x30DE, 0x30A4, 0x30AF, 0x30ED,
+ /* 3040 */ 0x30DE, 0x30A4, 0x30EB,
+ /* 3043 */ 0x30DE, 0x30C3, 0x30CF,
+ /* 3046 */ 0x30DE, 0x30EB, 0x30AF,
+ /* 3049 */ 0x30DE, 0x30F3, 0x30B7, 0x30E7, 0x30F3,
+ /* 3054 */ 0x30DF, 0x30AF, 0x30ED, 0x30F3,
+ /* 3058 */ 0x30DF, 0x30EA,
+ /* 3060 */ 0x30DF, 0x30EA, 0x30D0, 0x30FC, 0x30EB,
+ /* 3065 */ 0x30E1, 0x30AC,
+ /* 3067 */ 0x30E1, 0x30AC, 0x30C8, 0x30F3,
+ /* 3071 */ 0x30E1, 0x30FC, 0x30C8, 0x30EB,
+ /* 3075 */ 0x30E4, 0x30FC, 0x30C9,
+ /* 3078 */ 0x30E4, 0x30FC, 0x30EB,
+ /* 3081 */ 0x30E6, 0x30A2, 0x30F3,
+ /* 3084 */ 0x30EA, 0x30C3, 0x30C8, 0x30EB,
+ /* 3088 */ 0x30EA, 0x30E9,
+ /* 3090 */ 0x30EB, 0x30D4, 0x30FC,
+ /* 3093 */ 0x30EB, 0x30FC, 0x30D6, 0x30EB,
+ /* 3097 */ 0x30EC, 0x30E0,
+ /* 3099 */ 0x30EC, 0x30F3, 0x30C8, 0x30B2, 0x30F3,
+ /* 3104 */ 0x30EF, 0x30C3, 0x30C8,
+ /* 3107 */ 0x0030, 0x70B9,
+ /* 3109 */ 0x0031, 0x70B9,
+ /* 3111 */ 0x0032, 0x70B9,
+ /* 3113 */ 0x0033, 0x70B9,
+ /* 3115 */ 0x0034, 0x70B9,
+ /* 3117 */ 0x0035, 0x70B9,
+ /* 3119 */ 0x0036, 0x70B9,
+ /* 3121 */ 0x0037, 0x70B9,
+ /* 3123 */ 0x0038, 0x70B9,
+ /* 3125 */ 0x0039, 0x70B9,
+ /* 3127 */ 0x0031, 0x0030, 0x70B9,
+ /* 3130 */ 0x0031, 0x0031, 0x70B9,
+ /* 3133 */ 0x0031, 0x0032, 0x70B9,
+ /* 3136 */ 0x0031, 0x0033, 0x70B9,
+ /* 3139 */ 0x0031, 0x0034, 0x70B9,
+ /* 3142 */ 0x0031, 0x0035, 0x70B9,
+ /* 3145 */ 0x0031, 0x0036, 0x70B9,
+ /* 3148 */ 0x0031, 0x0037, 0x70B9,
+ /* 3151 */ 0x0031, 0x0038, 0x70B9,
+ /* 3154 */ 0x0031, 0x0039, 0x70B9,
+ /* 3157 */ 0x0032, 0x0030, 0x70B9,
+ /* 3160 */ 0x0032, 0x0031, 0x70B9,
+ /* 3163 */ 0x0032, 0x0032, 0x70B9,
+ /* 3166 */ 0x0032, 0x0033, 0x70B9,
+ /* 3169 */ 0x0032, 0x0034, 0x70B9,
+ /* 3172 */ 0x0068, 0x0050, 0x0061,
+ /* 3175 */ 0x0064, 0x0061,
+ /* 3177 */ 0x0041, 0x0055,
+ /* 3179 */ 0x0062, 0x0061, 0x0072,
+ /* 3182 */ 0x006F, 0x0056,
+ /* 3184 */ 0x0070, 0x0063,
+ /* 3186 */ 0x0064, 0x006D,
+ /* 3188 */ 0x0064, 0x006D, 0x00B2,
+ /* 3191 */ 0x0064, 0x006D, 0x00B3,
+ /* 3194 */ 0x0049, 0x0055,
+ /* 3196 */ 0x5E73, 0x6210,
+ /* 3198 */ 0x662D, 0x548C,
+ /* 3200 */ 0x5927, 0x6B63,
+ /* 3202 */ 0x660E, 0x6CBB,
+ /* 3204 */ 0x682A, 0x5F0F, 0x4F1A, 0x793E,
+ /* 3208 */ 0x0070, 0x0041,
+ /* 3210 */ 0x006E, 0x0041,
+ /* 3212 */ 0x03BC, 0x0041,
+ /* 3214 */ 0x006D, 0x0041,
+ /* 3216 */ 0x006B, 0x0041,
+ /* 3218 */ 0x004B, 0x0042,
+ /* 3220 */ 0x004D, 0x0042,
+ /* 3222 */ 0x0047, 0x0042,
+ /* 3224 */ 0x0063, 0x0061, 0x006C,
+ /* 3227 */ 0x006B, 0x0063, 0x0061, 0x006C,
+ /* 3231 */ 0x0070, 0x0046,
+ /* 3233 */ 0x006E, 0x0046,
+ /* 3235 */ 0x03BC, 0x0046,
+ /* 3237 */ 0x03BC, 0x0067,
+ /* 3239 */ 0x006D, 0x0067,
+ /* 3241 */ 0x006B, 0x0067,
+ /* 3243 */ 0x0048, 0x007A,
+ /* 3245 */ 0x006B, 0x0048, 0x007A,
+ /* 3248 */ 0x004D, 0x0048, 0x007A,
+ /* 3251 */ 0x0047, 0x0048, 0x007A,
+ /* 3254 */ 0x0054, 0x0048, 0x007A,
+ /* 3257 */ 0x03BC, 0x2113,
+ /* 3259 */ 0x006D, 0x2113,
+ /* 3261 */ 0x0064, 0x2113,
+ /* 3263 */ 0x006B, 0x2113,
+ /* 3265 */ 0x0066, 0x006D,
+ /* 3267 */ 0x006E, 0x006D,
+ /* 3269 */ 0x03BC, 0x006D,
+ /* 3271 */ 0x006D, 0x006D,
+ /* 3273 */ 0x0063, 0x006D,
+ /* 3275 */ 0x006B, 0x006D,
+ /* 3277 */ 0x006D, 0x006D, 0x00B2,
+ /* 3280 */ 0x0063, 0x006D, 0x00B2,
+ /* 3283 */ 0x006D, 0x00B2,
+ /* 3285 */ 0x006B, 0x006D, 0x00B2,
+ /* 3288 */ 0x006D, 0x006D, 0x00B3,
+ /* 3291 */ 0x0063, 0x006D, 0x00B3,
+ /* 3294 */ 0x006D, 0x00B3,
+ /* 3296 */ 0x006B, 0x006D, 0x00B3,
+ /* 3299 */ 0x006D, 0x2215, 0x0073,
+ /* 3302 */ 0x006D, 0x2215, 0x0073, 0x00B2,
+ /* 3306 */ 0x0050, 0x0061,
+ /* 3308 */ 0x006B, 0x0050, 0x0061,
+ /* 3311 */ 0x004D, 0x0050, 0x0061,
+ /* 3314 */ 0x0047, 0x0050, 0x0061,
+ /* 3317 */ 0x0072, 0x0061, 0x0064,
+ /* 3320 */ 0x0072, 0x0061, 0x0064, 0x2215, 0x0073,
+ /* 3325 */ 0x0072, 0x0061, 0x0064, 0x2215, 0x0073, 0x00B2,
+ /* 3331 */ 0x0070, 0x0073,
+ /* 3333 */ 0x006E, 0x0073,
+ /* 3335 */ 0x03BC, 0x0073,
+ /* 3337 */ 0x006D, 0x0073,
+ /* 3339 */ 0x0070, 0x0056,
+ /* 3341 */ 0x006E, 0x0056,
+ /* 3343 */ 0x03BC, 0x0056,
+ /* 3345 */ 0x006D, 0x0056,
+ /* 3347 */ 0x006B, 0x0056,
+ /* 3349 */ 0x004D, 0x0056,
+ /* 3351 */ 0x0070, 0x0057,
+ /* 3353 */ 0x006E, 0x0057,
+ /* 3355 */ 0x03BC, 0x0057,
+ /* 3357 */ 0x006D, 0x0057,
+ /* 3359 */ 0x006B, 0x0057,
+ /* 3361 */ 0x004D, 0x0057,
+ /* 3363 */ 0x006B, 0x03A9,
+ /* 3365 */ 0x004D, 0x03A9,
+ /* 3367 */ 0x0061, 0x002E, 0x006D, 0x002E,
+ /* 3371 */ 0x0042, 0x0071,
+ /* 3373 */ 0x0063, 0x0063,
+ /* 3375 */ 0x0063, 0x0064,
+ /* 3377 */ 0x0043, 0x2215, 0x006B, 0x0067,
+ /* 3381 */ 0x0043, 0x006F, 0x002E,
+ /* 3384 */ 0x0064, 0x0042,
+ /* 3386 */ 0x0047, 0x0079,
+ /* 3388 */ 0x0068, 0x0061,
+ /* 3390 */ 0x0048, 0x0050,
+ /* 3392 */ 0x0069, 0x006E,
+ /* 3394 */ 0x004B, 0x004B,
+ /* 3396 */ 0x004B, 0x004D,
+ /* 3398 */ 0x006B, 0x0074,
+ /* 3400 */ 0x006C, 0x006D,
+ /* 3402 */ 0x006C, 0x006E,
+ /* 3404 */ 0x006C, 0x006F, 0x0067,
+ /* 3407 */ 0x006C, 0x0078,
+ /* 3409 */ 0x006D, 0x0062,
+ /* 3411 */ 0x006D, 0x0069, 0x006C,
+ /* 3414 */ 0x006D, 0x006F, 0x006C,
+ /* 3417 */ 0x0050, 0x0048,
+ /* 3419 */ 0x0070, 0x002E, 0x006D, 0x002E,
+ /* 3423 */ 0x0050, 0x0050, 0x004D,
+ /* 3426 */ 0x0050, 0x0052,
+ /* 3428 */ 0x0073, 0x0072,
+ /* 3430 */ 0x0053, 0x0076,
+ /* 3432 */ 0x0057, 0x0062,
+ /* 3434 */ 0x0056, 0x2215, 0x006D,
+ /* 3437 */ 0x0041, 0x2215, 0x006D,
+ /* 3440 */ 0x0031, 0x65E5,
+ /* 3442 */ 0x0032, 0x65E5,
+ /* 3444 */ 0x0033, 0x65E5,
+ /* 3446 */ 0x0034, 0x65E5,
+ /* 3448 */ 0x0035, 0x65E5,
+ /* 3450 */ 0x0036, 0x65E5,
+ /* 3452 */ 0x0037, 0x65E5,
+ /* 3454 */ 0x0038, 0x65E5,
+ /* 3456 */ 0x0039, 0x65E5,
+ /* 3458 */ 0x0031, 0x0030, 0x65E5,
+ /* 3461 */ 0x0031, 0x0031, 0x65E5,
+ /* 3464 */ 0x0031, 0x0032, 0x65E5,
+ /* 3467 */ 0x0031, 0x0033, 0x65E5,
+ /* 3470 */ 0x0031, 0x0034, 0x65E5,
+ /* 3473 */ 0x0031, 0x0035, 0x65E5,
+ /* 3476 */ 0x0031, 0x0036, 0x65E5,
+ /* 3479 */ 0x0031, 0x0037, 0x65E5,
+ /* 3482 */ 0x0031, 0x0038, 0x65E5,
+ /* 3485 */ 0x0031, 0x0039, 0x65E5,
+ /* 3488 */ 0x0032, 0x0030, 0x65E5,
+ /* 3491 */ 0x0032, 0x0031, 0x65E5,
+ /* 3494 */ 0x0032, 0x0032, 0x65E5,
+ /* 3497 */ 0x0032, 0x0033, 0x65E5,
+ /* 3500 */ 0x0032, 0x0034, 0x65E5,
+ /* 3503 */ 0x0032, 0x0035, 0x65E5,
+ /* 3506 */ 0x0032, 0x0036, 0x65E5,
+ /* 3509 */ 0x0032, 0x0037, 0x65E5,
+ /* 3512 */ 0x0032, 0x0038, 0x65E5,
+ /* 3515 */ 0x0032, 0x0039, 0x65E5,
+ /* 3518 */ 0x0033, 0x0030, 0x65E5,
+ /* 3521 */ 0x0033, 0x0031, 0x65E5,
+ /* 3524 */ 0x0067, 0x0061, 0x006C,
+ /* 3527 */ 0x242EE,
+ /* 3528 */ 0x2284A,
+ /* 3529 */ 0x22844,
+ /* 3530 */ 0x233D5,
+ /* 3531 */ 0x25249,
+ /* 3532 */ 0x25CD0,
+ /* 3533 */ 0x27ED3,
+ /* 3534 */ 0x0066, 0x0066,
+ /* 3536 */ 0x0066, 0x0069,
+ /* 3538 */ 0x0066, 0x006C,
+ /* 3540 */ 0x0066, 0x0066, 0x0069,
+ /* 3543 */ 0x0066, 0x0066, 0x006C,
+ /* 3546 */ 0x017F, 0x0074,
+ /* 3548 */ 0x0073, 0x0074,
+ /* 3550 */ 0x0574, 0x0576,
+ /* 3552 */ 0x0574, 0x0565,
+ /* 3554 */ 0x0574, 0x056B,
+ /* 3556 */ 0x057E, 0x0576,
+ /* 3558 */ 0x0574, 0x056D,
+ /* 3560 */ 0x05D9, 0x05B4,
+ /* 3562 */ 0x05F2, 0x05B7,
+ /* 3564 */ 0x05E9, 0x05C1,
+ /* 3566 */ 0x05E9, 0x05C2,
+ /* 3568 */ 0xFB49, 0x05C1,
+ /* 3570 */ 0xFB49, 0x05C2,
+ /* 3572 */ 0x05D0, 0x05B7,
+ /* 3574 */ 0x05D0, 0x05B8,
+ /* 3576 */ 0x05D0, 0x05BC,
+ /* 3578 */ 0x05D1, 0x05BC,
+ /* 3580 */ 0x05D2, 0x05BC,
+ /* 3582 */ 0x05D3, 0x05BC,
+ /* 3584 */ 0x05D4, 0x05BC,
+ /* 3586 */ 0x05D5, 0x05BC,
+ /* 3588 */ 0x05D6, 0x05BC,
+ /* 3590 */ 0x05D8, 0x05BC,
+ /* 3592 */ 0x05D9, 0x05BC,
+ /* 3594 */ 0x05DA, 0x05BC,
+ /* 3596 */ 0x05DB, 0x05BC,
+ /* 3598 */ 0x05DC, 0x05BC,
+ /* 3600 */ 0x05DE, 0x05BC,
+ /* 3602 */ 0x05E0, 0x05BC,
+ /* 3604 */ 0x05E1, 0x05BC,
+ /* 3606 */ 0x05E3, 0x05BC,
+ /* 3608 */ 0x05E4, 0x05BC,
+ /* 3610 */ 0x05E6, 0x05BC,
+ /* 3612 */ 0x05E7, 0x05BC,
+ /* 3614 */ 0x05E8, 0x05BC,
+ /* 3616 */ 0x05E9, 0x05BC,
+ /* 3618 */ 0x05EA, 0x05BC,
+ /* 3620 */ 0x05D5, 0x05B9,
+ /* 3622 */ 0x05D1, 0x05BF,
+ /* 3624 */ 0x05DB, 0x05BF,
+ /* 3626 */ 0x05E4, 0x05BF,
+ /* 3628 */ 0x05D0, 0x05DC,
+ /* 3630 */ 0x0626, 0x0627,
+ /* 3632 */ 0x0626, 0x0627,
+ /* 3634 */ 0x0626, 0x06D5,
+ /* 3636 */ 0x0626, 0x06D5,
+ /* 3638 */ 0x0626, 0x0648,
+ /* 3640 */ 0x0626, 0x0648,
+ /* 3642 */ 0x0626, 0x06C7,
+ /* 3644 */ 0x0626, 0x06C7,
+ /* 3646 */ 0x0626, 0x06C6,
+ /* 3648 */ 0x0626, 0x06C6,
+ /* 3650 */ 0x0626, 0x06C8,
+ /* 3652 */ 0x0626, 0x06C8,
+ /* 3654 */ 0x0626, 0x06D0,
+ /* 3656 */ 0x0626, 0x06D0,
+ /* 3658 */ 0x0626, 0x06D0,
+ /* 3660 */ 0x0626, 0x0649,
+ /* 3662 */ 0x0626, 0x0649,
+ /* 3664 */ 0x0626, 0x0649,
+ /* 3666 */ 0x0626, 0x062C,
+ /* 3668 */ 0x0626, 0x062D,
+ /* 3670 */ 0x0626, 0x0645,
+ /* 3672 */ 0x0626, 0x0649,
+ /* 3674 */ 0x0626, 0x064A,
+ /* 3676 */ 0x0628, 0x062C,
+ /* 3678 */ 0x0628, 0x062D,
+ /* 3680 */ 0x0628, 0x062E,
+ /* 3682 */ 0x0628, 0x0645,
+ /* 3684 */ 0x0628, 0x0649,
+ /* 3686 */ 0x0628, 0x064A,
+ /* 3688 */ 0x062A, 0x062C,
+ /* 3690 */ 0x062A, 0x062D,
+ /* 3692 */ 0x062A, 0x062E,
+ /* 3694 */ 0x062A, 0x0645,
+ /* 3696 */ 0x062A, 0x0649,
+ /* 3698 */ 0x062A, 0x064A,
+ /* 3700 */ 0x062B, 0x062C,
+ /* 3702 */ 0x062B, 0x0645,
+ /* 3704 */ 0x062B, 0x0649,
+ /* 3706 */ 0x062B, 0x064A,
+ /* 3708 */ 0x062C, 0x062D,
+ /* 3710 */ 0x062C, 0x0645,
+ /* 3712 */ 0x062D, 0x062C,
+ /* 3714 */ 0x062D, 0x0645,
+ /* 3716 */ 0x062E, 0x062C,
+ /* 3718 */ 0x062E, 0x062D,
+ /* 3720 */ 0x062E, 0x0645,
+ /* 3722 */ 0x0633, 0x062C,
+ /* 3724 */ 0x0633, 0x062D,
+ /* 3726 */ 0x0633, 0x062E,
+ /* 3728 */ 0x0633, 0x0645,
+ /* 3730 */ 0x0635, 0x062D,
+ /* 3732 */ 0x0635, 0x0645,
+ /* 3734 */ 0x0636, 0x062C,
+ /* 3736 */ 0x0636, 0x062D,
+ /* 3738 */ 0x0636, 0x062E,
+ /* 3740 */ 0x0636, 0x0645,
+ /* 3742 */ 0x0637, 0x062D,
+ /* 3744 */ 0x0637, 0x0645,
+ /* 3746 */ 0x0638, 0x0645,
+ /* 3748 */ 0x0639, 0x062C,
+ /* 3750 */ 0x0639, 0x0645,
+ /* 3752 */ 0x063A, 0x062C,
+ /* 3754 */ 0x063A, 0x0645,
+ /* 3756 */ 0x0641, 0x062C,
+ /* 3758 */ 0x0641, 0x062D,
+ /* 3760 */ 0x0641, 0x062E,
+ /* 3762 */ 0x0641, 0x0645,
+ /* 3764 */ 0x0641, 0x0649,
+ /* 3766 */ 0x0641, 0x064A,
+ /* 3768 */ 0x0642, 0x062D,
+ /* 3770 */ 0x0642, 0x0645,
+ /* 3772 */ 0x0642, 0x0649,
+ /* 3774 */ 0x0642, 0x064A,
+ /* 3776 */ 0x0643, 0x0627,
+ /* 3778 */ 0x0643, 0x062C,
+ /* 3780 */ 0x0643, 0x062D,
+ /* 3782 */ 0x0643, 0x062E,
+ /* 3784 */ 0x0643, 0x0644,
+ /* 3786 */ 0x0643, 0x0645,
+ /* 3788 */ 0x0643, 0x0649,
+ /* 3790 */ 0x0643, 0x064A,
+ /* 3792 */ 0x0644, 0x062C,
+ /* 3794 */ 0x0644, 0x062D,
+ /* 3796 */ 0x0644, 0x062E,
+ /* 3798 */ 0x0644, 0x0645,
+ /* 3800 */ 0x0644, 0x0649,
+ /* 3802 */ 0x0644, 0x064A,
+ /* 3804 */ 0x0645, 0x062C,
+ /* 3806 */ 0x0645, 0x062D,
+ /* 3808 */ 0x0645, 0x062E,
+ /* 3810 */ 0x0645, 0x0645,
+ /* 3812 */ 0x0645, 0x0649,
+ /* 3814 */ 0x0645, 0x064A,
+ /* 3816 */ 0x0646, 0x062C,
+ /* 3818 */ 0x0646, 0x062D,
+ /* 3820 */ 0x0646, 0x062E,
+ /* 3822 */ 0x0646, 0x0645,
+ /* 3824 */ 0x0646, 0x0649,
+ /* 3826 */ 0x0646, 0x064A,
+ /* 3828 */ 0x0647, 0x062C,
+ /* 3830 */ 0x0647, 0x0645,
+ /* 3832 */ 0x0647, 0x0649,
+ /* 3834 */ 0x0647, 0x064A,
+ /* 3836 */ 0x064A, 0x062C,
+ /* 3838 */ 0x064A, 0x062D,
+ /* 3840 */ 0x064A, 0x062E,
+ /* 3842 */ 0x064A, 0x0645,
+ /* 3844 */ 0x064A, 0x0649,
+ /* 3846 */ 0x064A, 0x064A,
+ /* 3848 */ 0x0630, 0x0670,
+ /* 3850 */ 0x0631, 0x0670,
+ /* 3852 */ 0x0649, 0x0670,
+ /* 3854 */ 0x0020, 0x064C, 0x0651,
+ /* 3857 */ 0x0020, 0x064D, 0x0651,
+ /* 3860 */ 0x0020, 0x064E, 0x0651,
+ /* 3863 */ 0x0020, 0x064F, 0x0651,
+ /* 3866 */ 0x0020, 0x0650, 0x0651,
+ /* 3869 */ 0x0020, 0x0651, 0x0670,
+ /* 3872 */ 0x0626, 0x0631,
+ /* 3874 */ 0x0626, 0x0632,
+ /* 3876 */ 0x0626, 0x0645,
+ /* 3878 */ 0x0626, 0x0646,
+ /* 3880 */ 0x0626, 0x0649,
+ /* 3882 */ 0x0626, 0x064A,
+ /* 3884 */ 0x0628, 0x0631,
+ /* 3886 */ 0x0628, 0x0632,
+ /* 3888 */ 0x0628, 0x0645,
+ /* 3890 */ 0x0628, 0x0646,
+ /* 3892 */ 0x0628, 0x0649,
+ /* 3894 */ 0x0628, 0x064A,
+ /* 3896 */ 0x062A, 0x0631,
+ /* 3898 */ 0x062A, 0x0632,
+ /* 3900 */ 0x062A, 0x0645,
+ /* 3902 */ 0x062A, 0x0646,
+ /* 3904 */ 0x062A, 0x0649,
+ /* 3906 */ 0x062A, 0x064A,
+ /* 3908 */ 0x062B, 0x0631,
+ /* 3910 */ 0x062B, 0x0632,
+ /* 3912 */ 0x062B, 0x0645,
+ /* 3914 */ 0x062B, 0x0646,
+ /* 3916 */ 0x062B, 0x0649,
+ /* 3918 */ 0x062B, 0x064A,
+ /* 3920 */ 0x0641, 0x0649,
+ /* 3922 */ 0x0641, 0x064A,
+ /* 3924 */ 0x0642, 0x0649,
+ /* 3926 */ 0x0642, 0x064A,
+ /* 3928 */ 0x0643, 0x0627,
+ /* 3930 */ 0x0643, 0x0644,
+ /* 3932 */ 0x0643, 0x0645,
+ /* 3934 */ 0x0643, 0x0649,
+ /* 3936 */ 0x0643, 0x064A,
+ /* 3938 */ 0x0644, 0x0645,
+ /* 3940 */ 0x0644, 0x0649,
+ /* 3942 */ 0x0644, 0x064A,
+ /* 3944 */ 0x0645, 0x0627,
+ /* 3946 */ 0x0645, 0x0645,
+ /* 3948 */ 0x0646, 0x0631,
+ /* 3950 */ 0x0646, 0x0632,
+ /* 3952 */ 0x0646, 0x0645,
+ /* 3954 */ 0x0646, 0x0646,
+ /* 3956 */ 0x0646, 0x0649,
+ /* 3958 */ 0x0646, 0x064A,
+ /* 3960 */ 0x0649, 0x0670,
+ /* 3962 */ 0x064A, 0x0631,
+ /* 3964 */ 0x064A, 0x0632,
+ /* 3966 */ 0x064A, 0x0645,
+ /* 3968 */ 0x064A, 0x0646,
+ /* 3970 */ 0x064A, 0x0649,
+ /* 3972 */ 0x064A, 0x064A,
+ /* 3974 */ 0x0626, 0x062C,
+ /* 3976 */ 0x0626, 0x062D,
+ /* 3978 */ 0x0626, 0x062E,
+ /* 3980 */ 0x0626, 0x0645,
+ /* 3982 */ 0x0626, 0x0647,
+ /* 3984 */ 0x0628, 0x062C,
+ /* 3986 */ 0x0628, 0x062D,
+ /* 3988 */ 0x0628, 0x062E,
+ /* 3990 */ 0x0628, 0x0645,
+ /* 3992 */ 0x0628, 0x0647,
+ /* 3994 */ 0x062A, 0x062C,
+ /* 3996 */ 0x062A, 0x062D,
+ /* 3998 */ 0x062A, 0x062E,
+ /* 4000 */ 0x062A, 0x0645,
+ /* 4002 */ 0x062A, 0x0647,
+ /* 4004 */ 0x062B, 0x0645,
+ /* 4006 */ 0x062C, 0x062D,
+ /* 4008 */ 0x062C, 0x0645,
+ /* 4010 */ 0x062D, 0x062C,
+ /* 4012 */ 0x062D, 0x0645,
+ /* 4014 */ 0x062E, 0x062C,
+ /* 4016 */ 0x062E, 0x0645,
+ /* 4018 */ 0x0633, 0x062C,
+ /* 4020 */ 0x0633, 0x062D,
+ /* 4022 */ 0x0633, 0x062E,
+ /* 4024 */ 0x0633, 0x0645,
+ /* 4026 */ 0x0635, 0x062D,
+ /* 4028 */ 0x0635, 0x062E,
+ /* 4030 */ 0x0635, 0x0645,
+ /* 4032 */ 0x0636, 0x062C,
+ /* 4034 */ 0x0636, 0x062D,
+ /* 4036 */ 0x0636, 0x062E,
+ /* 4038 */ 0x0636, 0x0645,
+ /* 4040 */ 0x0637, 0x062D,
+ /* 4042 */ 0x0638, 0x0645,
+ /* 4044 */ 0x0639, 0x062C,
+ /* 4046 */ 0x0639, 0x0645,
+ /* 4048 */ 0x063A, 0x062C,
+ /* 4050 */ 0x063A, 0x0645,
+ /* 4052 */ 0x0641, 0x062C,
+ /* 4054 */ 0x0641, 0x062D,
+ /* 4056 */ 0x0641, 0x062E,
+ /* 4058 */ 0x0641, 0x0645,
+ /* 4060 */ 0x0642, 0x062D,
+ /* 4062 */ 0x0642, 0x0645,
+ /* 4064 */ 0x0643, 0x062C,
+ /* 4066 */ 0x0643, 0x062D,
+ /* 4068 */ 0x0643, 0x062E,
+ /* 4070 */ 0x0643, 0x0644,
+ /* 4072 */ 0x0643, 0x0645,
+ /* 4074 */ 0x0644, 0x062C,
+ /* 4076 */ 0x0644, 0x062D,
+ /* 4078 */ 0x0644, 0x062E,
+ /* 4080 */ 0x0644, 0x0645,
+ /* 4082 */ 0x0644, 0x0647,
+ /* 4084 */ 0x0645, 0x062C,
+ /* 4086 */ 0x0645, 0x062D,
+ /* 4088 */ 0x0645, 0x062E,
+ /* 4090 */ 0x0645, 0x0645,
+ /* 4092 */ 0x0646, 0x062C,
+ /* 4094 */ 0x0646, 0x062D,
+ /* 4096 */ 0x0646, 0x062E,
+ /* 4098 */ 0x0646, 0x0645,
+ /* 4100 */ 0x0646, 0x0647,
+ /* 4102 */ 0x0647, 0x062C,
+ /* 4104 */ 0x0647, 0x0645,
+ /* 4106 */ 0x0647, 0x0670,
+ /* 4108 */ 0x064A, 0x062C,
+ /* 4110 */ 0x064A, 0x062D,
+ /* 4112 */ 0x064A, 0x062E,
+ /* 4114 */ 0x064A, 0x0645,
+ /* 4116 */ 0x064A, 0x0647,
+ /* 4118 */ 0x0626, 0x0645,
+ /* 4120 */ 0x0626, 0x0647,
+ /* 4122 */ 0x0628, 0x0645,
+ /* 4124 */ 0x0628, 0x0647,
+ /* 4126 */ 0x062A, 0x0645,
+ /* 4128 */ 0x062A, 0x0647,
+ /* 4130 */ 0x062B, 0x0645,
+ /* 4132 */ 0x062B, 0x0647,
+ /* 4134 */ 0x0633, 0x0645,
+ /* 4136 */ 0x0633, 0x0647,
+ /* 4138 */ 0x0634, 0x0645,
+ /* 4140 */ 0x0634, 0x0647,
+ /* 4142 */ 0x0643, 0x0644,
+ /* 4144 */ 0x0643, 0x0645,
+ /* 4146 */ 0x0644, 0x0645,
+ /* 4148 */ 0x0646, 0x0645,
+ /* 4150 */ 0x0646, 0x0647,
+ /* 4152 */ 0x064A, 0x0645,
+ /* 4154 */ 0x064A, 0x0647,
+ /* 4156 */ 0x0640, 0x064E, 0x0651,
+ /* 4159 */ 0x0640, 0x064F, 0x0651,
+ /* 4162 */ 0x0640, 0x0650, 0x0651,
+ /* 4165 */ 0x0637, 0x0649,
+ /* 4167 */ 0x0637, 0x064A,
+ /* 4169 */ 0x0639, 0x0649,
+ /* 4171 */ 0x0639, 0x064A,
+ /* 4173 */ 0x063A, 0x0649,
+ /* 4175 */ 0x063A, 0x064A,
+ /* 4177 */ 0x0633, 0x0649,
+ /* 4179 */ 0x0633, 0x064A,
+ /* 4181 */ 0x0634, 0x0649,
+ /* 4183 */ 0x0634, 0x064A,
+ /* 4185 */ 0x062D, 0x0649,
+ /* 4187 */ 0x062D, 0x064A,
+ /* 4189 */ 0x062C, 0x0649,
+ /* 4191 */ 0x062C, 0x064A,
+ /* 4193 */ 0x062E, 0x0649,
+ /* 4195 */ 0x062E, 0x064A,
+ /* 4197 */ 0x0635, 0x0649,
+ /* 4199 */ 0x0635, 0x064A,
+ /* 4201 */ 0x0636, 0x0649,
+ /* 4203 */ 0x0636, 0x064A,
+ /* 4205 */ 0x0634, 0x062C,
+ /* 4207 */ 0x0634, 0x062D,
+ /* 4209 */ 0x0634, 0x062E,
+ /* 4211 */ 0x0634, 0x0645,
+ /* 4213 */ 0x0634, 0x0631,
+ /* 4215 */ 0x0633, 0x0631,
+ /* 4217 */ 0x0635, 0x0631,
+ /* 4219 */ 0x0636, 0x0631,
+ /* 4221 */ 0x0637, 0x0649,
+ /* 4223 */ 0x0637, 0x064A,
+ /* 4225 */ 0x0639, 0x0649,
+ /* 4227 */ 0x0639, 0x064A,
+ /* 4229 */ 0x063A, 0x0649,
+ /* 4231 */ 0x063A, 0x064A,
+ /* 4233 */ 0x0633, 0x0649,
+ /* 4235 */ 0x0633, 0x064A,
+ /* 4237 */ 0x0634, 0x0649,
+ /* 4239 */ 0x0634, 0x064A,
+ /* 4241 */ 0x062D, 0x0649,
+ /* 4243 */ 0x062D, 0x064A,
+ /* 4245 */ 0x062C, 0x0649,
+ /* 4247 */ 0x062C, 0x064A,
+ /* 4249 */ 0x062E, 0x0649,
+ /* 4251 */ 0x062E, 0x064A,
+ /* 4253 */ 0x0635, 0x0649,
+ /* 4255 */ 0x0635, 0x064A,
+ /* 4257 */ 0x0636, 0x0649,
+ /* 4259 */ 0x0636, 0x064A,
+ /* 4261 */ 0x0634, 0x062C,
+ /* 4263 */ 0x0634, 0x062D,
+ /* 4265 */ 0x0634, 0x062E,
+ /* 4267 */ 0x0634, 0x0645,
+ /* 4269 */ 0x0634, 0x0631,
+ /* 4271 */ 0x0633, 0x0631,
+ /* 4273 */ 0x0635, 0x0631,
+ /* 4275 */ 0x0636, 0x0631,
+ /* 4277 */ 0x0634, 0x062C,
+ /* 4279 */ 0x0634, 0x062D,
+ /* 4281 */ 0x0634, 0x062E,
+ /* 4283 */ 0x0634, 0x0645,
+ /* 4285 */ 0x0633, 0x0647,
+ /* 4287 */ 0x0634, 0x0647,
+ /* 4289 */ 0x0637, 0x0645,
+ /* 4291 */ 0x0633, 0x062C,
+ /* 4293 */ 0x0633, 0x062D,
+ /* 4295 */ 0x0633, 0x062E,
+ /* 4297 */ 0x0634, 0x062C,
+ /* 4299 */ 0x0634, 0x062D,
+ /* 4301 */ 0x0634, 0x062E,
+ /* 4303 */ 0x0637, 0x0645,
+ /* 4305 */ 0x0638, 0x0645,
+ /* 4307 */ 0x0627, 0x064B,
+ /* 4309 */ 0x0627, 0x064B,
+ /* 4311 */ 0x062A, 0x062C, 0x0645,
+ /* 4314 */ 0x062A, 0x062D, 0x062C,
+ /* 4317 */ 0x062A, 0x062D, 0x062C,
+ /* 4320 */ 0x062A, 0x062D, 0x0645,
+ /* 4323 */ 0x062A, 0x062E, 0x0645,
+ /* 4326 */ 0x062A, 0x0645, 0x062C,
+ /* 4329 */ 0x062A, 0x0645, 0x062D,
+ /* 4332 */ 0x062A, 0x0645, 0x062E,
+ /* 4335 */ 0x062C, 0x0645, 0x062D,
+ /* 4338 */ 0x062C, 0x0645, 0x062D,
+ /* 4341 */ 0x062D, 0x0645, 0x064A,
+ /* 4344 */ 0x062D, 0x0645, 0x0649,
+ /* 4347 */ 0x0633, 0x062D, 0x062C,
+ /* 4350 */ 0x0633, 0x062C, 0x062D,
+ /* 4353 */ 0x0633, 0x062C, 0x0649,
+ /* 4356 */ 0x0633, 0x0645, 0x062D,
+ /* 4359 */ 0x0633, 0x0645, 0x062D,
+ /* 4362 */ 0x0633, 0x0645, 0x062C,
+ /* 4365 */ 0x0633, 0x0645, 0x0645,
+ /* 4368 */ 0x0633, 0x0645, 0x0645,
+ /* 4371 */ 0x0635, 0x062D, 0x062D,
+ /* 4374 */ 0x0635, 0x062D, 0x062D,
+ /* 4377 */ 0x0635, 0x0645, 0x0645,
+ /* 4380 */ 0x0634, 0x062D, 0x0645,
+ /* 4383 */ 0x0634, 0x062D, 0x0645,
+ /* 4386 */ 0x0634, 0x062C, 0x064A,
+ /* 4389 */ 0x0634, 0x0645, 0x062E,
+ /* 4392 */ 0x0634, 0x0645, 0x062E,
+ /* 4395 */ 0x0634, 0x0645, 0x0645,
+ /* 4398 */ 0x0634, 0x0645, 0x0645,
+ /* 4401 */ 0x0636, 0x062D, 0x0649,
+ /* 4404 */ 0x0636, 0x062E, 0x0645,
+ /* 4407 */ 0x0636, 0x062E, 0x0645,
+ /* 4410 */ 0x0637, 0x0645, 0x062D,
+ /* 4413 */ 0x0637, 0x0645, 0x062D,
+ /* 4416 */ 0x0637, 0x0645, 0x0645,
+ /* 4419 */ 0x0637, 0x0645, 0x064A,
+ /* 4422 */ 0x0639, 0x062C, 0x0645,
+ /* 4425 */ 0x0639, 0x0645, 0x0645,
+ /* 4428 */ 0x0639, 0x0645, 0x0645,
+ /* 4431 */ 0x0639, 0x0645, 0x0649,
+ /* 4434 */ 0x063A, 0x0645, 0x0645,
+ /* 4437 */ 0x063A, 0x0645, 0x064A,
+ /* 4440 */ 0x063A, 0x0645, 0x0649,
+ /* 4443 */ 0x0641, 0x062E, 0x0645,
+ /* 4446 */ 0x0641, 0x062E, 0x0645,
+ /* 4449 */ 0x0642, 0x0645, 0x062D,
+ /* 4452 */ 0x0642, 0x0645, 0x0645,
+ /* 4455 */ 0x0644, 0x062D, 0x0645,
+ /* 4458 */ 0x0644, 0x062D, 0x064A,
+ /* 4461 */ 0x0644, 0x062D, 0x0649,
+ /* 4464 */ 0x0644, 0x062C, 0x062C,
+ /* 4467 */ 0x0644, 0x062C, 0x062C,
+ /* 4470 */ 0x0644, 0x062E, 0x0645,
+ /* 4473 */ 0x0644, 0x062E, 0x0645,
+ /* 4476 */ 0x0644, 0x0645, 0x062D,
+ /* 4479 */ 0x0644, 0x0645, 0x062D,
+ /* 4482 */ 0x0645, 0x062D, 0x062C,
+ /* 4485 */ 0x0645, 0x062D, 0x0645,
+ /* 4488 */ 0x0645, 0x062D, 0x064A,
+ /* 4491 */ 0x0645, 0x062C, 0x062D,
+ /* 4494 */ 0x0645, 0x062C, 0x0645,
+ /* 4497 */ 0x0645, 0x062E, 0x062C,
+ /* 4500 */ 0x0645, 0x062E, 0x0645,
+ /* 4503 */ 0x0645, 0x062C, 0x062E,
+ /* 4506 */ 0x0647, 0x0645, 0x062C,
+ /* 4509 */ 0x0647, 0x0645, 0x0645,
+ /* 4512 */ 0x0646, 0x062D, 0x0645,
+ /* 4515 */ 0x0646, 0x062D, 0x0649,
+ /* 4518 */ 0x0646, 0x062C, 0x0645,
+ /* 4521 */ 0x0646, 0x062C, 0x0645,
+ /* 4524 */ 0x0646, 0x062C, 0x0649,
+ /* 4527 */ 0x0646, 0x0645, 0x064A,
+ /* 4530 */ 0x0646, 0x0645, 0x0649,
+ /* 4533 */ 0x064A, 0x0645, 0x0645,
+ /* 4536 */ 0x064A, 0x0645, 0x0645,
+ /* 4539 */ 0x0628, 0x062E, 0x064A,
+ /* 4542 */ 0x062A, 0x062C, 0x064A,
+ /* 4545 */ 0x062A, 0x062C, 0x0649,
+ /* 4548 */ 0x062A, 0x062E, 0x064A,
+ /* 4551 */ 0x062A, 0x062E, 0x0649,
+ /* 4554 */ 0x062A, 0x0645, 0x064A,
+ /* 4557 */ 0x062A, 0x0645, 0x0649,
+ /* 4560 */ 0x062C, 0x0645, 0x064A,
+ /* 4563 */ 0x062C, 0x062D, 0x0649,
+ /* 4566 */ 0x062C, 0x0645, 0x0649,
+ /* 4569 */ 0x0633, 0x062E, 0x0649,
+ /* 4572 */ 0x0635, 0x062D, 0x064A,
+ /* 4575 */ 0x0634, 0x062D, 0x064A,
+ /* 4578 */ 0x0636, 0x062D, 0x064A,
+ /* 4581 */ 0x0644, 0x062C, 0x064A,
+ /* 4584 */ 0x0644, 0x0645, 0x064A,
+ /* 4587 */ 0x064A, 0x062D, 0x064A,
+ /* 4590 */ 0x064A, 0x062C, 0x064A,
+ /* 4593 */ 0x064A, 0x0645, 0x064A,
+ /* 4596 */ 0x0645, 0x0645, 0x064A,
+ /* 4599 */ 0x0642, 0x0645, 0x064A,
+ /* 4602 */ 0x0646, 0x062D, 0x064A,
+ /* 4605 */ 0x0642, 0x0645, 0x062D,
+ /* 4608 */ 0x0644, 0x062D, 0x0645,
+ /* 4611 */ 0x0639, 0x0645, 0x064A,
+ /* 4614 */ 0x0643, 0x0645, 0x064A,
+ /* 4617 */ 0x0646, 0x062C, 0x062D,
+ /* 4620 */ 0x0645, 0x062E, 0x064A,
+ /* 4623 */ 0x0644, 0x062C, 0x0645,
+ /* 4626 */ 0x0643, 0x0645, 0x0645,
+ /* 4629 */ 0x0644, 0x062C, 0x0645,
+ /* 4632 */ 0x0646, 0x062C, 0x062D,
+ /* 4635 */ 0x062C, 0x062D, 0x064A,
+ /* 4638 */ 0x062D, 0x062C, 0x064A,
+ /* 4641 */ 0x0645, 0x062C, 0x064A,
+ /* 4644 */ 0x0641, 0x0645, 0x064A,
+ /* 4647 */ 0x0628, 0x062D, 0x064A,
+ /* 4650 */ 0x0643, 0x0645, 0x0645,
+ /* 4653 */ 0x0639, 0x062C, 0x0645,
+ /* 4656 */ 0x0635, 0x0645, 0x0645,
+ /* 4659 */ 0x0633, 0x062E, 0x064A,
+ /* 4662 */ 0x0646, 0x062C, 0x064A,
+ /* 4665 */ 0x0635, 0x0644, 0x06D2,
+ /* 4668 */ 0x0642, 0x0644, 0x06D2,
+ /* 4671 */ 0x0627, 0x0644, 0x0644, 0x0647,
+ /* 4675 */ 0x0627, 0x0643, 0x0628, 0x0631,
+ /* 4679 */ 0x0645, 0x062D, 0x0645, 0x062F,
+ /* 4683 */ 0x0635, 0x0644, 0x0639, 0x0645,
+ /* 4687 */ 0x0631, 0x0633, 0x0648, 0x0644,
+ /* 4691 */ 0x0639, 0x0644, 0x064A, 0x0647,
+ /* 4695 */ 0x0648, 0x0633, 0x0644, 0x0645,
+ /* 4699 */ 0x0635, 0x0644, 0x0649,
+ /* 4702 */ 0x0635, 0x0644, 0x0649, 0x0020, 0x0627, 0x0644, 0x0644, 0x0647, 0x0020, 0x0639, 0x0644, 0x064A, 0x0647, 0x0020, 0x0648, 0x0633, 0x0644, 0x0645,
+ /* 4720 */ 0x062C, 0x0644, 0x0020, 0x062C, 0x0644, 0x0627, 0x0644, 0x0647,
+ /* 4728 */ 0x0631, 0x06CC, 0x0627, 0x0644,
+ /* 4732 */ 0x0020, 0x064B,
+ /* 4734 */ 0x0640, 0x064B,
+ /* 4736 */ 0x0020, 0x064C,
+ /* 4738 */ 0x0020, 0x064D,
+ /* 4740 */ 0x0020, 0x064E,
+ /* 4742 */ 0x0640, 0x064E,
+ /* 4744 */ 0x0020, 0x064F,
+ /* 4746 */ 0x0640, 0x064F,
+ /* 4748 */ 0x0020, 0x0650,
+ /* 4750 */ 0x0640, 0x0650,
+ /* 4752 */ 0x0020, 0x0651,
+ /* 4754 */ 0x0640, 0x0651,
+ /* 4756 */ 0x0020, 0x0652,
+ /* 4758 */ 0x0640, 0x0652,
+ /* 4760 */ 0x0644, 0x0622,
+ /* 4762 */ 0x0644, 0x0622,
+ /* 4764 */ 0x0644, 0x0623,
+ /* 4766 */ 0x0644, 0x0623,
+ /* 4768 */ 0x0644, 0x0625,
+ /* 4770 */ 0x0644, 0x0625,
+ /* 4772 */ 0x0644, 0x0627,
+ /* 4774 */ 0x0644, 0x0627,
+ /* 4776 */ 0x1DF04,
+ /* 4777 */ 0x1DF05,
+ /* 4778 */ 0x1DF06,
+ /* 4779 */ 0x1DF08,
+ /* 4780 */ 0x1DF0A,
+ /* 4781 */ 0x1DF1E,
+ /* 4782 */ 0x11099, 0x110BA,
+ /* 4784 */ 0x1109B, 0x110BA,
+ /* 4786 */ 0x110A5, 0x110BA,
+ /* 4788 */ 0x11131, 0x11127,
+ /* 4790 */ 0x11132, 0x11127,
+ /* 4792 */ 0x11347, 0x1133E,
+ /* 4794 */ 0x11347, 0x11357,
+ /* 4796 */ 0x114B9, 0x114BA,
+ /* 4798 */ 0x114B9, 0x114B0,
+ /* 4800 */ 0x114B9, 0x114BD,
+ /* 4802 */ 0x115B8, 0x115AF,
+ /* 4804 */ 0x115B9, 0x115AF,
+ /* 4806 */ 0x11935, 0x11930,
+ /* 4808 */ 0x1D157, 0x1D165,
+ /* 4810 */ 0x1D158, 0x1D165,
+ /* 4812 */ 0x1D15F, 0x1D16E,
+ /* 4814 */ 0x1D15F, 0x1D16F,
+ /* 4816 */ 0x1D15F, 0x1D170,
+ /* 4818 */ 0x1D15F, 0x1D171,
+ /* 4820 */ 0x1D15F, 0x1D172,
+ /* 4822 */ 0x1D1B9, 0x1D165,
+ /* 4824 */ 0x1D1BA, 0x1D165,
+ /* 4826 */ 0x1D1BB, 0x1D16E,
+ /* 4828 */ 0x1D1BC, 0x1D16E,
+ /* 4830 */ 0x1D1BB, 0x1D16F,
+ /* 4832 */ 0x1D1BC, 0x1D16F,
+ /* 4834 */ 0x0030, 0x002E,
+ /* 4836 */ 0x0030, 0x002C,
+ /* 4838 */ 0x0031, 0x002C,
+ /* 4840 */ 0x0032, 0x002C,
+ /* 4842 */ 0x0033, 0x002C,
+ /* 4844 */ 0x0034, 0x002C,
+ /* 4846 */ 0x0035, 0x002C,
+ /* 4848 */ 0x0036, 0x002C,
+ /* 4850 */ 0x0037, 0x002C,
+ /* 4852 */ 0x0038, 0x002C,
+ /* 4854 */ 0x0039, 0x002C,
+ /* 4856 */ 0x0028, 0x0041, 0x0029,
+ /* 4859 */ 0x0028, 0x0042, 0x0029,
+ /* 4862 */ 0x0028, 0x0043, 0x0029,
+ /* 4865 */ 0x0028, 0x0044, 0x0029,
+ /* 4868 */ 0x0028, 0x0045, 0x0029,
+ /* 4871 */ 0x0028, 0x0046, 0x0029,
+ /* 4874 */ 0x0028, 0x0047, 0x0029,
+ /* 4877 */ 0x0028, 0x0048, 0x0029,
+ /* 4880 */ 0x0028, 0x0049, 0x0029,
+ /* 4883 */ 0x0028, 0x004A, 0x0029,
+ /* 4886 */ 0x0028, 0x004B, 0x0029,
+ /* 4889 */ 0x0028, 0x004C, 0x0029,
+ /* 4892 */ 0x0028, 0x004D, 0x0029,
+ /* 4895 */ 0x0028, 0x004E, 0x0029,
+ /* 4898 */ 0x0028, 0x004F, 0x0029,
+ /* 4901 */ 0x0028, 0x0050, 0x0029,
+ /* 4904 */ 0x0028, 0x0051, 0x0029,
+ /* 4907 */ 0x0028, 0x0052, 0x0029,
+ /* 4910 */ 0x0028, 0x0053, 0x0029,
+ /* 4913 */ 0x0028, 0x0054, 0x0029,
+ /* 4916 */ 0x0028, 0x0055, 0x0029,
+ /* 4919 */ 0x0028, 0x0056, 0x0029,
+ /* 4922 */ 0x0028, 0x0057, 0x0029,
+ /* 4925 */ 0x0028, 0x0058, 0x0029,
+ /* 4928 */ 0x0028, 0x0059, 0x0029,
+ /* 4931 */ 0x0028, 0x005A, 0x0029,
+ /* 4934 */ 0x3014, 0x0053, 0x3015,
+ /* 4937 */ 0x0043, 0x0044,
+ /* 4939 */ 0x0057, 0x005A,
+ /* 4941 */ 0x0048, 0x0056,
+ /* 4943 */ 0x004D, 0x0056,
+ /* 4945 */ 0x0053, 0x0044,
+ /* 4947 */ 0x0053, 0x0053,
+ /* 4949 */ 0x0050, 0x0050, 0x0056,
+ /* 4952 */ 0x0057, 0x0043,
+ /* 4954 */ 0x004D, 0x0043,
+ /* 4956 */ 0x004D, 0x0044,
+ /* 4958 */ 0x004D, 0x0052,
+ /* 4960 */ 0x0044, 0x004A,
+ /* 4962 */ 0x307B, 0x304B,
+ /* 4964 */ 0x30B3, 0x30B3,
+ /* 4966 */ 0x3014, 0x672C, 0x3015,
+ /* 4969 */ 0x3014, 0x4E09, 0x3015,
+ /* 4972 */ 0x3014, 0x4E8C, 0x3015,
+ /* 4975 */ 0x3014, 0x5B89, 0x3015,
+ /* 4978 */ 0x3014, 0x70B9, 0x3015,
+ /* 4981 */ 0x3014, 0x6253, 0x3015,
+ /* 4984 */ 0x3014, 0x76D7, 0x3015,
+ /* 4987 */ 0x3014, 0x52DD, 0x3015,
+ /* 4990 */ 0x3014, 0x6557, 0x3015,
+ /* 4993 */ 0x20122,
+ /* 4994 */ 0x2063A,
+ /* 4995 */ 0x2051C,
+ /* 4996 */ 0x2054B,
+ /* 4997 */ 0x291DF,
+ /* 4998 */ 0x20A2C,
+ /* 4999 */ 0x20B63,
+ /* 5000 */ 0x214E4,
+ /* 5001 */ 0x216A8,
+ /* 5002 */ 0x216EA,
+ /* 5003 */ 0x219C8,
+ /* 5004 */ 0x21B18,
+ /* 5005 */ 0x21DE4,
+ /* 5006 */ 0x21DE6,
+ /* 5007 */ 0x22183,
+ /* 5008 */ 0x2A392,
+ /* 5009 */ 0x22331,
+ /* 5010 */ 0x22331,
+ /* 5011 */ 0x232B8,
+ /* 5012 */ 0x261DA,
+ /* 5013 */ 0x226D4,
+ /* 5014 */ 0x22B0C,
+ /* 5015 */ 0x22BF1,
+ /* 5016 */ 0x2300A,
+ /* 5017 */ 0x233C3,
+ /* 5018 */ 0x2346D,
+ /* 5019 */ 0x236A3,
+ /* 5020 */ 0x238A7,
+ /* 5021 */ 0x23A8D,
+ /* 5022 */ 0x21D0B,
+ /* 5023 */ 0x23AFA,
+ /* 5024 */ 0x23CBC,
+ /* 5025 */ 0x23D1E,
+ /* 5026 */ 0x23ED1,
+ /* 5027 */ 0x23F5E,
+ /* 5028 */ 0x23F8E,
+ /* 5029 */ 0x20525,
+ /* 5030 */ 0x24263,
+ /* 5031 */ 0x243AB,
+ /* 5032 */ 0x24608,
+ /* 5033 */ 0x24735,
+ /* 5034 */ 0x24814,
+ /* 5035 */ 0x24C36,
+ /* 5036 */ 0x24C92,
+ /* 5037 */ 0x2219F,
+ /* 5038 */ 0x24FA1,
+ /* 5039 */ 0x24FB8,
+ /* 5040 */ 0x25044,
+ /* 5041 */ 0x250F3,
+ /* 5042 */ 0x250F2,
+ /* 5043 */ 0x25119,
+ /* 5044 */ 0x25133,
+ /* 5045 */ 0x2541D,
+ /* 5046 */ 0x25626,
+ /* 5047 */ 0x2569A,
+ /* 5048 */ 0x256C5,
+ /* 5049 */ 0x2597C,
+ /* 5050 */ 0x25AA7,
+ /* 5051 */ 0x25AA7,
+ /* 5052 */ 0x25BAB,
+ /* 5053 */ 0x25C80,
+ /* 5054 */ 0x25F86,
+ /* 5055 */ 0x26228,
+ /* 5056 */ 0x26247,
+ /* 5057 */ 0x262D9,
+ /* 5058 */ 0x2633E,
+ /* 5059 */ 0x264DA,
+ /* 5060 */ 0x26523,
+ /* 5061 */ 0x265A8,
+ /* 5062 */ 0x2335F,
+ /* 5063 */ 0x267A7,
+ /* 5064 */ 0x267B5,
+ /* 5065 */ 0x23393,
+ /* 5066 */ 0x2339C,
+ /* 5067 */ 0x26B3C,
+ /* 5068 */ 0x26C36,
+ /* 5069 */ 0x26D6B,
+ /* 5070 */ 0x26CD5,
+ /* 5071 */ 0x273CA,
+ /* 5072 */ 0x26F2C,
+ /* 5073 */ 0x26FB1,
+ /* 5074 */ 0x270D2,
+ /* 5075 */ 0x27667,
+ /* 5076 */ 0x278AE,
+ /* 5077 */ 0x27966,
+ /* 5078 */ 0x27CA8,
+ /* 5079 */ 0x27F2F,
+ /* 5080 */ 0x20804,
+ /* 5081 */ 0x208DE,
+ /* 5082 */ 0x285D2,
+ /* 5083 */ 0x285ED,
+ /* 5084 */ 0x2872E,
+ /* 5085 */ 0x28BFA,
+ /* 5086 */ 0x28D77,
+ /* 5087 */ 0x29145,
+ /* 5088 */ 0x2921A,
+ /* 5089 */ 0x2940A,
+ /* 5090 */ 0x29496,
+ /* 5091 */ 0x295B6,
+ /* 5092 */ 0x29B30,
+ /* 5093 */ 0x2A0CE,
+ /* 5094 */ 0x2A105,
+ /* 5095 */ 0x2A20E,
+ /* 5096 */ 0x2A291,
+ /* 5097 */ 0x2A600
+};
diff --git a/contrib/libs/libpq/src/include/common/username.h b/contrib/libs/libpq/src/include/common/username.h
new file mode 100644
index 0000000000..fd07df64c1
--- /dev/null
+++ b/contrib/libs/libpq/src/include/common/username.h
@@ -0,0 +1,15 @@
+/*
+ * username.h
+ * lookup effective username
+ *
+ * Copyright (c) 2003-2023, PostgreSQL Global Development Group
+ *
+ * src/include/common/username.h
+ */
+#ifndef USERNAME_H
+#define USERNAME_H
+
+extern const char *get_user_name(char **errstr);
+extern const char *get_user_name_or_exit(const char *progname);
+
+#endif /* USERNAME_H */
diff --git a/contrib/libs/libpq/src/include/datatype/timestamp.h b/contrib/libs/libpq/src/include/datatype/timestamp.h
new file mode 100644
index 0000000000..ab8ccf89ca
--- /dev/null
+++ b/contrib/libs/libpq/src/include/datatype/timestamp.h
@@ -0,0 +1,243 @@
+/*-------------------------------------------------------------------------
+ *
+ * timestamp.h
+ * Timestamp and Interval typedefs and related macros.
+ *
+ * Note: this file must be includable in both frontend and backend contexts.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/datatype/timestamp.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef DATATYPE_TIMESTAMP_H
+#define DATATYPE_TIMESTAMP_H
+
+/*
+ * Timestamp represents absolute time.
+ *
+ * Interval represents delta time. Keep track of months (and years), days,
+ * and hours/minutes/seconds separately since the elapsed time spanned is
+ * unknown until instantiated relative to an absolute time.
+ *
+ * Note that Postgres uses "time interval" to mean a bounded interval,
+ * consisting of a beginning and ending time, not a time span - thomas 97/03/20
+ *
+ * Timestamps, as well as the h/m/s fields of intervals, are stored as
+ * int64 values with units of microseconds. (Once upon a time they were
+ * double values with units of seconds.)
+ *
+ * TimeOffset and fsec_t are convenience typedefs for temporary variables.
+ * Do not use fsec_t in values stored on-disk.
+ * Also, fsec_t is only meant for *fractional* seconds; beware of overflow
+ * if the value you need to store could be many seconds.
+ */
+
+typedef int64 Timestamp;
+typedef int64 TimestampTz;
+typedef int64 TimeOffset;
+typedef int32 fsec_t; /* fractional seconds (in microseconds) */
+
+
+/*
+ * Storage format for type interval.
+ */
+typedef struct
+{
+ TimeOffset time; /* all time units other than days, months and
+ * years */
+ int32 day; /* days, after time for alignment */
+ int32 month; /* months and years, after time for alignment */
+} Interval;
+
+/*
+ * Data structure representing a broken-down interval.
+ *
+ * For historical reasons, this is modeled on struct pg_tm for timestamps.
+ * Unlike the situation for timestamps, there's no magic interpretation
+ * needed for months or years: they're just zero or not. Note that fields
+ * can be negative; however, because of the divisions done while converting
+ * from struct Interval, only tm_mday could be INT_MIN. This is important
+ * because we may need to negate the values in some code paths.
+ */
+struct pg_itm
+{
+ int tm_usec;
+ int tm_sec;
+ int tm_min;
+ int64 tm_hour; /* needs to be wide */
+ int tm_mday;
+ int tm_mon;
+ int tm_year;
+};
+
+/*
+ * Data structure for decoding intervals. We could just use struct pg_itm,
+ * but then the requirement for tm_usec to be 64 bits would propagate to
+ * places where it's not really needed. Also, omitting the fields that
+ * aren't used during decoding seems like a good error-prevention measure.
+ */
+struct pg_itm_in
+{
+ int64 tm_usec; /* needs to be wide */
+ int tm_mday;
+ int tm_mon;
+ int tm_year;
+};
+
+
+/* Limits on the "precision" option (typmod) for these data types */
+#define MAX_TIMESTAMP_PRECISION 6
+#define MAX_INTERVAL_PRECISION 6
+
+/*
+ * Round off to MAX_TIMESTAMP_PRECISION decimal places.
+ * Note: this is also used for rounding off intervals.
+ */
+#define TS_PREC_INV 1000000.0
+#define TSROUND(j) (rint(((double) (j)) * TS_PREC_INV) / TS_PREC_INV)
+
+
+/*
+ * Assorted constants for datetime-related calculations
+ */
+
+#define DAYS_PER_YEAR 365.25 /* assumes leap year every four years */
+#define MONTHS_PER_YEAR 12
+/*
+ * DAYS_PER_MONTH is very imprecise. The more accurate value is
+ * 365.2425/12 = 30.436875, or '30 days 10:29:06'. Right now we only
+ * return an integral number of days, but someday perhaps we should
+ * also return a 'time' value to be used as well. ISO 8601 suggests
+ * 30 days.
+ */
+#define DAYS_PER_MONTH 30 /* assumes exactly 30 days per month */
+#define HOURS_PER_DAY 24 /* assume no daylight savings time changes */
+
+/*
+ * This doesn't adjust for uneven daylight savings time intervals or leap
+ * seconds, and it crudely estimates leap years. A more accurate value
+ * for days per years is 365.2422.
+ */
+#define SECS_PER_YEAR (36525 * 864) /* avoid floating-point computation */
+#define SECS_PER_DAY 86400
+#define SECS_PER_HOUR 3600
+#define SECS_PER_MINUTE 60
+#define MINS_PER_HOUR 60
+
+#define USECS_PER_DAY INT64CONST(86400000000)
+#define USECS_PER_HOUR INT64CONST(3600000000)
+#define USECS_PER_MINUTE INT64CONST(60000000)
+#define USECS_PER_SEC INT64CONST(1000000)
+
+/*
+ * We allow numeric timezone offsets up to 15:59:59 either way from Greenwich.
+ * Currently, the record holders for wackiest offsets in actual use are zones
+ * Asia/Manila, at -15:56:00 until 1844, and America/Metlakatla, at +15:13:42
+ * until 1867. If we were to reject such values we would fail to dump and
+ * restore old timestamptz values with these zone settings.
+ */
+#define MAX_TZDISP_HOUR 15 /* maximum allowed hour part */
+#define TZDISP_LIMIT ((MAX_TZDISP_HOUR + 1) * SECS_PER_HOUR)
+
+/*
+ * We reserve the minimum and maximum integer values to represent
+ * timestamp (or timestamptz) -infinity and +infinity.
+ */
+#define TIMESTAMP_MINUS_INFINITY PG_INT64_MIN
+#define TIMESTAMP_INFINITY PG_INT64_MAX
+
+/*
+ * Historically these alias for infinity have been used.
+ */
+#define DT_NOBEGIN TIMESTAMP_MINUS_INFINITY
+#define DT_NOEND TIMESTAMP_INFINITY
+
+#define TIMESTAMP_NOBEGIN(j) \
+ do {(j) = DT_NOBEGIN;} while (0)
+
+#define TIMESTAMP_IS_NOBEGIN(j) ((j) == DT_NOBEGIN)
+
+#define TIMESTAMP_NOEND(j) \
+ do {(j) = DT_NOEND;} while (0)
+
+#define TIMESTAMP_IS_NOEND(j) ((j) == DT_NOEND)
+
+#define TIMESTAMP_NOT_FINITE(j) (TIMESTAMP_IS_NOBEGIN(j) || TIMESTAMP_IS_NOEND(j))
+
+
+/*
+ * Julian date support.
+ *
+ * date2j() and j2date() nominally handle the Julian date range 0..INT_MAX,
+ * or 4714-11-24 BC to 5874898-06-03 AD. In practice, date2j() will work and
+ * give correct negative Julian dates for dates before 4714-11-24 BC as well.
+ * We rely on it to do so back to 4714-11-01 BC. Allowing at least one day's
+ * slop is necessary so that timestamp rotation doesn't produce dates that
+ * would be rejected on input. For example, '4714-11-24 00:00 GMT BC' is a
+ * legal timestamptz value, but in zones east of Greenwich it would print as
+ * sometime in the afternoon of 4714-11-23 BC; if we couldn't process such a
+ * date we'd have a dump/reload failure. So the idea is for IS_VALID_JULIAN
+ * to accept a slightly wider range of dates than we really support, and
+ * then we apply the exact checks in IS_VALID_DATE or IS_VALID_TIMESTAMP,
+ * after timezone rotation if any. To save a few cycles, we can make
+ * IS_VALID_JULIAN check only to the month boundary, since its exact cutoffs
+ * are not very critical in this scheme.
+ *
+ * It is correct that JULIAN_MINYEAR is -4713, not -4714; it is defined to
+ * allow easy comparison to tm_year values, in which we follow the convention
+ * that tm_year <= 0 represents abs(tm_year)+1 BC.
+ */
+
+#define JULIAN_MINYEAR (-4713)
+#define JULIAN_MINMONTH (11)
+#define JULIAN_MINDAY (24)
+#define JULIAN_MAXYEAR (5874898)
+#define JULIAN_MAXMONTH (6)
+#define JULIAN_MAXDAY (3)
+
+#define IS_VALID_JULIAN(y,m,d) \
+ (((y) > JULIAN_MINYEAR || \
+ ((y) == JULIAN_MINYEAR && ((m) >= JULIAN_MINMONTH))) && \
+ ((y) < JULIAN_MAXYEAR || \
+ ((y) == JULIAN_MAXYEAR && ((m) < JULIAN_MAXMONTH))))
+
+/* Julian-date equivalents of Day 0 in Unix and Postgres reckoning */
+#define UNIX_EPOCH_JDATE 2440588 /* == date2j(1970, 1, 1) */
+#define POSTGRES_EPOCH_JDATE 2451545 /* == date2j(2000, 1, 1) */
+
+/*
+ * Range limits for dates and timestamps.
+ *
+ * We have traditionally allowed Julian day zero as a valid datetime value,
+ * so that is the lower bound for both dates and timestamps.
+ *
+ * The upper limit for dates is 5874897-12-31, which is a bit less than what
+ * the Julian-date code can allow. For timestamps, the upper limit is
+ * 294276-12-31. The int64 overflow limit would be a few days later; again,
+ * leaving some slop avoids worries about corner-case overflow, and provides
+ * a simpler user-visible definition.
+ */
+
+/* First allowed date, and first disallowed date, in Julian-date form */
+#define DATETIME_MIN_JULIAN (0)
+#define DATE_END_JULIAN (2147483494) /* == date2j(JULIAN_MAXYEAR, 1, 1) */
+#define TIMESTAMP_END_JULIAN (109203528) /* == date2j(294277, 1, 1) */
+
+/* Timestamp limits */
+#define MIN_TIMESTAMP INT64CONST(-211813488000000000)
+/* == (DATETIME_MIN_JULIAN - POSTGRES_EPOCH_JDATE) * USECS_PER_DAY */
+#define END_TIMESTAMP INT64CONST(9223371331200000000)
+/* == (TIMESTAMP_END_JULIAN - POSTGRES_EPOCH_JDATE) * USECS_PER_DAY */
+
+/* Range-check a date (given in Postgres, not Julian, numbering) */
+#define IS_VALID_DATE(d) \
+ ((DATETIME_MIN_JULIAN - POSTGRES_EPOCH_JDATE) <= (d) && \
+ (d) < (DATE_END_JULIAN - POSTGRES_EPOCH_JDATE))
+
+/* Range-check a timestamp */
+#define IS_VALID_TIMESTAMP(t) (MIN_TIMESTAMP <= (t) && (t) < END_TIMESTAMP)
+
+#endif /* DATATYPE_TIMESTAMP_H */
diff --git a/contrib/libs/libpq/src/include/lib/sort_template.h b/contrib/libs/libpq/src/include/lib/sort_template.h
new file mode 100644
index 0000000000..1edd05c7d3
--- /dev/null
+++ b/contrib/libs/libpq/src/include/lib/sort_template.h
@@ -0,0 +1,432 @@
+/*-------------------------------------------------------------------------
+ *
+ * sort_template.h
+ *
+ * A template for a sort algorithm that supports varying degrees of
+ * specialization.
+ *
+ * Copyright (c) 2021-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1992-1994, Regents of the University of California
+ *
+ * Usage notes:
+ *
+ * To generate functions specialized for a type, the following parameter
+ * macros should be #define'd before this file is included.
+ *
+ * - ST_SORT - the name of a sort function to be generated
+ * - ST_ELEMENT_TYPE - type of the referenced elements
+ * - ST_DECLARE - if defined the functions and types are declared
+ * - ST_DEFINE - if defined the functions and types are defined
+ * - ST_SCOPE - scope (e.g. extern, static inline) for functions
+ * - ST_CHECK_FOR_INTERRUPTS - if defined the sort is interruptible
+ *
+ * Instead of ST_ELEMENT_TYPE, ST_ELEMENT_TYPE_VOID can be defined. Then
+ * the generated functions will automatically gain an "element_size"
+ * parameter. This allows us to generate a traditional qsort function.
+ *
+ * One of the following macros must be defined, to show how to compare
+ * elements. The first two options are arbitrary expressions depending
+ * on whether an extra pass-through argument is desired, and the third
+ * option should be defined if the sort function should receive a
+ * function pointer at runtime.
+ *
+ * - ST_COMPARE(a, b) - a simple comparison expression
+ * - ST_COMPARE(a, b, arg) - variant that takes an extra argument
+ * - ST_COMPARE_RUNTIME_POINTER - sort function takes a function pointer
+ *
+ * To say that the comparator and therefore also sort function should
+ * receive an extra pass-through argument, specify the type of the
+ * argument.
+ *
+ * - ST_COMPARE_ARG_TYPE - type of extra argument
+ *
+ * The prototype of the generated sort function is:
+ *
+ * void ST_SORT(ST_ELEMENT_TYPE *data, size_t n,
+ * [size_t element_size,]
+ * [ST_SORT_compare_function compare,]
+ * [ST_COMPARE_ARG_TYPE *arg]);
+ *
+ * ST_SORT_compare_function is a function pointer of the following type:
+ *
+ * int (*)(const ST_ELEMENT_TYPE *a, const ST_ELEMENT_TYPE *b,
+ * [ST_COMPARE_ARG_TYPE *arg])
+ *
+ * HISTORY
+ *
+ * Modifications from vanilla NetBSD source:
+ * - Add do ... while() macro fix
+ * - Remove __inline, _DIAGASSERTs, __P
+ * - Remove ill-considered "swap_cnt" switch to insertion sort, in favor
+ * of a simple check for presorted input.
+ * - Take care to recurse on the smaller partition, to bound stack usage
+ * - Convert into a header that can generate specialized functions
+ *
+ * IDENTIFICATION
+ * src/include/lib/sort_template.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/* $NetBSD: qsort.c,v 1.13 2003/08/07 16:43:42 agc Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Qsort routine based on J. L. Bentley and M. D. McIlroy,
+ * "Engineering a sort function",
+ * Software--Practice and Experience 23 (1993) 1249-1265.
+ *
+ * We have modified their original by adding a check for already-sorted
+ * input, which seems to be a win per discussions on pgsql-hackers around
+ * 2006-03-21.
+ *
+ * Also, we recurse on the smaller partition and iterate on the larger one,
+ * which ensures we cannot recurse more than log(N) levels (since the
+ * partition recursed to is surely no more than half of the input). Bentley
+ * and McIlroy explicitly rejected doing this on the grounds that it's "not
+ * worth the effort", but we have seen crashes in the field due to stack
+ * overrun, so that judgment seems wrong.
+ */
+
+#define ST_MAKE_PREFIX(a) CppConcat(a,_)
+#define ST_MAKE_NAME(a,b) ST_MAKE_NAME_(ST_MAKE_PREFIX(a),b)
+#define ST_MAKE_NAME_(a,b) CppConcat(a,b)
+
+/*
+ * If the element type is void, we'll also need an element_size argument
+ * because we don't know the size.
+ */
+#ifdef ST_ELEMENT_TYPE_VOID
+#define ST_ELEMENT_TYPE void
+#define ST_SORT_PROTO_ELEMENT_SIZE , size_t element_size
+#define ST_SORT_INVOKE_ELEMENT_SIZE , element_size
+#else
+#define ST_SORT_PROTO_ELEMENT_SIZE
+#define ST_SORT_INVOKE_ELEMENT_SIZE
+#endif
+
+/*
+ * If the user wants to be able to pass in compare functions at runtime,
+ * we'll need to make that an argument of the sort and med3 functions.
+ */
+#ifdef ST_COMPARE_RUNTIME_POINTER
+/*
+ * The type of the comparator function pointer that ST_SORT will take, unless
+ * you've already declared a type name manually and want to use that instead of
+ * having a new one defined.
+ */
+#ifndef ST_COMPARATOR_TYPE_NAME
+#define ST_COMPARATOR_TYPE_NAME ST_MAKE_NAME(ST_SORT, compare_function)
+#endif
+#define ST_COMPARE compare
+#ifndef ST_COMPARE_ARG_TYPE
+#define ST_SORT_PROTO_COMPARE , ST_COMPARATOR_TYPE_NAME compare
+#define ST_SORT_INVOKE_COMPARE , compare
+#else
+#define ST_SORT_PROTO_COMPARE , ST_COMPARATOR_TYPE_NAME compare
+#define ST_SORT_INVOKE_COMPARE , compare
+#endif
+#else
+#define ST_SORT_PROTO_COMPARE
+#define ST_SORT_INVOKE_COMPARE
+#endif
+
+/*
+ * If the user wants to use a compare function or expression that takes an
+ * extra argument, we'll need to make that an argument of the sort, compare and
+ * med3 functions.
+ */
+#ifdef ST_COMPARE_ARG_TYPE
+#define ST_SORT_PROTO_ARG , ST_COMPARE_ARG_TYPE *arg
+#define ST_SORT_INVOKE_ARG , arg
+#else
+#define ST_SORT_PROTO_ARG
+#define ST_SORT_INVOKE_ARG
+#endif
+
+#ifdef ST_DECLARE
+
+#ifdef ST_COMPARE_RUNTIME_POINTER
+typedef int (*ST_COMPARATOR_TYPE_NAME) (const ST_ELEMENT_TYPE *,
+ const ST_ELEMENT_TYPE * ST_SORT_PROTO_ARG);
+#endif
+
+/* Declare the sort function. Note optional arguments at end. */
+ST_SCOPE void ST_SORT(ST_ELEMENT_TYPE * first, size_t n
+ ST_SORT_PROTO_ELEMENT_SIZE
+ ST_SORT_PROTO_COMPARE
+ ST_SORT_PROTO_ARG);
+
+#endif
+
+#ifdef ST_DEFINE
+
+/* sort private helper functions */
+#define ST_MED3 ST_MAKE_NAME(ST_SORT, med3)
+#define ST_SWAP ST_MAKE_NAME(ST_SORT, swap)
+#define ST_SWAPN ST_MAKE_NAME(ST_SORT, swapn)
+
+/* Users expecting to run very large sorts may need them to be interruptible. */
+#ifdef ST_CHECK_FOR_INTERRUPTS
+#define DO_CHECK_FOR_INTERRUPTS() CHECK_FOR_INTERRUPTS()
+#else
+#define DO_CHECK_FOR_INTERRUPTS()
+#endif
+
+/*
+ * Create wrapper macros that know how to invoke compare, med3 and sort with
+ * the right arguments.
+ */
+#ifdef ST_COMPARE_RUNTIME_POINTER
+#define DO_COMPARE(a_, b_) ST_COMPARE((a_), (b_) ST_SORT_INVOKE_ARG)
+#elif defined(ST_COMPARE_ARG_TYPE)
+#define DO_COMPARE(a_, b_) ST_COMPARE((a_), (b_), arg)
+#else
+#define DO_COMPARE(a_, b_) ST_COMPARE((a_), (b_))
+#endif
+#define DO_MED3(a_, b_, c_) \
+ ST_MED3((a_), (b_), (c_) \
+ ST_SORT_INVOKE_COMPARE \
+ ST_SORT_INVOKE_ARG)
+#define DO_SORT(a_, n_) \
+ ST_SORT((a_), (n_) \
+ ST_SORT_INVOKE_ELEMENT_SIZE \
+ ST_SORT_INVOKE_COMPARE \
+ ST_SORT_INVOKE_ARG)
+
+/*
+ * If we're working with void pointers, we'll use pointer arithmetic based on
+ * uint8, and use the runtime element_size to step through the array and swap
+ * elements. Otherwise we'll work with ST_ELEMENT_TYPE.
+ */
+#ifndef ST_ELEMENT_TYPE_VOID
+#define ST_POINTER_TYPE ST_ELEMENT_TYPE
+#define ST_POINTER_STEP 1
+#define DO_SWAPN(a_, b_, n_) ST_SWAPN((a_), (b_), (n_))
+#define DO_SWAP(a_, b_) ST_SWAP((a_), (b_))
+#else
+#define ST_POINTER_TYPE uint8
+#define ST_POINTER_STEP element_size
+#define DO_SWAPN(a_, b_, n_) ST_SWAPN((a_), (b_), (n_))
+#define DO_SWAP(a_, b_) DO_SWAPN((a_), (b_), element_size)
+#endif
+
+/*
+ * Find the median of three values. Currently, performance seems to be best
+ * if the comparator is inlined here, but the med3 function is not inlined
+ * in the qsort function.
+ */
+static pg_noinline ST_ELEMENT_TYPE *
+ST_MED3(ST_ELEMENT_TYPE * a,
+ ST_ELEMENT_TYPE * b,
+ ST_ELEMENT_TYPE * c
+ ST_SORT_PROTO_COMPARE
+ ST_SORT_PROTO_ARG)
+{
+ return DO_COMPARE(a, b) < 0 ?
+ (DO_COMPARE(b, c) < 0 ? b : (DO_COMPARE(a, c) < 0 ? c : a))
+ : (DO_COMPARE(b, c) > 0 ? b : (DO_COMPARE(a, c) < 0 ? a : c));
+}
+
+static inline void
+ST_SWAP(ST_POINTER_TYPE * a, ST_POINTER_TYPE * b)
+{
+ ST_POINTER_TYPE tmp = *a;
+
+ *a = *b;
+ *b = tmp;
+}
+
+static inline void
+ST_SWAPN(ST_POINTER_TYPE * a, ST_POINTER_TYPE * b, size_t n)
+{
+ for (size_t i = 0; i < n; ++i)
+ ST_SWAP(&a[i], &b[i]);
+}
+
+/*
+ * Sort an array.
+ */
+ST_SCOPE void
+ST_SORT(ST_ELEMENT_TYPE * data, size_t n
+ ST_SORT_PROTO_ELEMENT_SIZE
+ ST_SORT_PROTO_COMPARE
+ ST_SORT_PROTO_ARG)
+{
+ ST_POINTER_TYPE *a = (ST_POINTER_TYPE *) data,
+ *pa,
+ *pb,
+ *pc,
+ *pd,
+ *pl,
+ *pm,
+ *pn;
+ size_t d1,
+ d2;
+ int r,
+ presorted;
+
+loop:
+ DO_CHECK_FOR_INTERRUPTS();
+ if (n < 7)
+ {
+ for (pm = a + ST_POINTER_STEP; pm < a + n * ST_POINTER_STEP;
+ pm += ST_POINTER_STEP)
+ for (pl = pm; pl > a && DO_COMPARE(pl - ST_POINTER_STEP, pl) > 0;
+ pl -= ST_POINTER_STEP)
+ DO_SWAP(pl, pl - ST_POINTER_STEP);
+ return;
+ }
+ presorted = 1;
+ for (pm = a + ST_POINTER_STEP; pm < a + n * ST_POINTER_STEP;
+ pm += ST_POINTER_STEP)
+ {
+ DO_CHECK_FOR_INTERRUPTS();
+ if (DO_COMPARE(pm - ST_POINTER_STEP, pm) > 0)
+ {
+ presorted = 0;
+ break;
+ }
+ }
+ if (presorted)
+ return;
+ pm = a + (n / 2) * ST_POINTER_STEP;
+ if (n > 7)
+ {
+ pl = a;
+ pn = a + (n - 1) * ST_POINTER_STEP;
+ if (n > 40)
+ {
+ size_t d = (n / 8) * ST_POINTER_STEP;
+
+ pl = DO_MED3(pl, pl + d, pl + 2 * d);
+ pm = DO_MED3(pm - d, pm, pm + d);
+ pn = DO_MED3(pn - 2 * d, pn - d, pn);
+ }
+ pm = DO_MED3(pl, pm, pn);
+ }
+ DO_SWAP(a, pm);
+ pa = pb = a + ST_POINTER_STEP;
+ pc = pd = a + (n - 1) * ST_POINTER_STEP;
+ for (;;)
+ {
+ while (pb <= pc && (r = DO_COMPARE(pb, a)) <= 0)
+ {
+ if (r == 0)
+ {
+ DO_SWAP(pa, pb);
+ pa += ST_POINTER_STEP;
+ }
+ pb += ST_POINTER_STEP;
+ DO_CHECK_FOR_INTERRUPTS();
+ }
+ while (pb <= pc && (r = DO_COMPARE(pc, a)) >= 0)
+ {
+ if (r == 0)
+ {
+ DO_SWAP(pc, pd);
+ pd -= ST_POINTER_STEP;
+ }
+ pc -= ST_POINTER_STEP;
+ DO_CHECK_FOR_INTERRUPTS();
+ }
+ if (pb > pc)
+ break;
+ DO_SWAP(pb, pc);
+ pb += ST_POINTER_STEP;
+ pc -= ST_POINTER_STEP;
+ }
+ pn = a + n * ST_POINTER_STEP;
+ d1 = Min(pa - a, pb - pa);
+ DO_SWAPN(a, pb - d1, d1);
+ d1 = Min(pd - pc, pn - pd - ST_POINTER_STEP);
+ DO_SWAPN(pb, pn - d1, d1);
+ d1 = pb - pa;
+ d2 = pd - pc;
+ if (d1 <= d2)
+ {
+ /* Recurse on left partition, then iterate on right partition */
+ if (d1 > ST_POINTER_STEP)
+ DO_SORT(a, d1 / ST_POINTER_STEP);
+ if (d2 > ST_POINTER_STEP)
+ {
+ /* Iterate rather than recurse to save stack space */
+ /* DO_SORT(pn - d2, d2 / ST_POINTER_STEP) */
+ a = pn - d2;
+ n = d2 / ST_POINTER_STEP;
+ goto loop;
+ }
+ }
+ else
+ {
+ /* Recurse on right partition, then iterate on left partition */
+ if (d2 > ST_POINTER_STEP)
+ DO_SORT(pn - d2, d2 / ST_POINTER_STEP);
+ if (d1 > ST_POINTER_STEP)
+ {
+ /* Iterate rather than recurse to save stack space */
+ /* DO_SORT(a, d1 / ST_POINTER_STEP) */
+ n = d1 / ST_POINTER_STEP;
+ goto loop;
+ }
+ }
+}
+#endif
+
+#undef DO_CHECK_FOR_INTERRUPTS
+#undef DO_COMPARE
+#undef DO_MED3
+#undef DO_SORT
+#undef DO_SWAP
+#undef DO_SWAPN
+#undef ST_CHECK_FOR_INTERRUPTS
+#undef ST_COMPARATOR_TYPE_NAME
+#undef ST_COMPARE
+#undef ST_COMPARE_ARG_TYPE
+#undef ST_COMPARE_RUNTIME_POINTER
+#undef ST_ELEMENT_TYPE
+#undef ST_ELEMENT_TYPE_VOID
+#undef ST_MAKE_NAME
+#undef ST_MAKE_NAME_
+#undef ST_MAKE_PREFIX
+#undef ST_MED3
+#undef ST_POINTER_STEP
+#undef ST_POINTER_TYPE
+#undef ST_SCOPE
+#undef ST_SORT
+#undef ST_SORT_INVOKE_ARG
+#undef ST_SORT_INVOKE_COMPARE
+#undef ST_SORT_INVOKE_ELEMENT_SIZE
+#undef ST_SORT_PROTO_ARG
+#undef ST_SORT_PROTO_COMPARE
+#undef ST_SORT_PROTO_ELEMENT_SIZE
+#undef ST_SWAP
+#undef ST_SWAPN
diff --git a/contrib/libs/libpq/src/include/lib/stringinfo.h b/contrib/libs/libpq/src/include/lib/stringinfo.h
new file mode 100644
index 0000000000..36a416f8e0
--- /dev/null
+++ b/contrib/libs/libpq/src/include/lib/stringinfo.h
@@ -0,0 +1,161 @@
+/*-------------------------------------------------------------------------
+ *
+ * stringinfo.h
+ * Declarations/definitions for "StringInfo" functions.
+ *
+ * StringInfo provides an extensible string data type (currently limited to a
+ * length of 1GB). It can be used to buffer either ordinary C strings
+ * (null-terminated text) or arbitrary binary data. All storage is allocated
+ * with palloc() (falling back to malloc in frontend code).
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/lib/stringinfo.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef STRINGINFO_H
+#define STRINGINFO_H
+
+/*-------------------------
+ * StringInfoData holds information about an extensible string.
+ * data is the current buffer for the string (allocated with palloc).
+ * len is the current string length. There is guaranteed to be
+ * a terminating '\0' at data[len], although this is not very
+ * useful when the string holds binary data rather than text.
+ * maxlen is the allocated size in bytes of 'data', i.e. the maximum
+ * string size (including the terminating '\0' char) that we can
+ * currently store in 'data' without having to reallocate
+ * more space. We must always have maxlen > len.
+ * cursor is initialized to zero by makeStringInfo or initStringInfo,
+ * but is not otherwise touched by the stringinfo.c routines.
+ * Some routines use it to scan through a StringInfo.
+ *-------------------------
+ */
+typedef struct StringInfoData
+{
+ char *data;
+ int len;
+ int maxlen;
+ int cursor;
+} StringInfoData;
+
+typedef StringInfoData *StringInfo;
+
+
+/*------------------------
+ * There are two ways to create a StringInfo object initially:
+ *
+ * StringInfo stringptr = makeStringInfo();
+ * Both the StringInfoData and the data buffer are palloc'd.
+ *
+ * StringInfoData string;
+ * initStringInfo(&string);
+ * The data buffer is palloc'd but the StringInfoData is just local.
+ * This is the easiest approach for a StringInfo object that will
+ * only live as long as the current routine.
+ *
+ * To destroy a StringInfo, pfree() the data buffer, and then pfree() the
+ * StringInfoData if it was palloc'd. There's no special support for this.
+ *
+ * NOTE: some routines build up a string using StringInfo, and then
+ * release the StringInfoData but return the data string itself to their
+ * caller. At that point the data string looks like a plain palloc'd
+ * string.
+ *-------------------------
+ */
+
+/*------------------------
+ * makeStringInfo
+ * Create an empty 'StringInfoData' & return a pointer to it.
+ */
+extern StringInfo makeStringInfo(void);
+
+/*------------------------
+ * initStringInfo
+ * Initialize a StringInfoData struct (with previously undefined contents)
+ * to describe an empty string.
+ */
+extern void initStringInfo(StringInfo str);
+
+/*------------------------
+ * resetStringInfo
+ * Clears the current content of the StringInfo, if any. The
+ * StringInfo remains valid.
+ */
+extern void resetStringInfo(StringInfo str);
+
+/*------------------------
+ * appendStringInfo
+ * Format text data under the control of fmt (an sprintf-style format string)
+ * and append it to whatever is already in str. More space is allocated
+ * to str if necessary. This is sort of like a combination of sprintf and
+ * strcat.
+ */
+extern void appendStringInfo(StringInfo str, const char *fmt,...) pg_attribute_printf(2, 3);
+
+/*------------------------
+ * appendStringInfoVA
+ * Attempt to format text data under the control of fmt (an sprintf-style
+ * format string) and append it to whatever is already in str. If successful
+ * return zero; if not (because there's not enough space), return an estimate
+ * of the space needed, without modifying str. Typically the caller should
+ * pass the return value to enlargeStringInfo() before trying again; see
+ * appendStringInfo for standard usage pattern.
+ */
+extern int appendStringInfoVA(StringInfo str, const char *fmt, va_list args) pg_attribute_printf(2, 0);
+
+/*------------------------
+ * appendStringInfoString
+ * Append a null-terminated string to str.
+ * Like appendStringInfo(str, "%s", s) but faster.
+ */
+extern void appendStringInfoString(StringInfo str, const char *s);
+
+/*------------------------
+ * appendStringInfoChar
+ * Append a single byte to str.
+ * Like appendStringInfo(str, "%c", ch) but much faster.
+ */
+extern void appendStringInfoChar(StringInfo str, char ch);
+
+/*------------------------
+ * appendStringInfoCharMacro
+ * As above, but a macro for even more speed where it matters.
+ * Caution: str argument will be evaluated multiple times.
+ */
+#define appendStringInfoCharMacro(str,ch) \
+ (((str)->len + 1 >= (str)->maxlen) ? \
+ appendStringInfoChar(str, ch) : \
+ (void)((str)->data[(str)->len] = (ch), (str)->data[++(str)->len] = '\0'))
+
+/*------------------------
+ * appendStringInfoSpaces
+ * Append a given number of spaces to str.
+ */
+extern void appendStringInfoSpaces(StringInfo str, int count);
+
+/*------------------------
+ * appendBinaryStringInfo
+ * Append arbitrary binary data to a StringInfo, allocating more space
+ * if necessary.
+ */
+extern void appendBinaryStringInfo(StringInfo str,
+ const void *data, int datalen);
+
+/*------------------------
+ * appendBinaryStringInfoNT
+ * Append arbitrary binary data to a StringInfo, allocating more space
+ * if necessary. Does not ensure a trailing null-byte exists.
+ */
+extern void appendBinaryStringInfoNT(StringInfo str,
+ const void *data, int datalen);
+
+/*------------------------
+ * enlargeStringInfo
+ * Make sure a StringInfo's buffer can hold at least 'needed' more bytes.
+ */
+extern void enlargeStringInfo(StringInfo str, int needed);
+
+#endif /* STRINGINFO_H */
diff --git a/contrib/libs/libpq/src/include/libpq/libpq-fs.h b/contrib/libs/libpq/src/include/libpq/libpq-fs.h
new file mode 100644
index 0000000000..f89e0f9e3f
--- /dev/null
+++ b/contrib/libs/libpq/src/include/libpq/libpq-fs.h
@@ -0,0 +1,24 @@
+/*-------------------------------------------------------------------------
+ *
+ * libpq-fs.h
+ * definitions for using Inversion file system routines (ie, large objects)
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/libpq/libpq-fs.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef LIBPQ_FS_H
+#define LIBPQ_FS_H
+
+/*
+ * Read/write mode flags for inversion (large object) calls
+ */
+
+#define INV_WRITE 0x00020000
+#define INV_READ 0x00040000
+
+#endif /* LIBPQ_FS_H */
diff --git a/contrib/libs/libpq/src/include/libpq/pqcomm.h b/contrib/libs/libpq/src/include/libpq/pqcomm.h
new file mode 100644
index 0000000000..c85090259d
--- /dev/null
+++ b/contrib/libs/libpq/src/include/libpq/pqcomm.h
@@ -0,0 +1,163 @@
+/*-------------------------------------------------------------------------
+ *
+ * pqcomm.h
+ * Definitions common to frontends and backends.
+ *
+ * NOTE: for historical reasons, this does not correspond to pqcomm.c.
+ * pqcomm.c's routines are declared in libpq.h.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/libpq/pqcomm.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PQCOMM_H
+#define PQCOMM_H
+
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netdb.h>
+#include <netinet/in.h>
+
+typedef struct
+{
+ struct sockaddr_storage addr;
+ socklen_t salen;
+} SockAddr;
+
+typedef struct
+{
+ int family;
+ SockAddr addr;
+} AddrInfo;
+
+/* Configure the UNIX socket location for the well known port. */
+
+#define UNIXSOCK_PATH(path, port, sockdir) \
+ (AssertMacro(sockdir), \
+ AssertMacro(*(sockdir) != '\0'), \
+ snprintf(path, sizeof(path), "%s/.s.PGSQL.%d", \
+ (sockdir), (port)))
+
+/*
+ * The maximum workable length of a socket path is what will fit into
+ * struct sockaddr_un. This is usually only 100 or so bytes :-(.
+ *
+ * For consistency, always pass a MAXPGPATH-sized buffer to UNIXSOCK_PATH(),
+ * then complain if the resulting string is >= UNIXSOCK_PATH_BUFLEN bytes.
+ * (Because the standard API for getaddrinfo doesn't allow it to complain in
+ * a useful way when the socket pathname is too long, we have to test for
+ * this explicitly, instead of just letting the subroutine return an error.)
+ */
+#define UNIXSOCK_PATH_BUFLEN sizeof(((struct sockaddr_un *) NULL)->sun_path)
+
+/*
+ * A host that looks either like an absolute path or starts with @ is
+ * interpreted as a Unix-domain socket address.
+ */
+static inline bool
+is_unixsock_path(const char *path)
+{
+ return is_absolute_path(path) || path[0] == '@';
+}
+
+/*
+ * These manipulate the frontend/backend protocol version number.
+ *
+ * The major number should be incremented for incompatible changes. The minor
+ * number should be incremented for compatible changes (eg. additional
+ * functionality).
+ *
+ * If a backend supports version m.n of the protocol it must actually support
+ * versions m.[0..n]. Backend support for version m-1 can be dropped after a
+ * `reasonable' length of time.
+ *
+ * A frontend isn't required to support anything other than the current
+ * version.
+ */
+
+#define PG_PROTOCOL_MAJOR(v) ((v) >> 16)
+#define PG_PROTOCOL_MINOR(v) ((v) & 0x0000ffff)
+#define PG_PROTOCOL(m,n) (((m) << 16) | (n))
+
+/*
+ * The earliest and latest frontend/backend protocol version supported.
+ * (Only protocol version 3 is currently supported)
+ */
+
+#define PG_PROTOCOL_EARLIEST PG_PROTOCOL(3,0)
+#define PG_PROTOCOL_LATEST PG_PROTOCOL(3,0)
+
+typedef uint32 ProtocolVersion; /* FE/BE protocol version number */
+
+typedef ProtocolVersion MsgType;
+
+
+/*
+ * Packet lengths are 4 bytes in network byte order.
+ *
+ * The initial length is omitted from the packet layouts appearing below.
+ */
+
+typedef uint32 PacketLen;
+
+extern PGDLLIMPORT bool Db_user_namespace;
+
+/*
+ * In protocol 3.0 and later, the startup packet length is not fixed, but
+ * we set an arbitrary limit on it anyway. This is just to prevent simple
+ * denial-of-service attacks via sending enough data to run the server
+ * out of memory.
+ */
+#define MAX_STARTUP_PACKET_LENGTH 10000
+
+
+/* These are the authentication request codes sent by the backend. */
+
+#define AUTH_REQ_OK 0 /* User is authenticated */
+#define AUTH_REQ_KRB4 1 /* Kerberos V4. Not supported any more. */
+#define AUTH_REQ_KRB5 2 /* Kerberos V5. Not supported any more. */
+#define AUTH_REQ_PASSWORD 3 /* Password */
+#define AUTH_REQ_CRYPT 4 /* crypt password. Not supported any more. */
+#define AUTH_REQ_MD5 5 /* md5 password */
+/* 6 is available. It was used for SCM creds, not supported any more. */
+#define AUTH_REQ_GSS 7 /* GSSAPI without wrap() */
+#define AUTH_REQ_GSS_CONT 8 /* Continue GSS exchanges */
+#define AUTH_REQ_SSPI 9 /* SSPI negotiate without wrap() */
+#define AUTH_REQ_SASL 10 /* Begin SASL authentication */
+#define AUTH_REQ_SASL_CONT 11 /* Continue SASL authentication */
+#define AUTH_REQ_SASL_FIN 12 /* Final SASL message */
+#define AUTH_REQ_MAX AUTH_REQ_SASL_FIN /* maximum AUTH_REQ_* value */
+
+typedef uint32 AuthRequest;
+
+
+/*
+ * A client can also send a cancel-current-operation request to the postmaster.
+ * This is uglier than sending it directly to the client's backend, but it
+ * avoids depending on out-of-band communication facilities.
+ *
+ * The cancel request code must not match any protocol version number
+ * we're ever likely to use. This random choice should do.
+ */
+#define CANCEL_REQUEST_CODE PG_PROTOCOL(1234,5678)
+
+typedef struct CancelRequestPacket
+{
+ /* Note that each field is stored in network byte order! */
+ MsgType cancelRequestCode; /* code to identify a cancel request */
+ uint32 backendPID; /* PID of client's backend */
+ uint32 cancelAuthCode; /* secret key to authorize cancel */
+} CancelRequestPacket;
+
+
+/*
+ * A client can also start by sending a SSL or GSSAPI negotiation request to
+ * get a secure channel.
+ */
+#define NEGOTIATE_SSL_CODE PG_PROTOCOL(1234,5679)
+#define NEGOTIATE_GSS_CODE PG_PROTOCOL(1234,5680)
+
+#endif /* PQCOMM_H */
diff --git a/contrib/libs/libpq/src/include/mb/pg_wchar.h b/contrib/libs/libpq/src/include/mb/pg_wchar.h
new file mode 100644
index 0000000000..25276b199f
--- /dev/null
+++ b/contrib/libs/libpq/src/include/mb/pg_wchar.h
@@ -0,0 +1,772 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_wchar.h
+ * multibyte-character support
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/mb/pg_wchar.h
+ *
+ * NOTES
+ * This is used both by the backend and by frontends, but should not be
+ * included by libpq client programs. In particular, a libpq client
+ * should not assume that the encoding IDs used by the version of libpq
+ * it's linked to match up with the IDs declared here.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_WCHAR_H
+#define PG_WCHAR_H
+
+#include "port/simd.h"
+
+/*
+ * The pg_wchar type
+ */
+typedef unsigned int pg_wchar;
+
+/*
+ * Maximum byte length of multibyte characters in any backend encoding
+ */
+#define MAX_MULTIBYTE_CHAR_LEN 4
+
+/*
+ * various definitions for EUC
+ */
+#define SS2 0x8e /* single shift 2 (JIS0201) */
+#define SS3 0x8f /* single shift 3 (JIS0212) */
+
+/*
+ * SJIS validation macros
+ */
+#define ISSJISHEAD(c) (((c) >= 0x81 && (c) <= 0x9f) || ((c) >= 0xe0 && (c) <= 0xfc))
+#define ISSJISTAIL(c) (((c) >= 0x40 && (c) <= 0x7e) || ((c) >= 0x80 && (c) <= 0xfc))
+
+/*----------------------------------------------------
+ * MULE Internal Encoding (MIC)
+ *
+ * This encoding follows the design used within XEmacs; it is meant to
+ * subsume many externally-defined character sets. Each character includes
+ * identification of the character set it belongs to, so the encoding is
+ * general but somewhat bulky.
+ *
+ * Currently PostgreSQL supports 5 types of MULE character sets:
+ *
+ * 1) 1-byte ASCII characters. Each byte is below 0x80.
+ *
+ * 2) "Official" single byte charsets such as ISO-8859-1 (Latin1).
+ * Each MULE character consists of 2 bytes: LC1 + C1, where LC1 is
+ * an identifier for the charset (in the range 0x81 to 0x8d) and C1
+ * is the character code (in the range 0xa0 to 0xff).
+ *
+ * 3) "Private" single byte charsets such as SISHENG. Each MULE
+ * character consists of 3 bytes: LCPRV1 + LC12 + C1, where LCPRV1
+ * is a private-charset flag, LC12 is an identifier for the charset,
+ * and C1 is the character code (in the range 0xa0 to 0xff).
+ * LCPRV1 is either 0x9a (if LC12 is in the range 0xa0 to 0xdf)
+ * or 0x9b (if LC12 is in the range 0xe0 to 0xef).
+ *
+ * 4) "Official" multibyte charsets such as JIS X0208. Each MULE
+ * character consists of 3 bytes: LC2 + C1 + C2, where LC2 is
+ * an identifier for the charset (in the range 0x90 to 0x99) and C1
+ * and C2 form the character code (each in the range 0xa0 to 0xff).
+ *
+ * 5) "Private" multibyte charsets such as CNS 11643-1992 Plane 3.
+ * Each MULE character consists of 4 bytes: LCPRV2 + LC22 + C1 + C2,
+ * where LCPRV2 is a private-charset flag, LC22 is an identifier for
+ * the charset, and C1 and C2 form the character code (each in the range
+ * 0xa0 to 0xff). LCPRV2 is either 0x9c (if LC22 is in the range 0xf0
+ * to 0xf4) or 0x9d (if LC22 is in the range 0xf5 to 0xfe).
+ *
+ * "Official" encodings are those that have been assigned code numbers by
+ * the XEmacs project; "private" encodings have Postgres-specific charset
+ * identifiers.
+ *
+ * See the "XEmacs Internals Manual", available at http://www.xemacs.org,
+ * for more details. Note that for historical reasons, Postgres'
+ * private-charset flag values do not match what XEmacs says they should be,
+ * so this isn't really exactly MULE (not that private charsets would be
+ * interoperable anyway).
+ *
+ * Note that XEmacs's implementation is different from what emacs does.
+ * We follow emacs's implementation, rather than XEmacs's.
+ *----------------------------------------------------
+ */
+
+/*
+ * Charset identifiers (also called "leading bytes" in the MULE documentation)
+ */
+
+/*
+ * Charset IDs for official single byte encodings (0x81-0x8e)
+ */
+#define LC_ISO8859_1 0x81 /* ISO8859 Latin 1 */
+#define LC_ISO8859_2 0x82 /* ISO8859 Latin 2 */
+#define LC_ISO8859_3 0x83 /* ISO8859 Latin 3 */
+#define LC_ISO8859_4 0x84 /* ISO8859 Latin 4 */
+#define LC_TIS620 0x85 /* Thai (not supported yet) */
+#define LC_ISO8859_7 0x86 /* Greek (not supported yet) */
+#define LC_ISO8859_6 0x87 /* Arabic (not supported yet) */
+#define LC_ISO8859_8 0x88 /* Hebrew (not supported yet) */
+#define LC_JISX0201K 0x89 /* Japanese 1 byte kana */
+#define LC_JISX0201R 0x8a /* Japanese 1 byte Roman */
+/* Note that 0x8b seems to be unused as of Emacs 20.7.
+ * However, there might be a chance that 0x8b could be used
+ * in later versions of Emacs.
+ */
+#define LC_KOI8_R 0x8b /* Cyrillic KOI8-R */
+#define LC_ISO8859_5 0x8c /* ISO8859 Cyrillic */
+#define LC_ISO8859_9 0x8d /* ISO8859 Latin 5 (not supported yet) */
+#define LC_ISO8859_15 0x8e /* ISO8859 Latin 15 (not supported yet) */
+/* #define CONTROL_1 0x8f control characters (unused) */
+
+/* Is a leading byte for "official" single byte encodings? */
+#define IS_LC1(c) ((unsigned char)(c) >= 0x81 && (unsigned char)(c) <= 0x8d)
+
+/*
+ * Charset IDs for official multibyte encodings (0x90-0x99)
+ * 0x9a-0x9d are free. 0x9e and 0x9f are reserved.
+ */
+#define LC_JISX0208_1978 0x90 /* Japanese Kanji, old JIS (not supported) */
+#define LC_GB2312_80 0x91 /* Chinese */
+#define LC_JISX0208 0x92 /* Japanese Kanji (JIS X 0208) */
+#define LC_KS5601 0x93 /* Korean */
+#define LC_JISX0212 0x94 /* Japanese Kanji (JIS X 0212) */
+#define LC_CNS11643_1 0x95 /* CNS 11643-1992 Plane 1 */
+#define LC_CNS11643_2 0x96 /* CNS 11643-1992 Plane 2 */
+#define LC_JISX0213_1 0x97 /* Japanese Kanji (JIS X 0213 Plane 1)
+ * (not supported) */
+#define LC_BIG5_1 0x98 /* Plane 1 Chinese traditional (not
+ * supported) */
+#define LC_BIG5_2 0x99 /* Plane 1 Chinese traditional (not
+ * supported) */
+
+/* Is a leading byte for "official" multibyte encodings? */
+#define IS_LC2(c) ((unsigned char)(c) >= 0x90 && (unsigned char)(c) <= 0x99)
+
+/*
+ * Postgres-specific prefix bytes for "private" single byte encodings
+ * (According to the MULE docs, we should be using 0x9e for this)
+ */
+#define LCPRV1_A 0x9a
+#define LCPRV1_B 0x9b
+#define IS_LCPRV1(c) ((unsigned char)(c) == LCPRV1_A || (unsigned char)(c) == LCPRV1_B)
+#define IS_LCPRV1_A_RANGE(c) \
+ ((unsigned char)(c) >= 0xa0 && (unsigned char)(c) <= 0xdf)
+#define IS_LCPRV1_B_RANGE(c) \
+ ((unsigned char)(c) >= 0xe0 && (unsigned char)(c) <= 0xef)
+
+/*
+ * Postgres-specific prefix bytes for "private" multibyte encodings
+ * (According to the MULE docs, we should be using 0x9f for this)
+ */
+#define LCPRV2_A 0x9c
+#define LCPRV2_B 0x9d
+#define IS_LCPRV2(c) ((unsigned char)(c) == LCPRV2_A || (unsigned char)(c) == LCPRV2_B)
+#define IS_LCPRV2_A_RANGE(c) \
+ ((unsigned char)(c) >= 0xf0 && (unsigned char)(c) <= 0xf4)
+#define IS_LCPRV2_B_RANGE(c) \
+ ((unsigned char)(c) >= 0xf5 && (unsigned char)(c) <= 0xfe)
+
+/*
+ * Charset IDs for private single byte encodings (0xa0-0xef)
+ */
+#define LC_SISHENG 0xa0 /* Chinese SiSheng characters for
+ * PinYin/ZhuYin (not supported) */
+#define LC_IPA 0xa1 /* IPA (International Phonetic
+ * Association) (not supported) */
+#define LC_VISCII_LOWER 0xa2 /* Vietnamese VISCII1.1 lower-case (not
+ * supported) */
+#define LC_VISCII_UPPER 0xa3 /* Vietnamese VISCII1.1 upper-case (not
+ * supported) */
+#define LC_ARABIC_DIGIT 0xa4 /* Arabic digit (not supported) */
+#define LC_ARABIC_1_COLUMN 0xa5 /* Arabic 1-column (not supported) */
+#define LC_ASCII_RIGHT_TO_LEFT 0xa6 /* ASCII (left half of ISO8859-1) with
+ * right-to-left direction (not
+ * supported) */
+#define LC_LAO 0xa7 /* Lao characters (ISO10646 0E80..0EDF)
+ * (not supported) */
+#define LC_ARABIC_2_COLUMN 0xa8 /* Arabic 1-column (not supported) */
+
+/*
+ * Charset IDs for private multibyte encodings (0xf0-0xff)
+ */
+#define LC_INDIAN_1_COLUMN 0xf0 /* Indian charset for 1-column width
+ * glyphs (not supported) */
+#define LC_TIBETAN_1_COLUMN 0xf1 /* Tibetan 1-column width glyphs (not
+ * supported) */
+#define LC_UNICODE_SUBSET_2 0xf2 /* Unicode characters of the range
+ * U+2500..U+33FF. (not supported) */
+#define LC_UNICODE_SUBSET_3 0xf3 /* Unicode characters of the range
+ * U+E000..U+FFFF. (not supported) */
+#define LC_UNICODE_SUBSET 0xf4 /* Unicode characters of the range
+ * U+0100..U+24FF. (not supported) */
+#define LC_ETHIOPIC 0xf5 /* Ethiopic characters (not supported) */
+#define LC_CNS11643_3 0xf6 /* CNS 11643-1992 Plane 3 */
+#define LC_CNS11643_4 0xf7 /* CNS 11643-1992 Plane 4 */
+#define LC_CNS11643_5 0xf8 /* CNS 11643-1992 Plane 5 */
+#define LC_CNS11643_6 0xf9 /* CNS 11643-1992 Plane 6 */
+#define LC_CNS11643_7 0xfa /* CNS 11643-1992 Plane 7 */
+#define LC_INDIAN_2_COLUMN 0xfb /* Indian charset for 2-column width
+ * glyphs (not supported) */
+#define LC_TIBETAN 0xfc /* Tibetan (not supported) */
+/* #define FREE 0xfd free (unused) */
+/* #define FREE 0xfe free (unused) */
+/* #define FREE 0xff free (unused) */
+
+/*----------------------------------------------------
+ * end of MULE stuff
+ *----------------------------------------------------
+ */
+
+/*
+ * PostgreSQL encoding identifiers
+ *
+ * WARNING: the order of this enum must be same as order of entries
+ * in the pg_enc2name_tbl[] array (in src/common/encnames.c), and
+ * in the pg_wchar_table[] array (in src/common/wchar.c)!
+ *
+ * If you add some encoding don't forget to check
+ * PG_ENCODING_BE_LAST macro.
+ *
+ * PG_SQL_ASCII is default encoding and must be = 0.
+ *
+ * XXX We must avoid renumbering any backend encoding until libpq's major
+ * version number is increased beyond 5; it turns out that the backend
+ * encoding IDs are effectively part of libpq's ABI as far as 8.2 initdb and
+ * psql are concerned.
+ */
+typedef enum pg_enc
+{
+ PG_SQL_ASCII = 0, /* SQL/ASCII */
+ PG_EUC_JP, /* EUC for Japanese */
+ PG_EUC_CN, /* EUC for Chinese */
+ PG_EUC_KR, /* EUC for Korean */
+ PG_EUC_TW, /* EUC for Taiwan */
+ PG_EUC_JIS_2004, /* EUC-JIS-2004 */
+ PG_UTF8, /* Unicode UTF8 */
+ PG_MULE_INTERNAL, /* Mule internal code */
+ PG_LATIN1, /* ISO-8859-1 Latin 1 */
+ PG_LATIN2, /* ISO-8859-2 Latin 2 */
+ PG_LATIN3, /* ISO-8859-3 Latin 3 */
+ PG_LATIN4, /* ISO-8859-4 Latin 4 */
+ PG_LATIN5, /* ISO-8859-9 Latin 5 */
+ PG_LATIN6, /* ISO-8859-10 Latin6 */
+ PG_LATIN7, /* ISO-8859-13 Latin7 */
+ PG_LATIN8, /* ISO-8859-14 Latin8 */
+ PG_LATIN9, /* ISO-8859-15 Latin9 */
+ PG_LATIN10, /* ISO-8859-16 Latin10 */
+ PG_WIN1256, /* windows-1256 */
+ PG_WIN1258, /* Windows-1258 */
+ PG_WIN866, /* (MS-DOS CP866) */
+ PG_WIN874, /* windows-874 */
+ PG_KOI8R, /* KOI8-R */
+ PG_WIN1251, /* windows-1251 */
+ PG_WIN1252, /* windows-1252 */
+ PG_ISO_8859_5, /* ISO-8859-5 */
+ PG_ISO_8859_6, /* ISO-8859-6 */
+ PG_ISO_8859_7, /* ISO-8859-7 */
+ PG_ISO_8859_8, /* ISO-8859-8 */
+ PG_WIN1250, /* windows-1250 */
+ PG_WIN1253, /* windows-1253 */
+ PG_WIN1254, /* windows-1254 */
+ PG_WIN1255, /* windows-1255 */
+ PG_WIN1257, /* windows-1257 */
+ PG_KOI8U, /* KOI8-U */
+ /* PG_ENCODING_BE_LAST points to the above entry */
+
+ /* followings are for client encoding only */
+ PG_SJIS, /* Shift JIS (Windows-932) */
+ PG_BIG5, /* Big5 (Windows-950) */
+ PG_GBK, /* GBK (Windows-936) */
+ PG_UHC, /* UHC (Windows-949) */
+ PG_GB18030, /* GB18030 */
+ PG_JOHAB, /* EUC for Korean JOHAB */
+ PG_SHIFT_JIS_2004, /* Shift-JIS-2004 */
+ _PG_LAST_ENCODING_ /* mark only */
+
+} pg_enc;
+
+#define PG_ENCODING_BE_LAST PG_KOI8U
+
+/*
+ * Please use these tests before access to pg_enc2name_tbl[]
+ * or to other places...
+ */
+#define PG_VALID_BE_ENCODING(_enc) \
+ ((_enc) >= 0 && (_enc) <= PG_ENCODING_BE_LAST)
+
+#define PG_ENCODING_IS_CLIENT_ONLY(_enc) \
+ ((_enc) > PG_ENCODING_BE_LAST && (_enc) < _PG_LAST_ENCODING_)
+
+#define PG_VALID_ENCODING(_enc) \
+ ((_enc) >= 0 && (_enc) < _PG_LAST_ENCODING_)
+
+/* On FE are possible all encodings */
+#define PG_VALID_FE_ENCODING(_enc) PG_VALID_ENCODING(_enc)
+
+/*
+ * When converting strings between different encodings, we assume that space
+ * for converted result is 4-to-1 growth in the worst case. The rate for
+ * currently supported encoding pairs are within 3 (SJIS JIS X0201 half width
+ * kana -> UTF8 is the worst case). So "4" should be enough for the moment.
+ *
+ * Note that this is not the same as the maximum character width in any
+ * particular encoding.
+ */
+#define MAX_CONVERSION_GROWTH 4
+
+/*
+ * Maximum byte length of a string that's required in any encoding to convert
+ * at least one character to any other encoding. In other words, if you feed
+ * MAX_CONVERSION_INPUT_LENGTH bytes to any encoding conversion function, it
+ * is guaranteed to be able to convert something without needing more input
+ * (assuming the input is valid).
+ *
+ * Currently, the maximum case is the conversion UTF8 -> SJIS JIS X0201 half
+ * width kana, where a pair of UTF-8 characters is converted into a single
+ * SHIFT_JIS_2004 character (the reverse of the worst case for
+ * MAX_CONVERSION_GROWTH). It needs 6 bytes of input. In theory, a
+ * user-defined conversion function might have more complicated cases, although
+ * for the reverse mapping you would probably also need to bump up
+ * MAX_CONVERSION_GROWTH. But there is no need to be stingy here, so make it
+ * generous.
+ */
+#define MAX_CONVERSION_INPUT_LENGTH 16
+
+/*
+ * Maximum byte length of the string equivalent to any one Unicode code point,
+ * in any backend encoding. The current value assumes that a 4-byte UTF-8
+ * character might expand by MAX_CONVERSION_GROWTH, which is a huge
+ * overestimate. But in current usage we don't allocate large multiples of
+ * this, so there's little point in being stingy.
+ */
+#define MAX_UNICODE_EQUIVALENT_STRING 16
+
+/*
+ * Table for mapping an encoding number to official encoding name and
+ * possibly other subsidiary data. Be careful to check encoding number
+ * before accessing a table entry!
+ *
+ * if (PG_VALID_ENCODING(encoding))
+ * pg_enc2name_tbl[ encoding ];
+ */
+typedef struct pg_enc2name
+{
+ const char *name;
+ pg_enc encoding;
+#ifdef WIN32
+ unsigned codepage; /* codepage for WIN32 */
+#endif
+} pg_enc2name;
+
+extern PGDLLIMPORT const pg_enc2name pg_enc2name_tbl[];
+
+/*
+ * Encoding names for gettext
+ */
+typedef struct pg_enc2gettext
+{
+ pg_enc encoding;
+ const char *name;
+} pg_enc2gettext;
+
+extern PGDLLIMPORT const pg_enc2gettext pg_enc2gettext_tbl[];
+
+/*
+ * pg_wchar stuff
+ */
+typedef int (*mb2wchar_with_len_converter) (const unsigned char *from,
+ pg_wchar *to,
+ int len);
+
+typedef int (*wchar2mb_with_len_converter) (const pg_wchar *from,
+ unsigned char *to,
+ int len);
+
+typedef int (*mblen_converter) (const unsigned char *mbstr);
+
+typedef int (*mbdisplaylen_converter) (const unsigned char *mbstr);
+
+typedef bool (*mbcharacter_incrementer) (unsigned char *mbstr, int len);
+
+typedef int (*mbchar_verifier) (const unsigned char *mbstr, int len);
+
+typedef int (*mbstr_verifier) (const unsigned char *mbstr, int len);
+
+typedef struct
+{
+ mb2wchar_with_len_converter mb2wchar_with_len; /* convert a multibyte
+ * string to a wchar */
+ wchar2mb_with_len_converter wchar2mb_with_len; /* convert a wchar string
+ * to a multibyte */
+ mblen_converter mblen; /* get byte length of a char */
+ mbdisplaylen_converter dsplen; /* get display width of a char */
+ mbchar_verifier mbverifychar; /* verify multibyte character */
+ mbstr_verifier mbverifystr; /* verify multibyte string */
+ int maxmblen; /* max bytes for a char in this encoding */
+} pg_wchar_tbl;
+
+extern PGDLLIMPORT const pg_wchar_tbl pg_wchar_table[];
+
+/*
+ * Data structures for conversions between UTF-8 and other encodings
+ * (UtfToLocal() and LocalToUtf()). In these data structures, characters of
+ * either encoding are represented by uint32 words; hence we can only support
+ * characters up to 4 bytes long. For example, the byte sequence 0xC2 0x89
+ * would be represented by 0x0000C289, and 0xE8 0xA2 0xB4 by 0x00E8A2B4.
+ *
+ * There are three possible ways a character can be mapped:
+ *
+ * 1. Using a radix tree, from source to destination code.
+ * 2. Using a sorted array of source -> destination code pairs. This
+ * method is used for "combining" characters. There are so few of
+ * them that building a radix tree would be wasteful.
+ * 3. Using a conversion function.
+ */
+
+/*
+ * Radix tree for character conversion.
+ *
+ * Logically, this is actually four different radix trees, for 1-byte,
+ * 2-byte, 3-byte and 4-byte inputs. The 1-byte tree is a simple lookup
+ * table from source to target code. The 2-byte tree consists of two levels:
+ * one lookup table for the first byte, where the value in the lookup table
+ * points to a lookup table for the second byte. And so on.
+ *
+ * Physically, all the trees are stored in one big array, in 'chars16' or
+ * 'chars32', depending on the maximum value that needs to be represented. For
+ * each level in each tree, we also store lower and upper bound of allowed
+ * values - values outside those bounds are considered invalid, and are left
+ * out of the tables.
+ *
+ * In the intermediate levels of the trees, the values stored are offsets
+ * into the chars[16|32] array.
+ *
+ * In the beginning of the chars[16|32] array, there is always a number of
+ * zeros, so that you safely follow an index from an intermediate table
+ * without explicitly checking for a zero. Following a zero any number of
+ * times will always bring you to the dummy, all-zeros table in the
+ * beginning. This helps to shave some cycles when looking up values.
+ */
+typedef struct
+{
+ /*
+ * Array containing all the values. Only one of chars16 or chars32 is
+ * used, depending on how wide the values we need to represent are.
+ */
+ const uint16 *chars16;
+ const uint32 *chars32;
+
+ /* Radix tree for 1-byte inputs */
+ uint32 b1root; /* offset of table in the chars[16|32] array */
+ uint8 b1_lower; /* min allowed value for a single byte input */
+ uint8 b1_upper; /* max allowed value for a single byte input */
+
+ /* Radix tree for 2-byte inputs */
+ uint32 b2root; /* offset of 1st byte's table */
+ uint8 b2_1_lower; /* min/max allowed value for 1st input byte */
+ uint8 b2_1_upper;
+ uint8 b2_2_lower; /* min/max allowed value for 2nd input byte */
+ uint8 b2_2_upper;
+
+ /* Radix tree for 3-byte inputs */
+ uint32 b3root; /* offset of 1st byte's table */
+ uint8 b3_1_lower; /* min/max allowed value for 1st input byte */
+ uint8 b3_1_upper;
+ uint8 b3_2_lower; /* min/max allowed value for 2nd input byte */
+ uint8 b3_2_upper;
+ uint8 b3_3_lower; /* min/max allowed value for 3rd input byte */
+ uint8 b3_3_upper;
+
+ /* Radix tree for 4-byte inputs */
+ uint32 b4root; /* offset of 1st byte's table */
+ uint8 b4_1_lower; /* min/max allowed value for 1st input byte */
+ uint8 b4_1_upper;
+ uint8 b4_2_lower; /* min/max allowed value for 2nd input byte */
+ uint8 b4_2_upper;
+ uint8 b4_3_lower; /* min/max allowed value for 3rd input byte */
+ uint8 b4_3_upper;
+ uint8 b4_4_lower; /* min/max allowed value for 4th input byte */
+ uint8 b4_4_upper;
+
+} pg_mb_radix_tree;
+
+/*
+ * UTF-8 to local code conversion map (for combined characters)
+ */
+typedef struct
+{
+ uint32 utf1; /* UTF-8 code 1 */
+ uint32 utf2; /* UTF-8 code 2 */
+ uint32 code; /* local code */
+} pg_utf_to_local_combined;
+
+/*
+ * local code to UTF-8 conversion map (for combined characters)
+ */
+typedef struct
+{
+ uint32 code; /* local code */
+ uint32 utf1; /* UTF-8 code 1 */
+ uint32 utf2; /* UTF-8 code 2 */
+} pg_local_to_utf_combined;
+
+/*
+ * callback function for algorithmic encoding conversions (in either direction)
+ *
+ * if function returns zero, it does not know how to convert the code
+ */
+typedef uint32 (*utf_local_conversion_func) (uint32 code);
+
+/*
+ * Support macro for encoding conversion functions to validate their
+ * arguments. (This could be made more compact if we included fmgr.h
+ * here, but we don't want to do that because this header file is also
+ * used by frontends.)
+ */
+#define CHECK_ENCODING_CONVERSION_ARGS(srcencoding,destencoding) \
+ check_encoding_conversion_args(PG_GETARG_INT32(0), \
+ PG_GETARG_INT32(1), \
+ PG_GETARG_INT32(4), \
+ (srcencoding), \
+ (destencoding))
+
+
+/*
+ * Some handy functions for Unicode-specific tests.
+ */
+static inline bool
+is_valid_unicode_codepoint(pg_wchar c)
+{
+ return (c > 0 && c <= 0x10FFFF);
+}
+
+static inline bool
+is_utf16_surrogate_first(pg_wchar c)
+{
+ return (c >= 0xD800 && c <= 0xDBFF);
+}
+
+static inline bool
+is_utf16_surrogate_second(pg_wchar c)
+{
+ return (c >= 0xDC00 && c <= 0xDFFF);
+}
+
+static inline pg_wchar
+surrogate_pair_to_codepoint(pg_wchar first, pg_wchar second)
+{
+ return ((first & 0x3FF) << 10) + 0x10000 + (second & 0x3FF);
+}
+
+
+/*
+ * These functions are considered part of libpq's exported API and
+ * are also declared in libpq-fe.h.
+ */
+extern int pg_char_to_encoding(const char *name);
+extern const char *pg_encoding_to_char(int encoding);
+extern int pg_valid_server_encoding_id(int encoding);
+
+/*
+ * These functions are available to frontend code that links with libpgcommon
+ * (in addition to the ones just above). The constant tables declared
+ * earlier in this file are also available from libpgcommon.
+ */
+extern int pg_encoding_mblen(int encoding, const char *mbstr);
+extern int pg_encoding_mblen_bounded(int encoding, const char *mbstr);
+extern int pg_encoding_dsplen(int encoding, const char *mbstr);
+extern int pg_encoding_verifymbchar(int encoding, const char *mbstr, int len);
+extern int pg_encoding_verifymbstr(int encoding, const char *mbstr, int len);
+extern int pg_encoding_max_length(int encoding);
+extern int pg_valid_client_encoding(const char *name);
+extern int pg_valid_server_encoding(const char *name);
+extern bool is_encoding_supported_by_icu(int encoding);
+extern const char *get_encoding_name_for_icu(int encoding);
+
+extern unsigned char *unicode_to_utf8(pg_wchar c, unsigned char *utf8string);
+extern pg_wchar utf8_to_unicode(const unsigned char *c);
+extern bool pg_utf8_islegal(const unsigned char *source, int length);
+extern int pg_utf_mblen(const unsigned char *s);
+extern int pg_mule_mblen(const unsigned char *s);
+
+/*
+ * The remaining functions are backend-only.
+ */
+extern int pg_mb2wchar(const char *from, pg_wchar *to);
+extern int pg_mb2wchar_with_len(const char *from, pg_wchar *to, int len);
+extern int pg_encoding_mb2wchar_with_len(int encoding,
+ const char *from, pg_wchar *to, int len);
+extern int pg_wchar2mb(const pg_wchar *from, char *to);
+extern int pg_wchar2mb_with_len(const pg_wchar *from, char *to, int len);
+extern int pg_encoding_wchar2mb_with_len(int encoding,
+ const pg_wchar *from, char *to, int len);
+extern int pg_char_and_wchar_strcmp(const char *s1, const pg_wchar *s2);
+extern int pg_wchar_strncmp(const pg_wchar *s1, const pg_wchar *s2, size_t n);
+extern int pg_char_and_wchar_strncmp(const char *s1, const pg_wchar *s2, size_t n);
+extern size_t pg_wchar_strlen(const pg_wchar *str);
+extern int pg_mblen(const char *mbstr);
+extern int pg_dsplen(const char *mbstr);
+extern int pg_mbstrlen(const char *mbstr);
+extern int pg_mbstrlen_with_len(const char *mbstr, int limit);
+extern int pg_mbcliplen(const char *mbstr, int len, int limit);
+extern int pg_encoding_mbcliplen(int encoding, const char *mbstr,
+ int len, int limit);
+extern int pg_mbcharcliplen(const char *mbstr, int len, int limit);
+extern int pg_database_encoding_max_length(void);
+extern mbcharacter_incrementer pg_database_encoding_character_incrementer(void);
+
+extern int PrepareClientEncoding(int encoding);
+extern int SetClientEncoding(int encoding);
+extern void InitializeClientEncoding(void);
+extern int pg_get_client_encoding(void);
+extern const char *pg_get_client_encoding_name(void);
+
+extern void SetDatabaseEncoding(int encoding);
+extern int GetDatabaseEncoding(void);
+extern const char *GetDatabaseEncodingName(void);
+extern void SetMessageEncoding(int encoding);
+extern int GetMessageEncoding(void);
+
+#ifdef ENABLE_NLS
+extern int pg_bind_textdomain_codeset(const char *domainname);
+#endif
+
+extern unsigned char *pg_do_encoding_conversion(unsigned char *src, int len,
+ int src_encoding,
+ int dest_encoding);
+extern int pg_do_encoding_conversion_buf(Oid proc,
+ int src_encoding,
+ int dest_encoding,
+ unsigned char *src, int srclen,
+ unsigned char *dest, int destlen,
+ bool noError);
+
+extern char *pg_client_to_server(const char *s, int len);
+extern char *pg_server_to_client(const char *s, int len);
+extern char *pg_any_to_server(const char *s, int len, int encoding);
+extern char *pg_server_to_any(const char *s, int len, int encoding);
+
+extern void pg_unicode_to_server(pg_wchar c, unsigned char *s);
+extern bool pg_unicode_to_server_noerror(pg_wchar c, unsigned char *s);
+
+extern unsigned short BIG5toCNS(unsigned short big5, unsigned char *lc);
+extern unsigned short CNStoBIG5(unsigned short cns, unsigned char lc);
+
+extern int UtfToLocal(const unsigned char *utf, int len,
+ unsigned char *iso,
+ const pg_mb_radix_tree *map,
+ const pg_utf_to_local_combined *cmap, int cmapsize,
+ utf_local_conversion_func conv_func,
+ int encoding, bool noError);
+extern int LocalToUtf(const unsigned char *iso, int len,
+ unsigned char *utf,
+ const pg_mb_radix_tree *map,
+ const pg_local_to_utf_combined *cmap, int cmapsize,
+ utf_local_conversion_func conv_func,
+ int encoding, bool noError);
+
+extern bool pg_verifymbstr(const char *mbstr, int len, bool noError);
+extern bool pg_verify_mbstr(int encoding, const char *mbstr, int len,
+ bool noError);
+extern int pg_verify_mbstr_len(int encoding, const char *mbstr, int len,
+ bool noError);
+
+extern void check_encoding_conversion_args(int src_encoding,
+ int dest_encoding,
+ int len,
+ int expected_src_encoding,
+ int expected_dest_encoding);
+
+extern void report_invalid_encoding(int encoding, const char *mbstr, int len) pg_attribute_noreturn();
+extern void report_untranslatable_char(int src_encoding, int dest_encoding,
+ const char *mbstr, int len) pg_attribute_noreturn();
+
+extern int local2local(const unsigned char *l, unsigned char *p, int len,
+ int src_encoding, int dest_encoding,
+ const unsigned char *tab, bool noError);
+extern int latin2mic(const unsigned char *l, unsigned char *p, int len,
+ int lc, int encoding, bool noError);
+extern int mic2latin(const unsigned char *mic, unsigned char *p, int len,
+ int lc, int encoding, bool noError);
+extern int latin2mic_with_table(const unsigned char *l, unsigned char *p,
+ int len, int lc, int encoding,
+ const unsigned char *tab, bool noError);
+extern int mic2latin_with_table(const unsigned char *mic, unsigned char *p,
+ int len, int lc, int encoding,
+ const unsigned char *tab, bool noError);
+
+#ifdef WIN32
+extern WCHAR *pgwin32_message_to_UTF16(const char *str, int len, int *utf16len);
+#endif
+
+
+/*
+ * Verify a chunk of bytes for valid ASCII.
+ *
+ * Returns false if the input contains any zero bytes or bytes with the
+ * high-bit set. Input len must be a multiple of the chunk size (8 or 16).
+ */
+static inline bool
+is_valid_ascii(const unsigned char *s, int len)
+{
+ const unsigned char *const s_end = s + len;
+ Vector8 chunk;
+ Vector8 highbit_cum = vector8_broadcast(0);
+#ifdef USE_NO_SIMD
+ Vector8 zero_cum = vector8_broadcast(0x80);
+#endif
+
+ Assert(len % sizeof(chunk) == 0);
+
+ while (s < s_end)
+ {
+ vector8_load(&chunk, s);
+
+ /* Capture any zero bytes in this chunk. */
+#ifdef USE_NO_SIMD
+
+ /*
+ * First, add 0x7f to each byte. This sets the high bit in each byte,
+ * unless it was a zero. If any resulting high bits are zero, the
+ * corresponding high bits in the zero accumulator will be cleared.
+ *
+ * If none of the bytes in the chunk had the high bit set, the max
+ * value each byte can have after the addition is 0x7f + 0x7f = 0xfe,
+ * and we don't need to worry about carrying over to the next byte. If
+ * any input bytes did have the high bit set, it doesn't matter
+ * because we check for those separately.
+ */
+ zero_cum &= (chunk + vector8_broadcast(0x7F));
+#else
+
+ /*
+ * Set all bits in each lane of the highbit accumulator where input
+ * bytes are zero.
+ */
+ highbit_cum = vector8_or(highbit_cum,
+ vector8_eq(chunk, vector8_broadcast(0)));
+#endif
+
+ /* Capture all set bits in this chunk. */
+ highbit_cum = vector8_or(highbit_cum, chunk);
+
+ s += sizeof(chunk);
+ }
+
+ /* Check if any high bits in the high bit accumulator got set. */
+ if (vector8_is_highbit_set(highbit_cum))
+ return false;
+
+#ifdef USE_NO_SIMD
+ /* Check if any high bits in the zero accumulator got cleared. */
+ if (zero_cum != vector8_broadcast(0x80))
+ return false;
+#endif
+
+ return true;
+}
+
+#endif /* PG_WCHAR_H */
diff --git a/contrib/libs/libpq/src/include/parser/kwlist.h b/contrib/libs/libpq/src/include/parser/kwlist.h
new file mode 100644
index 0000000000..f5b2e61ca5
--- /dev/null
+++ b/contrib/libs/libpq/src/include/parser/kwlist.h
@@ -0,0 +1,498 @@
+/*-------------------------------------------------------------------------
+ *
+ * kwlist.h
+ *
+ * The keyword lists are kept in their own source files for use by
+ * automatic tools. The exact representation of a keyword is determined
+ * by the PG_KEYWORD macro, which is not defined in this file; it can
+ * be defined by the caller for special purposes.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/include/parser/kwlist.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/* there is deliberately not an #ifndef KWLIST_H here */
+
+/*
+ * List of keyword (name, token-value, category, bare-label-status) entries.
+ *
+ * Note: gen_keywordlist.pl requires the entries to appear in ASCII order.
+ */
+
+/* name, value, category, is-bare-label */
+PG_KEYWORD("abort", ABORT_P, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("absent", ABSENT, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("absolute", ABSOLUTE_P, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("access", ACCESS, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("action", ACTION, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("add", ADD_P, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("admin", ADMIN, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("after", AFTER, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("aggregate", AGGREGATE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("all", ALL, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("also", ALSO, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("alter", ALTER, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("always", ALWAYS, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("analyse", ANALYSE, RESERVED_KEYWORD, BARE_LABEL) /* British spelling */
+PG_KEYWORD("analyze", ANALYZE, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("and", AND, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("any", ANY, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("array", ARRAY, RESERVED_KEYWORD, AS_LABEL)
+PG_KEYWORD("as", AS, RESERVED_KEYWORD, AS_LABEL)
+PG_KEYWORD("asc", ASC, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("asensitive", ASENSITIVE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("assertion", ASSERTION, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("assignment", ASSIGNMENT, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("asymmetric", ASYMMETRIC, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("at", AT, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("atomic", ATOMIC, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("attach", ATTACH, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("attribute", ATTRIBUTE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("authorization", AUTHORIZATION, TYPE_FUNC_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("backward", BACKWARD, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("before", BEFORE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("begin", BEGIN_P, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("between", BETWEEN, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("bigint", BIGINT, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("binary", BINARY, TYPE_FUNC_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("bit", BIT, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("boolean", BOOLEAN_P, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("both", BOTH, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("breadth", BREADTH, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("by", BY, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("cache", CACHE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("call", CALL, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("called", CALLED, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("cascade", CASCADE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("cascaded", CASCADED, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("case", CASE, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("cast", CAST, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("catalog", CATALOG_P, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("chain", CHAIN, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("char", CHAR_P, COL_NAME_KEYWORD, AS_LABEL)
+PG_KEYWORD("character", CHARACTER, COL_NAME_KEYWORD, AS_LABEL)
+PG_KEYWORD("characteristics", CHARACTERISTICS, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("check", CHECK, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("checkpoint", CHECKPOINT, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("class", CLASS, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("close", CLOSE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("cluster", CLUSTER, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("coalesce", COALESCE, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("collate", COLLATE, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("collation", COLLATION, TYPE_FUNC_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("column", COLUMN, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("columns", COLUMNS, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("comment", COMMENT, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("comments", COMMENTS, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("commit", COMMIT, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("committed", COMMITTED, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("compression", COMPRESSION, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("concurrently", CONCURRENTLY, TYPE_FUNC_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("configuration", CONFIGURATION, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("conflict", CONFLICT, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("connection", CONNECTION, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("constraint", CONSTRAINT, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("constraints", CONSTRAINTS, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("content", CONTENT_P, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("continue", CONTINUE_P, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("conversion", CONVERSION_P, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("copy", COPY, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("cost", COST, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("create", CREATE, RESERVED_KEYWORD, AS_LABEL)
+PG_KEYWORD("cross", CROSS, TYPE_FUNC_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("csv", CSV, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("cube", CUBE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("current", CURRENT_P, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("current_catalog", CURRENT_CATALOG, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("current_date", CURRENT_DATE, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("current_role", CURRENT_ROLE, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("current_schema", CURRENT_SCHEMA, TYPE_FUNC_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("current_time", CURRENT_TIME, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("current_timestamp", CURRENT_TIMESTAMP, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("current_user", CURRENT_USER, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("cursor", CURSOR, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("cycle", CYCLE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("data", DATA_P, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("database", DATABASE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("day", DAY_P, UNRESERVED_KEYWORD, AS_LABEL)
+PG_KEYWORD("deallocate", DEALLOCATE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("dec", DEC, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("decimal", DECIMAL_P, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("declare", DECLARE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("default", DEFAULT, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("defaults", DEFAULTS, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("deferrable", DEFERRABLE, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("deferred", DEFERRED, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("definer", DEFINER, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("delete", DELETE_P, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("delimiter", DELIMITER, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("delimiters", DELIMITERS, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("depends", DEPENDS, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("depth", DEPTH, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("desc", DESC, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("detach", DETACH, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("dictionary", DICTIONARY, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("disable", DISABLE_P, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("discard", DISCARD, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("distinct", DISTINCT, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("do", DO, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("document", DOCUMENT_P, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("domain", DOMAIN_P, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("double", DOUBLE_P, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("drop", DROP, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("each", EACH, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("else", ELSE, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("enable", ENABLE_P, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("encoding", ENCODING, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("encrypted", ENCRYPTED, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("end", END_P, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("enum", ENUM_P, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("escape", ESCAPE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("event", EVENT, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("except", EXCEPT, RESERVED_KEYWORD, AS_LABEL)
+PG_KEYWORD("exclude", EXCLUDE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("excluding", EXCLUDING, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("exclusive", EXCLUSIVE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("execute", EXECUTE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("exists", EXISTS, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("explain", EXPLAIN, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("expression", EXPRESSION, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("extension", EXTENSION, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("external", EXTERNAL, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("extract", EXTRACT, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("false", FALSE_P, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("family", FAMILY, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("fetch", FETCH, RESERVED_KEYWORD, AS_LABEL)
+PG_KEYWORD("filter", FILTER, UNRESERVED_KEYWORD, AS_LABEL)
+PG_KEYWORD("finalize", FINALIZE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("first", FIRST_P, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("float", FLOAT_P, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("following", FOLLOWING, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("for", FOR, RESERVED_KEYWORD, AS_LABEL)
+PG_KEYWORD("force", FORCE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("foreign", FOREIGN, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("format", FORMAT, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("forward", FORWARD, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("freeze", FREEZE, TYPE_FUNC_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("from", FROM, RESERVED_KEYWORD, AS_LABEL)
+PG_KEYWORD("full", FULL, TYPE_FUNC_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("function", FUNCTION, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("functions", FUNCTIONS, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("generated", GENERATED, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("global", GLOBAL, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("grant", GRANT, RESERVED_KEYWORD, AS_LABEL)
+PG_KEYWORD("granted", GRANTED, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("greatest", GREATEST, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("group", GROUP_P, RESERVED_KEYWORD, AS_LABEL)
+PG_KEYWORD("grouping", GROUPING, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("groups", GROUPS, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("handler", HANDLER, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("having", HAVING, RESERVED_KEYWORD, AS_LABEL)
+PG_KEYWORD("header", HEADER_P, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("hold", HOLD, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("hour", HOUR_P, UNRESERVED_KEYWORD, AS_LABEL)
+PG_KEYWORD("identity", IDENTITY_P, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("if", IF_P, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("ilike", ILIKE, TYPE_FUNC_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("immediate", IMMEDIATE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("immutable", IMMUTABLE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("implicit", IMPLICIT_P, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("import", IMPORT_P, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("in", IN_P, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("include", INCLUDE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("including", INCLUDING, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("increment", INCREMENT, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("indent", INDENT, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("index", INDEX, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("indexes", INDEXES, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("inherit", INHERIT, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("inherits", INHERITS, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("initially", INITIALLY, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("inline", INLINE_P, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("inner", INNER_P, TYPE_FUNC_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("inout", INOUT, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("input", INPUT_P, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("insensitive", INSENSITIVE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("insert", INSERT, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("instead", INSTEAD, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("int", INT_P, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("integer", INTEGER, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("intersect", INTERSECT, RESERVED_KEYWORD, AS_LABEL)
+PG_KEYWORD("interval", INTERVAL, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("into", INTO, RESERVED_KEYWORD, AS_LABEL)
+PG_KEYWORD("invoker", INVOKER, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("is", IS, TYPE_FUNC_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("isnull", ISNULL, TYPE_FUNC_NAME_KEYWORD, AS_LABEL)
+PG_KEYWORD("isolation", ISOLATION, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("join", JOIN, TYPE_FUNC_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("json", JSON, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("json_array", JSON_ARRAY, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("json_arrayagg", JSON_ARRAYAGG, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("json_object", JSON_OBJECT, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("json_objectagg", JSON_OBJECTAGG, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("key", KEY, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("keys", KEYS, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("label", LABEL, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("language", LANGUAGE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("large", LARGE_P, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("last", LAST_P, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("lateral", LATERAL_P, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("leading", LEADING, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("leakproof", LEAKPROOF, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("least", LEAST, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("left", LEFT, TYPE_FUNC_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("level", LEVEL, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("like", LIKE, TYPE_FUNC_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("limit", LIMIT, RESERVED_KEYWORD, AS_LABEL)
+PG_KEYWORD("listen", LISTEN, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("load", LOAD, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("local", LOCAL, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("localtime", LOCALTIME, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("localtimestamp", LOCALTIMESTAMP, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("location", LOCATION, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("lock", LOCK_P, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("locked", LOCKED, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("logged", LOGGED, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("mapping", MAPPING, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("match", MATCH, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("matched", MATCHED, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("materialized", MATERIALIZED, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("maxvalue", MAXVALUE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("merge", MERGE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("method", METHOD, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("minute", MINUTE_P, UNRESERVED_KEYWORD, AS_LABEL)
+PG_KEYWORD("minvalue", MINVALUE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("mode", MODE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("month", MONTH_P, UNRESERVED_KEYWORD, AS_LABEL)
+PG_KEYWORD("move", MOVE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("name", NAME_P, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("names", NAMES, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("national", NATIONAL, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("natural", NATURAL, TYPE_FUNC_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("nchar", NCHAR, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("new", NEW, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("next", NEXT, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("nfc", NFC, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("nfd", NFD, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("nfkc", NFKC, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("nfkd", NFKD, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("no", NO, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("none", NONE, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("normalize", NORMALIZE, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("normalized", NORMALIZED, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("not", NOT, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("nothing", NOTHING, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("notify", NOTIFY, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("notnull", NOTNULL, TYPE_FUNC_NAME_KEYWORD, AS_LABEL)
+PG_KEYWORD("nowait", NOWAIT, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("null", NULL_P, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("nullif", NULLIF, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("nulls", NULLS_P, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("numeric", NUMERIC, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("object", OBJECT_P, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("of", OF, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("off", OFF, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("offset", OFFSET, RESERVED_KEYWORD, AS_LABEL)
+PG_KEYWORD("oids", OIDS, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("old", OLD, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("on", ON, RESERVED_KEYWORD, AS_LABEL)
+PG_KEYWORD("only", ONLY, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("operator", OPERATOR, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("option", OPTION, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("options", OPTIONS, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("or", OR, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("order", ORDER, RESERVED_KEYWORD, AS_LABEL)
+PG_KEYWORD("ordinality", ORDINALITY, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("others", OTHERS, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("out", OUT_P, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("outer", OUTER_P, TYPE_FUNC_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("over", OVER, UNRESERVED_KEYWORD, AS_LABEL)
+PG_KEYWORD("overlaps", OVERLAPS, TYPE_FUNC_NAME_KEYWORD, AS_LABEL)
+PG_KEYWORD("overlay", OVERLAY, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("overriding", OVERRIDING, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("owned", OWNED, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("owner", OWNER, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("parallel", PARALLEL, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("parameter", PARAMETER, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("parser", PARSER, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("partial", PARTIAL, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("partition", PARTITION, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("passing", PASSING, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("password", PASSWORD, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("placing", PLACING, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("plans", PLANS, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("policy", POLICY, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("position", POSITION, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("preceding", PRECEDING, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("precision", PRECISION, COL_NAME_KEYWORD, AS_LABEL)
+PG_KEYWORD("prepare", PREPARE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("prepared", PREPARED, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("preserve", PRESERVE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("primary", PRIMARY, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("prior", PRIOR, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("privileges", PRIVILEGES, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("procedural", PROCEDURAL, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("procedure", PROCEDURE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("procedures", PROCEDURES, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("program", PROGRAM, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("publication", PUBLICATION, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("quote", QUOTE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("range", RANGE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("read", READ, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("real", REAL, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("reassign", REASSIGN, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("recheck", RECHECK, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("recursive", RECURSIVE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("ref", REF_P, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("references", REFERENCES, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("referencing", REFERENCING, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("refresh", REFRESH, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("reindex", REINDEX, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("relative", RELATIVE_P, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("release", RELEASE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("rename", RENAME, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("repeatable", REPEATABLE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("replace", REPLACE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("replica", REPLICA, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("reset", RESET, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("restart", RESTART, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("restrict", RESTRICT, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("return", RETURN, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("returning", RETURNING, RESERVED_KEYWORD, AS_LABEL)
+PG_KEYWORD("returns", RETURNS, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("revoke", REVOKE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("right", RIGHT, TYPE_FUNC_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("role", ROLE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("rollback", ROLLBACK, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("rollup", ROLLUP, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("routine", ROUTINE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("routines", ROUTINES, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("row", ROW, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("rows", ROWS, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("rule", RULE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("savepoint", SAVEPOINT, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("scalar", SCALAR, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("schema", SCHEMA, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("schemas", SCHEMAS, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("scroll", SCROLL, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("search", SEARCH, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("second", SECOND_P, UNRESERVED_KEYWORD, AS_LABEL)
+PG_KEYWORD("security", SECURITY, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("select", SELECT, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("sequence", SEQUENCE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("sequences", SEQUENCES, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("serializable", SERIALIZABLE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("server", SERVER, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("session", SESSION, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("session_user", SESSION_USER, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("set", SET, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("setof", SETOF, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("sets", SETS, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("share", SHARE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("show", SHOW, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("similar", SIMILAR, TYPE_FUNC_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("simple", SIMPLE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("skip", SKIP, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("smallint", SMALLINT, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("snapshot", SNAPSHOT, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("some", SOME, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("sql", SQL_P, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("stable", STABLE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("standalone", STANDALONE_P, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("start", START, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("statement", STATEMENT, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("statistics", STATISTICS, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("stdin", STDIN, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("stdout", STDOUT, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("storage", STORAGE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("stored", STORED, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("strict", STRICT_P, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("strip", STRIP_P, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("subscription", SUBSCRIPTION, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("substring", SUBSTRING, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("support", SUPPORT, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("symmetric", SYMMETRIC, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("sysid", SYSID, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("system", SYSTEM_P, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("system_user", SYSTEM_USER, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("table", TABLE, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("tables", TABLES, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("tablesample", TABLESAMPLE, TYPE_FUNC_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("tablespace", TABLESPACE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("temp", TEMP, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("template", TEMPLATE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("temporary", TEMPORARY, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("text", TEXT_P, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("then", THEN, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("ties", TIES, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("time", TIME, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("timestamp", TIMESTAMP, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("to", TO, RESERVED_KEYWORD, AS_LABEL)
+PG_KEYWORD("trailing", TRAILING, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("transaction", TRANSACTION, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("transform", TRANSFORM, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("treat", TREAT, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("trigger", TRIGGER, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("trim", TRIM, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("true", TRUE_P, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("truncate", TRUNCATE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("trusted", TRUSTED, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("type", TYPE_P, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("types", TYPES_P, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("uescape", UESCAPE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("unbounded", UNBOUNDED, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("uncommitted", UNCOMMITTED, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("unencrypted", UNENCRYPTED, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("union", UNION, RESERVED_KEYWORD, AS_LABEL)
+PG_KEYWORD("unique", UNIQUE, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("unknown", UNKNOWN, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("unlisten", UNLISTEN, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("unlogged", UNLOGGED, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("until", UNTIL, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("update", UPDATE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("user", USER, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("using", USING, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("vacuum", VACUUM, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("valid", VALID, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("validate", VALIDATE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("validator", VALIDATOR, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("value", VALUE_P, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("values", VALUES, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("varchar", VARCHAR, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("variadic", VARIADIC, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("varying", VARYING, UNRESERVED_KEYWORD, AS_LABEL)
+PG_KEYWORD("verbose", VERBOSE, TYPE_FUNC_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("version", VERSION_P, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("view", VIEW, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("views", VIEWS, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("volatile", VOLATILE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("when", WHEN, RESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("where", WHERE, RESERVED_KEYWORD, AS_LABEL)
+PG_KEYWORD("whitespace", WHITESPACE_P, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("window", WINDOW, RESERVED_KEYWORD, AS_LABEL)
+PG_KEYWORD("with", WITH, RESERVED_KEYWORD, AS_LABEL)
+PG_KEYWORD("within", WITHIN, UNRESERVED_KEYWORD, AS_LABEL)
+PG_KEYWORD("without", WITHOUT, UNRESERVED_KEYWORD, AS_LABEL)
+PG_KEYWORD("work", WORK, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("wrapper", WRAPPER, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("write", WRITE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("xml", XML_P, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("xmlattributes", XMLATTRIBUTES, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("xmlconcat", XMLCONCAT, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("xmlelement", XMLELEMENT, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("xmlexists", XMLEXISTS, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("xmlforest", XMLFOREST, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("xmlnamespaces", XMLNAMESPACES, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("xmlparse", XMLPARSE, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("xmlpi", XMLPI, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("xmlroot", XMLROOT, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("xmlserialize", XMLSERIALIZE, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("xmltable", XMLTABLE, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("year", YEAR_P, UNRESERVED_KEYWORD, AS_LABEL)
+PG_KEYWORD("yes", YES_P, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("zone", ZONE, UNRESERVED_KEYWORD, BARE_LABEL)
diff --git a/contrib/libs/libpq/src/include/pg_config-linux-aarch64.h b/contrib/libs/libpq/src/include/pg_config-linux-aarch64.h
new file mode 100644
index 0000000000..f27c40f1d7
--- /dev/null
+++ b/contrib/libs/libpq/src/include/pg_config-linux-aarch64.h
@@ -0,0 +1,6 @@
+#pragma once
+
+#include "pg_config-linux.h"
+
+/* Define to 1 if you have __get_cpuid. */
+#undef HAVE__GET_CPUID
diff --git a/contrib/libs/libpq/src/include/pg_config-linux.h b/contrib/libs/libpq/src/include/pg_config-linux.h
new file mode 100644
index 0000000000..afcf2967c5
--- /dev/null
+++ b/contrib/libs/libpq/src/include/pg_config-linux.h
@@ -0,0 +1,828 @@
+/* src/include/pg_config.h. Generated from pg_config.h.in by configure. */
+/* src/include/pg_config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define if building universal (internal helper macro) */
+/* #undef AC_APPLE_UNIVERSAL_BUILD */
+
+/* The normal alignment of `double', in bytes. */
+#define ALIGNOF_DOUBLE 8
+
+/* The normal alignment of `int', in bytes. */
+#define ALIGNOF_INT 4
+
+/* The normal alignment of `long', in bytes. */
+#define ALIGNOF_LONG 8
+
+/* The normal alignment of `long long int', in bytes. */
+/* #undef ALIGNOF_LONG_LONG_INT */
+
+/* The normal alignment of `PG_INT128_TYPE', in bytes. */
+#define ALIGNOF_PG_INT128_TYPE 16
+
+/* The normal alignment of `short', in bytes. */
+#define ALIGNOF_SHORT 2
+
+/* Size of a disk block --- this also limits the size of a tuple. You can set
+ it bigger if you need bigger tuples (although TOAST should reduce the need
+ to have large tuples, since fields can be spread across multiple tuples).
+ BLCKSZ must be a power of 2. The maximum possible value of BLCKSZ is
+ currently 2^15 (32768). This is determined by the 15-bit widths of the
+ lp_off and lp_len fields in ItemIdData (see include/storage/itemid.h).
+ Changing BLCKSZ requires an initdb. */
+#define BLCKSZ 8192
+
+/* Saved arguments from configure */
+#define CONFIGURE_ARGS " '--prefix=/var/empty/postgresql-16.1' '--with-openssl' '--with-libxml' '--with-icu' '--sysconfdir=/etc' '--libdir=$(lib)/lib' '--with-system-tzdata=/var/empty/tzdata-2022f/share/zoneinfo' '--enable-debug' '--with-systemd' '--with-ossp-uuid' '--with-lz4' '--with-gssapi' '--without-gssapi' 'CC=cc' 'CXX=g++' 'PKG_CONFIG=pkg-config' 'PKG_CONFIG_PATH=/var/empty/libxcrypt-4.4.30/lib/pkgconfig:/var/empty/zlib-1.2.13-dev/lib/pkgconfig:/var/empty/ncurses-6.3-p20220507-dev/lib/pkgconfig:/var/empty/openssl-3.0.7-dev/lib/pkgconfig:/var/empty/libxml2-2.10.3-dev/lib/pkgconfig:/var/empty/icu4c-72.1-dev/lib/pkgconfig:/var/empty/lz4-1.9.4-dev/lib/pkgconfig:/var/empty/systemd-251.7-dev/lib/pkgconfig:/var/empty/systemd-251.7-dev/share/pkgconfig:/var/empty/libkrb5-1.20-dev/lib/pkgconfig:/var/empty/libossp-uuid-1.6.2/lib/pkgconfig'"
+
+/* Define to the default TCP port number on which the server listens and to
+ which clients will try to connect. This can be overridden at run-time, but
+ it's convenient if your clients have the right default compiled in.
+ (--with-pgport=PORTNUM) */
+#define DEF_PGPORT 5432
+
+/* Define to the default TCP port number as a string constant. */
+#define DEF_PGPORT_STR "5432"
+
+/* Define to the file name extension of dynamically-loadable modules. */
+#define DLSUFFIX ".so"
+
+/* Define to build with GSSAPI support. (--with-gssapi) */
+/* #undef ENABLE_GSS */
+
+/* Define to 1 if you want National Language Support. (--enable-nls) */
+/* #undef ENABLE_NLS */
+
+/* Define to 1 to build client libraries as thread-safe code.
+ (--enable-thread-safety) */
+#define ENABLE_THREAD_SAFETY 1
+
+/* Define to 1 if you have the `append_history' function. */
+#define HAVE_APPEND_HISTORY 1
+
+/* Define to 1 if you have the `ASN1_STRING_get0_data' function. */
+#define HAVE_ASN1_STRING_GET0_DATA 1
+
+/* Define to 1 if you want to use atomics if available. */
+#define HAVE_ATOMICS 1
+
+/* Define to 1 if you have the <atomic.h> header file. */
+/* #undef HAVE_ATOMIC_H */
+
+/* Define to 1 if you have the `backtrace_symbols' function. */
+#define HAVE_BACKTRACE_SYMBOLS 1
+
+/* Define to 1 if you have the `BIO_get_data' function. */
+#define HAVE_BIO_GET_DATA 1
+
+/* Define to 1 if you have the `BIO_meth_new' function. */
+#define HAVE_BIO_METH_NEW 1
+
+/* Define to 1 if your compiler handles computed gotos. */
+#define HAVE_COMPUTED_GOTO 1
+
+/* Define to 1 if you have the `copyfile' function. */
+/* #undef HAVE_COPYFILE */
+
+/* Define to 1 if you have the <copyfile.h> header file. */
+/* #undef HAVE_COPYFILE_H */
+
+/* Define to 1 if you have the <crtdefs.h> header file. */
+/* #undef HAVE_CRTDEFS_H */
+
+/* Define to 1 if you have the `CRYPTO_lock' function. */
+/* #undef HAVE_CRYPTO_LOCK */
+
+/* Define to 1 if you have the declaration of `fdatasync', and to 0 if you
+ don't. */
+#define HAVE_DECL_FDATASYNC 1
+
+/* Define to 1 if you have the declaration of `F_FULLFSYNC', and to 0 if you
+ don't. */
+#define HAVE_DECL_F_FULLFSYNC 0
+
+/* Define to 1 if you have the declaration of
+ `LLVMCreateGDBRegistrationListener', and to 0 if you don't. */
+/* #undef HAVE_DECL_LLVMCREATEGDBREGISTRATIONLISTENER */
+
+/* Define to 1 if you have the declaration of
+ `LLVMCreatePerfJITEventListener', and to 0 if you don't. */
+/* #undef HAVE_DECL_LLVMCREATEPERFJITEVENTLISTENER */
+
+/* Define to 1 if you have the declaration of `LLVMGetHostCPUFeatures', and to
+ 0 if you don't. */
+/* #undef HAVE_DECL_LLVMGETHOSTCPUFEATURES */
+
+/* Define to 1 if you have the declaration of `LLVMGetHostCPUName', and to 0
+ if you don't. */
+/* #undef HAVE_DECL_LLVMGETHOSTCPUNAME */
+
+/* Define to 1 if you have the declaration of `LLVMOrcGetSymbolAddressIn', and
+ to 0 if you don't. */
+/* #undef HAVE_DECL_LLVMORCGETSYMBOLADDRESSIN */
+
+/* Define to 1 if you have the declaration of `posix_fadvise', and to 0 if you
+ don't. */
+#define HAVE_DECL_POSIX_FADVISE 1
+
+/* Define to 1 if you have the declaration of `preadv', and to 0 if you don't.
+ */
+#define HAVE_DECL_PREADV 1
+
+/* Define to 1 if you have the declaration of `pwritev', and to 0 if you
+ don't. */
+#define HAVE_DECL_PWRITEV 1
+
+/* Define to 1 if you have the declaration of `strlcat', and to 0 if you
+ don't. */
+#define HAVE_DECL_STRLCAT 0
+
+/* Define to 1 if you have the declaration of `strlcpy', and to 0 if you
+ don't. */
+#define HAVE_DECL_STRLCPY 0
+
+/* Define to 1 if you have the declaration of `strnlen', and to 0 if you
+ don't. */
+#define HAVE_DECL_STRNLEN 1
+
+/* Define to 1 if you have the <editline/history.h> header file. */
+/* #undef HAVE_EDITLINE_HISTORY_H */
+
+/* Define to 1 if you have the <editline/readline.h> header file. */
+/* #undef HAVE_EDITLINE_READLINE_H */
+
+/* Define to 1 if you have the <execinfo.h> header file. */
+#define HAVE_EXECINFO_H 1
+
+/* Define to 1 if you have the `explicit_bzero' function. */
+#define HAVE_EXPLICIT_BZERO 1
+
+/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
+#define HAVE_FSEEKO 1
+
+/* Define to 1 if you have __atomic_compare_exchange_n(int *, int *, int). */
+#define HAVE_GCC__ATOMIC_INT32_CAS 1
+
+/* Define to 1 if you have __atomic_compare_exchange_n(int64 *, int64 *,
+ int64). */
+#define HAVE_GCC__ATOMIC_INT64_CAS 1
+
+/* Define to 1 if you have __sync_lock_test_and_set(char *) and friends. */
+#define HAVE_GCC__SYNC_CHAR_TAS 1
+
+/* Define to 1 if you have __sync_val_compare_and_swap(int *, int, int). */
+#define HAVE_GCC__SYNC_INT32_CAS 1
+
+/* Define to 1 if you have __sync_lock_test_and_set(int *) and friends. */
+#define HAVE_GCC__SYNC_INT32_TAS 1
+
+/* Define to 1 if you have __sync_val_compare_and_swap(int64 *, int64, int64).
+ */
+#define HAVE_GCC__SYNC_INT64_CAS 1
+
+/* Define to 1 if you have the `getifaddrs' function. */
+#define HAVE_GETIFADDRS 1
+
+/* Define to 1 if you have the `getopt' function. */
+#define HAVE_GETOPT 1
+
+/* Define to 1 if you have the <getopt.h> header file. */
+#define HAVE_GETOPT_H 1
+
+/* Define to 1 if you have the `getopt_long' function. */
+#define HAVE_GETOPT_LONG 1
+
+/* Define to 1 if you have the `getpeereid' function. */
+/* #undef HAVE_GETPEEREID */
+
+/* Define to 1 if you have the `getpeerucred' function. */
+/* #undef HAVE_GETPEERUCRED */
+
+/* Define to 1 if you have the <gssapi_ext.h> header file. */
+/* #undef HAVE_GSSAPI_EXT_H */
+
+/* Define to 1 if you have the <gssapi/gssapi_ext.h> header file. */
+/* #undef HAVE_GSSAPI_GSSAPI_EXT_H */
+
+/* Define to 1 if you have the <gssapi/gssapi.h> header file. */
+/* #undef HAVE_GSSAPI_GSSAPI_H */
+
+/* Define to 1 if you have the <gssapi.h> header file. */
+/* #undef HAVE_GSSAPI_H */
+
+/* Define to 1 if you have the <history.h> header file. */
+/* #undef HAVE_HISTORY_H */
+
+/* Define to 1 if you have the `history_truncate_file' function. */
+#define HAVE_HISTORY_TRUNCATE_FILE 1
+
+/* Define to 1 if you have the `HMAC_CTX_free' function. */
+#define HAVE_HMAC_CTX_FREE 1
+
+/* Define to 1 if you have the `HMAC_CTX_new' function. */
+#define HAVE_HMAC_CTX_NEW 1
+
+/* Define to 1 if you have the <ifaddrs.h> header file. */
+#define HAVE_IFADDRS_H 1
+
+/* Define to 1 if you have the `inet_aton' function. */
+#define HAVE_INET_ATON 1
+
+/* Define to 1 if you have the `inet_pton' function. */
+#define HAVE_INET_PTON 1
+
+/* 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. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the global variable 'int opterr'. */
+#define HAVE_INT_OPTERR 1
+
+/* Define to 1 if you have the global variable 'int optreset'. */
+/* #undef HAVE_INT_OPTRESET */
+
+/* Define to 1 if you have the global variable 'int timezone'. */
+#define HAVE_INT_TIMEZONE 1
+
+/* Define to 1 if __builtin_constant_p(x) implies "i"(x) acceptance. */
+/* #undef HAVE_I_CONSTRAINT__BUILTIN_CONSTANT_P */
+
+/* Define to 1 if you have the `kqueue' function. */
+/* #undef HAVE_KQUEUE */
+
+/* Define to 1 if you have the <langinfo.h> header file. */
+#define HAVE_LANGINFO_H 1
+
+/* Define to 1 if you have the `ldap_initialize' function. */
+/* #undef HAVE_LDAP_INITIALIZE */
+
+/* Define to 1 if you have the `crypto' library (-lcrypto). */
+#define HAVE_LIBCRYPTO 1
+
+/* Define to 1 if you have the `ldap' library (-lldap). */
+/* #undef HAVE_LIBLDAP */
+
+/* Define to 1 if you have the `lz4' library (-llz4). */
+#define HAVE_LIBLZ4 1
+
+/* Define to 1 if you have the `m' library (-lm). */
+#define HAVE_LIBM 1
+
+/* Define to 1 if you have the `pam' library (-lpam). */
+/* #undef HAVE_LIBPAM */
+
+/* Define if you have a function readline library */
+#define HAVE_LIBREADLINE 1
+
+/* Define to 1 if you have the `selinux' library (-lselinux). */
+/* #undef HAVE_LIBSELINUX */
+
+/* Define to 1 if you have the `ssl' library (-lssl). */
+#define HAVE_LIBSSL 1
+
+/* Define to 1 if you have the `wldap32' library (-lwldap32). */
+/* #undef HAVE_LIBWLDAP32 */
+
+/* Define to 1 if you have the `xml2' library (-lxml2). */
+#define HAVE_LIBXML2 1
+
+/* Define to 1 if you have the `xslt' library (-lxslt). */
+/* #undef HAVE_LIBXSLT */
+
+/* Define to 1 if you have the `z' library (-lz). */
+#define HAVE_LIBZ 1
+
+/* Define to 1 if you have the `zstd' library (-lzstd). */
+/* #undef HAVE_LIBZSTD */
+
+/* Define to 1 if the system has the type `locale_t'. */
+#define HAVE_LOCALE_T 1
+
+/* Define to 1 if `long int' works and is 64 bits. */
+#define HAVE_LONG_INT_64 1
+
+/* 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 */
+
+/* Define to 1 if you have the `mbstowcs_l' function. */
+/* #undef HAVE_MBSTOWCS_L */
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `memset_s' function. */
+/* #undef HAVE_MEMSET_S */
+
+/* Define to 1 if you have the `mkdtemp' function. */
+#define HAVE_MKDTEMP 1
+
+/* Define to 1 if you have the `OPENSSL_init_ssl' function. */
+#define HAVE_OPENSSL_INIT_SSL 1
+
+/* Define to 1 if you have the <ossp/uuid.h> header file. */
+/* #undef HAVE_OSSP_UUID_H */
+
+/* Define to 1 if you have the <pam/pam_appl.h> header file. */
+/* #undef HAVE_PAM_PAM_APPL_H */
+
+/* Define to 1 if you have the `posix_fadvise' function. */
+#define HAVE_POSIX_FADVISE 1
+
+/* Define to 1 if you have the `posix_fallocate' function. */
+#define HAVE_POSIX_FALLOCATE 1
+
+/* Define to 1 if you have the `ppoll' function. */
+#define HAVE_PPOLL 1
+
+/* Define if you have POSIX threads libraries and header files. */
+#define HAVE_PTHREAD 1
+
+/* Define to 1 if you have the `pthread_barrier_wait' function. */
+#define HAVE_PTHREAD_BARRIER_WAIT 1
+
+/* Define to 1 if you have the `pthread_is_threaded_np' function. */
+/* #undef HAVE_PTHREAD_IS_THREADED_NP */
+
+/* Have PTHREAD_PRIO_INHERIT. */
+#define HAVE_PTHREAD_PRIO_INHERIT 1
+
+/* Define to 1 if you have the <readline.h> header file. */
+/* #undef HAVE_READLINE_H */
+
+/* Define to 1 if you have the <readline/history.h> header file. */
+#define HAVE_READLINE_HISTORY_H 1
+
+/* Define to 1 if you have the <readline/readline.h> header file. */
+#define HAVE_READLINE_READLINE_H 1
+
+/* Define to 1 if you have the `rl_completion_matches' function. */
+#define HAVE_RL_COMPLETION_MATCHES 1
+
+/* Define to 1 if you have the global variable 'rl_completion_suppress_quote'.
+ */
+#define HAVE_RL_COMPLETION_SUPPRESS_QUOTE 1
+
+/* Define to 1 if you have the `rl_filename_completion_function' function. */
+#define HAVE_RL_FILENAME_COMPLETION_FUNCTION 1
+
+/* Define to 1 if you have the global variable 'rl_filename_quote_characters'.
+ */
+#define HAVE_RL_FILENAME_QUOTE_CHARACTERS 1
+
+/* Define to 1 if you have the global variable 'rl_filename_quoting_function'.
+ */
+#define HAVE_RL_FILENAME_QUOTING_FUNCTION 1
+
+/* Define to 1 if you have the `rl_reset_screen_size' function. */
+#define HAVE_RL_RESET_SCREEN_SIZE 1
+
+/* Define to 1 if you have the `rl_variable_bind' function. */
+#define HAVE_RL_VARIABLE_BIND 1
+
+/* Define to 1 if you have the <security/pam_appl.h> header file. */
+/* #undef HAVE_SECURITY_PAM_APPL_H */
+
+/* Define to 1 if you have the `setproctitle' function. */
+/* #undef HAVE_SETPROCTITLE */
+
+/* Define to 1 if you have the `setproctitle_fast' function. */
+/* #undef HAVE_SETPROCTITLE_FAST */
+
+/* Define to 1 if the system has the type `socklen_t'. */
+#define HAVE_SOCKLEN_T 1
+
+/* Define to 1 if you have spinlocks. */
+#define HAVE_SPINLOCKS 1
+
+/* Define to 1 if you have the `SSL_CTX_set_cert_cb' function. */
+#define HAVE_SSL_CTX_SET_CERT_CB 1
+
+/* Define to 1 if stdbool.h conforms to C99. */
+#define HAVE_STDBOOL_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strchrnul' function. */
+#define HAVE_STRCHRNUL 1
+
+/* Define to 1 if you have the `strerror_r' function. */
+#define HAVE_STRERROR_R 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strlcat' function. */
+/* #undef HAVE_STRLCAT */
+
+/* Define to 1 if you have the `strlcpy' function. */
+/* #undef HAVE_STRLCPY */
+
+/* Define to 1 if you have the `strnlen' function. */
+#define HAVE_STRNLEN 1
+
+/* Define to 1 if you have the `strsignal' function. */
+#define HAVE_STRSIGNAL 1
+
+/* Define to 1 if the system has the type `struct option'. */
+#define HAVE_STRUCT_OPTION 1
+
+/* Define to 1 if `sa_len' is a member of `struct sockaddr'. */
+/* #undef HAVE_STRUCT_SOCKADDR_SA_LEN */
+
+/* Define to 1 if `tm_zone' is a member of `struct tm'. */
+#define HAVE_STRUCT_TM_TM_ZONE 1
+
+/* Define to 1 if you have the `syncfs' function. */
+#define HAVE_SYNCFS 1
+
+/* Define to 1 if you have the `sync_file_range' function. */
+#define HAVE_SYNC_FILE_RANGE 1
+
+/* Define to 1 if you have the syslog interface. */
+#define HAVE_SYSLOG 1
+
+/* Define to 1 if you have the <sys/epoll.h> header file. */
+#define HAVE_SYS_EPOLL_H 1
+
+/* Define to 1 if you have the <sys/event.h> header file. */
+/* #undef HAVE_SYS_EVENT_H */
+
+/* Define to 1 if you have the <sys/personality.h> header file. */
+#define HAVE_SYS_PERSONALITY_H 1
+
+/* Define to 1 if you have the <sys/prctl.h> header file. */
+#define HAVE_SYS_PRCTL_H 1
+
+/* Define to 1 if you have the <sys/procctl.h> header file. */
+/* #undef HAVE_SYS_PROCCTL_H */
+
+/* Define to 1 if you have the <sys/signalfd.h> header file. */
+#define HAVE_SYS_SIGNALFD_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <sys/ucred.h> header file. */
+/* #undef HAVE_SYS_UCRED_H */
+
+/* Define to 1 if you have the <termios.h> header file. */
+#define HAVE_TERMIOS_H 1
+
+/* Define to 1 if your compiler understands `typeof' or something similar. */
+#define HAVE_TYPEOF 1
+
+/* 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 */
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `uselocale' function. */
+#define HAVE_USELOCALE 1
+
+/* Define to 1 if you have BSD UUID support. */
+/* #undef HAVE_UUID_BSD */
+
+/* Define to 1 if you have E2FS UUID support. */
+/* #undef HAVE_UUID_E2FS */
+
+/* Define to 1 if you have the <uuid.h> header file. */
+#define HAVE_UUID_H 1
+
+/* Define to 1 if you have OSSP UUID support. */
+#define HAVE_UUID_OSSP 1
+
+/* Define to 1 if you have the <uuid/uuid.h> header file. */
+/* #undef HAVE_UUID_UUID_H */
+
+/* Define to 1 if your compiler knows the visibility("hidden") attribute. */
+#define HAVE_VISIBILITY_ATTRIBUTE 1
+
+/* Define to 1 if you have the `wcstombs_l' function. */
+/* #undef HAVE_WCSTOMBS_L */
+
+/* Define to 1 if you have the `X509_get_signature_info' function. */
+#define HAVE_X509_GET_SIGNATURE_INFO 1
+
+/* Define to 1 if you have the `X509_get_signature_nid' function. */
+#define HAVE_X509_GET_SIGNATURE_NID 1
+
+/* Define to 1 if the assembler supports X86_64's POPCNTQ instruction. */
+#define HAVE_X86_64_POPCNTQ 1
+
+/* Define to 1 if the system has the type `_Bool'. */
+#define HAVE__BOOL 1
+
+/* Define to 1 if your compiler understands __builtin_bswap16. */
+#define HAVE__BUILTIN_BSWAP16 1
+
+/* Define to 1 if your compiler understands __builtin_bswap32. */
+#define HAVE__BUILTIN_BSWAP32 1
+
+/* Define to 1 if your compiler understands __builtin_bswap64. */
+#define HAVE__BUILTIN_BSWAP64 1
+
+/* Define to 1 if your compiler understands __builtin_clz. */
+#define HAVE__BUILTIN_CLZ 1
+
+/* Define to 1 if your compiler understands __builtin_constant_p. */
+#define HAVE__BUILTIN_CONSTANT_P 1
+
+/* Define to 1 if your compiler understands __builtin_ctz. */
+#define HAVE__BUILTIN_CTZ 1
+
+/* Define to 1 if your compiler understands __builtin_frame_address. */
+#define HAVE__BUILTIN_FRAME_ADDRESS 1
+
+/* Define to 1 if your compiler understands __builtin_$op_overflow. */
+#define HAVE__BUILTIN_OP_OVERFLOW 1
+
+/* Define to 1 if your compiler understands __builtin_popcount. */
+#define HAVE__BUILTIN_POPCOUNT 1
+
+/* Define to 1 if your compiler understands __builtin_types_compatible_p. */
+#define HAVE__BUILTIN_TYPES_COMPATIBLE_P 1
+
+/* Define to 1 if your compiler understands __builtin_unreachable. */
+#define HAVE__BUILTIN_UNREACHABLE 1
+
+/* Define to 1 if you have the `_configthreadlocale' function. */
+/* #undef HAVE__CONFIGTHREADLOCALE */
+
+/* Define to 1 if you have __cpuid. */
+/* #undef HAVE__CPUID */
+
+/* Define to 1 if you have __get_cpuid. */
+#define HAVE__GET_CPUID 1
+
+/* Define to 1 if your compiler understands _Static_assert. */
+#define HAVE__STATIC_ASSERT 1
+
+/* Define to the appropriate printf length modifier for 64-bit ints. */
+#define INT64_MODIFIER "l"
+
+/* Define to 1 if `locale_t' requires <xlocale.h>. */
+/* #undef LOCALE_T_IN_XLOCALE */
+
+/* Define as the maximum alignment requirement of any C data type. */
+#define MAXIMUM_ALIGNOF 8
+
+/* Define bytes to use libc memset(). */
+#define MEMSET_LOOP_LIMIT 1024
+
+/* Define to the OpenSSL API version in use. This avoids deprecation warnings
+ from newer OpenSSL versions. */
+/* #define OPENSSL_API_COMPAT 0x10001000L */
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "pgsql-bugs@lists.postgresql.org"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "PostgreSQL"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "PostgreSQL 16.1"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "postgresql"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL "https://www.postgresql.org/"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "16.1"
+
+/* Define to the name of a signed 128-bit integer type. */
+#define PG_INT128_TYPE __int128
+
+/* Define to the name of a signed 64-bit integer type. */
+#define PG_INT64_TYPE long int
+
+/* Define to the name of the default PostgreSQL service principal in Kerberos
+ (GSSAPI). (--with-krb-srvnam=NAME) */
+#define PG_KRB_SRVNAM "postgres"
+
+/* PostgreSQL major version as a string */
+#define PG_MAJORVERSION "16"
+
+/* PostgreSQL major version number */
+#define PG_MAJORVERSION_NUM 16
+
+/* PostgreSQL minor version number */
+#define PG_MINORVERSION_NUM 1
+
+/* Define to best printf format archetype, usually gnu_printf if available. */
+#define PG_PRINTF_ATTRIBUTE gnu_printf
+
+/* Define to 1 to use <stdbool.h> to define type bool. */
+#define PG_USE_STDBOOL 1
+
+/* PostgreSQL version as a string */
+#define PG_VERSION "16.1"
+
+/* PostgreSQL version as a number */
+#define PG_VERSION_NUM 160001
+
+/* A string containing the version number, platform, and C compiler */
+#define PG_VERSION_STR "PostgreSQL 16.1 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 11.3.0, 64-bit"
+
+/* Define to 1 to allow profiling output to be saved separately for each
+ process. */
+/* #undef PROFILE_PID_DIR */
+
+/* Define to necessary symbol if this constant uses a non-standard name on
+ your system. */
+/* #undef PTHREAD_CREATE_JOINABLE */
+
+/* RELSEG_SIZE is the maximum number of blocks allowed in one disk file. Thus,
+ the maximum size of a single file is RELSEG_SIZE * BLCKSZ; relations bigger
+ than that are divided into multiple files. RELSEG_SIZE * BLCKSZ must be
+ less than your OS' limit on file size. This is often 2 GB or 4GB in a
+ 32-bit operating system, unless you have large file support enabled. By
+ default, we make the limit 1 GB to avoid any possible integer-overflow
+ problems within the OS. A limit smaller than necessary only means we divide
+ a large relation into more chunks than necessary, so it seems best to err
+ in the direction of a small limit. A power-of-2 value is recommended to
+ save a few cycles in md.c, but is not absolutely required. Changing
+ RELSEG_SIZE requires an initdb. */
+#define RELSEG_SIZE 131072
+
+/* The size of `bool', as computed by sizeof. */
+#define SIZEOF_BOOL 1
+
+/* The size of `long', as computed by sizeof. */
+#define SIZEOF_LONG 8
+
+/* The size of `off_t', as computed by sizeof. */
+#define SIZEOF_OFF_T 8
+
+/* The size of `size_t', as computed by sizeof. */
+#define SIZEOF_SIZE_T 8
+
+/* The size of `void *', as computed by sizeof. */
+#define SIZEOF_VOID_P 8
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define to 1 if strerror_r() returns int. */
+/* #undef STRERROR_R_INT */
+
+/* Define to 1 to use ARMv8 CRC Extension. */
+/* #undef USE_ARMV8_CRC32C */
+
+/* Define to 1 to use ARMv8 CRC Extension with a runtime check. */
+/* #undef USE_ARMV8_CRC32C_WITH_RUNTIME_CHECK */
+
+/* Define to 1 to build with assertion checks. (--enable-cassert) */
+/* #undef USE_ASSERT_CHECKING */
+
+/* Define to 1 to build with Bonjour support. (--with-bonjour) */
+/* #undef USE_BONJOUR */
+
+/* Define to 1 to build with BSD Authentication support. (--with-bsd-auth) */
+/* #undef USE_BSD_AUTH */
+
+/* Define to build with ICU support. (--with-icu) */
+#define USE_ICU 1
+
+/* Define to 1 to build with LDAP support. (--with-ldap) */
+/* #undef USE_LDAP */
+
+/* Define to 1 to build with XML support. (--with-libxml) */
+#define USE_LIBXML 1
+
+/* Define to 1 to use XSLT support when building contrib/xml2.
+ (--with-libxslt) */
+/* #undef USE_LIBXSLT */
+
+/* Define to 1 to build with LLVM based JIT support. (--with-llvm) */
+/* #undef USE_LLVM */
+
+/* Define to 1 to build with LZ4 support. (--with-lz4) */
+#define USE_LZ4 1
+
+/* Define to select named POSIX semaphores. */
+/* #undef USE_NAMED_POSIX_SEMAPHORES */
+
+/* Define to 1 to build with OpenSSL support. (--with-ssl=openssl) */
+#define USE_OPENSSL 1
+
+/* Define to 1 to build with PAM support. (--with-pam) */
+/* #undef USE_PAM */
+
+/* Define to 1 to use software CRC-32C implementation (slicing-by-8). */
+/* #undef USE_SLICING_BY_8_CRC32C */
+
+/* Define to 1 use Intel SSE 4.2 CRC instructions. */
+/* #undef USE_SSE42_CRC32C */
+
+/* Define to 1 to use Intel SSE 4.2 CRC instructions with a runtime check. */
+#define USE_SSE42_CRC32C_WITH_RUNTIME_CHECK 1
+
+/* Define to build with systemd support. (--with-systemd) */
+#define USE_SYSTEMD 1
+
+/* Define to select SysV-style semaphores. */
+/* #undef USE_SYSV_SEMAPHORES */
+
+/* Define to select SysV-style shared memory. */
+#define USE_SYSV_SHARED_MEMORY 1
+
+/* Define to select unnamed POSIX semaphores. */
+#define USE_UNNAMED_POSIX_SEMAPHORES 1
+
+/* Define to select Win32-style semaphores. */
+/* #undef USE_WIN32_SEMAPHORES */
+
+/* Define to select Win32-style shared memory. */
+/* #undef USE_WIN32_SHARED_MEMORY */
+
+/* Define to 1 to build with ZSTD support. (--with-zstd) */
+/* #undef USE_ZSTD */
+
+/* Define to 1 if `wcstombs_l' requires <xlocale.h>. */
+/* #undef WCSTOMBS_L_IN_XLOCALE */
+
+/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
+ significant byte first (like Motorola and SPARC, unlike Intel). */
+#if defined AC_APPLE_UNIVERSAL_BUILD
+# if defined __BIG_ENDIAN__
+# define WORDS_BIGENDIAN 1
+# endif
+#else
+# ifndef WORDS_BIGENDIAN
+/* # undef WORDS_BIGENDIAN */
+# endif
+#endif
+
+/* Size of a WAL file block. This need have no particular relation to BLCKSZ.
+ XLOG_BLCKSZ must be a power of 2, and if your system supports O_DIRECT I/O,
+ XLOG_BLCKSZ must be a multiple of the alignment requirement for direct-I/O
+ buffers, else direct I/O may fail. Changing XLOG_BLCKSZ requires an initdb.
+ */
+#define XLOG_BLCKSZ 8192
+
+
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
+/* #undef _LARGEFILE_SOURCE */
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
+
+/* Define to keyword to use for C99 restrict support, or to nothing if not
+ supported */
+#define pg_restrict __restrict
+
+/* Define to the equivalent of the C99 'restrict' keyword, or to
+ nothing if this is not supported. Do not define if restrict is
+ supported directly. */
+#define restrict __restrict
+/* Work around a bug in Sun C++: it does not support _Restrict or
+ __restrict__, even though the corresponding Sun C compiler ends up with
+ "#define restrict _Restrict" or "#define restrict __restrict__" in the
+ previous line. Perhaps some future version of Sun C++ will work with
+ restrict; if so, hopefully it defines __RESTRICT like Sun C does. */
+#if defined __SUNPRO_CC && !defined __RESTRICT
+# define _Restrict
+# define __restrict__
+#endif
+
+/* Define to how the compiler spells `typeof'. */
+/* #undef typeof */
diff --git a/contrib/libs/libpq/src/include/pg_config-osx-arm64.h b/contrib/libs/libpq/src/include/pg_config-osx-arm64.h
new file mode 100644
index 0000000000..dde70a44c9
--- /dev/null
+++ b/contrib/libs/libpq/src/include/pg_config-osx-arm64.h
@@ -0,0 +1,159 @@
+#pragma once
+
+#include "pg_config-linux.h"
+
+/* Define to 1 if you have __get_cpuid. */
+#undef HAVE__GET_CPUID
+
+/* Define to 1 if you have the `append_history' function. */
+#undef HAVE_APPEND_HISTORY
+
+/* Define to 1 if you have the `ASN1_STRING_get0_data' function. */
+#undef HAVE_ASN1_STRING_GET0_DATA
+
+/* Define to 1 if you have the `copyfile' function. */
+#define HAVE_COPYFILE 1
+
+/* Define to 1 if you have the <copyfile.h> header file. */
+#define HAVE_COPYFILE_H 1
+
+/* Define to 1 if you have the <crypt.h> header file. */
+#undef HAVE_CRYPT_H
+
+/* Define to 1 if you have the declaration of `fdatasync', and to 0 if you
+ don't. */
+#undef HAVE_DECL_FDATASYNC
+#define HAVE_DECL_FDATASYNC 0
+
+/* Define to 1 if you have the declaration of `F_FULLFSYNC', and to 0 if you
+ don't. */
+#undef HAVE_DECL_F_FULLFSYNC
+#define HAVE_DECL_F_FULLFSYNC 1
+
+/* Define to 1 if you have the declaration of `snprintf', and to 0 if you
+ don't. */
+#define HAVE_DECL_SNPRINTF 1
+
+/* Define to 1 if you have the declaration of `strlcat', and to 0 if you
+ don't. */
+#undef HAVE_DECL_STRLCAT
+#define HAVE_DECL_STRLCAT 1
+
+/* Define to 1 if you have the declaration of `strlcpy', and to 0 if you
+ don't. */
+#undef HAVE_DECL_STRLCPY
+#define HAVE_DECL_STRLCPY 1
+
+/* Define to 1 if you have the declaration of `sys_siglist', and to 0 if you
+ don't. */
+#define HAVE_DECL_SYS_SIGLIST 1
+
+/* Define to 1 if you have the declaration of `vsnprintf', and to 0 if you
+ don't. */
+#define HAVE_DECL_VSNPRINTF 1
+
+/* Define to 1 if you have the <dld.h> header file. */
+#undef HAVE_DLD_H
+
+/* Define to 1 if you have the `fls' function. */
+#define HAVE_FLS 1
+
+/* Define to 1 if you have the `gethostbyname_r' function. */
+#undef HAVE_GETHOSTBYNAME_R
+
+/* Define to 1 if you have the `getpeereid' function. */
+#define HAVE_GETPEEREID 1
+
+/* Define to 1 if you have the `mbstowcs_l' function. */
+#define HAVE_MBSTOWCS_L 1
+
+/* Define to 1 if you have the `posix_fadvise' function. */
+#undef HAVE_POSIX_FADVISE
+
+/* Define to 1 if you have the `posix_fallocate' function. */
+#undef HAVE_POSIX_FALLOCATE
+
+/* Define to 1 if you have the `ppoll' function. */
+#undef HAVE_PPOLL
+
+/* Define to 1 if you have the `pread' function. */
+#undef HAVE_PREAD
+
+/* Define to 1 if you have the `pthread_is_threaded_np' function. */
+#define HAVE_PTHREAD_IS_THREADED_NP 1
+
+/* Define to 1 if you have the `pwrite' function. */
+#undef HAVE_PWRITE
+
+/* Define to 1 if you have the `rl_reset_screen_size' function. */
+#undef HAVE_RL_RESET_SCREEN_SIZE
+
+/* Define to 1 if you have the `snprintf' function. */
+#define HAVE_SNPRINTF 1
+
+/* Define to 1 if you have the `strchrnul' function. */
+#undef HAVE_STRCHRNUL
+
+/* Define to 1 if you have the `strerror_r' function. */
+#define HAVE_STRERROR_R 1
+
+/* Define to 1 if you have the `strlcat' function. */
+#define HAVE_STRLCAT 1
+
+/* Define to 1 if you have the `strlcpy' function. */
+#define HAVE_STRLCPY 1
+
+/* Define to 1 if `sa_len' is a member of `struct sockaddr'. */
+#define HAVE_STRUCT_SOCKADDR_SA_LEN 1
+
+/* Define to 1 if `ss_len' is a member of `struct sockaddr_storage'. */
+#define HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN 1
+
+/* Define to 1 if you have the `sync_file_range' function. */
+#undef HAVE_SYNC_FILE_RANGE
+
+/* Define to 1 if you have the <sys/epoll.h> header file. */
+#undef HAVE_SYS_EPOLL_H
+
+/* Define to 1 if you have the <sys/sockio.h> header file. */
+#define HAVE_SYS_SOCKIO_H 1
+
+/* Define to 1 if you have the <sys/ucred.h> header file. */
+#define HAVE_SYS_UCRED_H 1
+
+/* Define to 1 if you have the `towlower' function. */
+#define HAVE_TOWLOWER 1
+
+/* Define to 1 if you have the <uuid.h> header file. */
+/* #undef HAVE_UUID_H */
+
+/* Define to 1 if you have OSSP UUID support. */
+/* #undef HAVE_UUID_OSSP */
+
+/* Define to 1 if you have the `vsnprintf' function. */
+#define HAVE_VSNPRINTF 1
+
+/* Define to 1 if you have the `wcstombs_l' function. */
+#define HAVE_WCSTOMBS_L 1
+
+/* Define to 1 if `locale_t' requires <xlocale.h>. */
+#define LOCALE_T_IN_XLOCALE 1
+
+/* Define to gnu_printf if compiler supports it, else printf. */
+#undef PG_PRINTF_ATTRIBUTE
+#define PG_PRINTF_ATTRIBUTE printf
+
+/* Define to 1 if strerror_r() returns int. */
+#define STRERROR_R_INT 1
+
+/* Define to build with systemd support. (--with-systemd) */
+/* #undef USE_SYSTEMD */
+
+/* Define to select SysV-style semaphores. */
+#define USE_SYSV_SEMAPHORES 1
+
+/* Define to select unnamed POSIX semaphores. */
+/* #undef USE_UNNAMED_POSIX_SEMAPHORES */
+
+/* Define to 1 if `wcstombs_l' requires <xlocale.h>. */
+#define WCSTOMBS_L_IN_XLOCALE 1
diff --git a/contrib/libs/libpq/src/include/pg_config-osx.h b/contrib/libs/libpq/src/include/pg_config-osx.h
new file mode 100644
index 0000000000..4b1a8a294c
--- /dev/null
+++ b/contrib/libs/libpq/src/include/pg_config-osx.h
@@ -0,0 +1,156 @@
+#pragma once
+
+#include "pg_config-linux.h"
+
+/* Define to 1 if you have the `append_history' function. */
+#undef HAVE_APPEND_HISTORY
+
+/* Define to 1 if you have the `ASN1_STRING_get0_data' function. */
+#undef HAVE_ASN1_STRING_GET0_DATA
+
+/* Define to 1 if you have the `copyfile' function. */
+#define HAVE_COPYFILE 1
+
+/* Define to 1 if you have the <copyfile.h> header file. */
+#define HAVE_COPYFILE_H 1
+
+/* Define to 1 if you have the <crypt.h> header file. */
+#undef HAVE_CRYPT_H
+
+/* Define to 1 if you have the declaration of `fdatasync', and to 0 if you
+ don't. */
+#undef HAVE_DECL_FDATASYNC
+#define HAVE_DECL_FDATASYNC 0
+
+/* Define to 1 if you have the declaration of `F_FULLFSYNC', and to 0 if you
+ don't. */
+#undef HAVE_DECL_F_FULLFSYNC
+#define HAVE_DECL_F_FULLFSYNC 1
+
+/* Define to 1 if you have the declaration of `snprintf', and to 0 if you
+ don't. */
+#define HAVE_DECL_SNPRINTF 1
+
+/* Define to 1 if you have the declaration of `strlcat', and to 0 if you
+ don't. */
+#undef HAVE_DECL_STRLCAT
+#define HAVE_DECL_STRLCAT 1
+
+/* Define to 1 if you have the declaration of `strlcpy', and to 0 if you
+ don't. */
+#undef HAVE_DECL_STRLCPY
+#define HAVE_DECL_STRLCPY 1
+
+/* Define to 1 if you have the declaration of `sys_siglist', and to 0 if you
+ don't. */
+#define HAVE_DECL_SYS_SIGLIST 1
+
+/* Define to 1 if you have the declaration of `vsnprintf', and to 0 if you
+ don't. */
+#define HAVE_DECL_VSNPRINTF 1
+
+/* Define to 1 if you have the <dld.h> header file. */
+#undef HAVE_DLD_H
+
+/* Define to 1 if you have the `fls' function. */
+#define HAVE_FLS 1
+
+/* Define to 1 if you have the `gethostbyname_r' function. */
+#undef HAVE_GETHOSTBYNAME_R
+
+/* Define to 1 if you have the `getpeereid' function. */
+#define HAVE_GETPEEREID 1
+
+/* Define to 1 if you have the `mbstowcs_l' function. */
+#define HAVE_MBSTOWCS_L 1
+
+/* Define to 1 if you have the `posix_fadvise' function. */
+#undef HAVE_POSIX_FADVISE
+
+/* Define to 1 if you have the `posix_fallocate' function. */
+#undef HAVE_POSIX_FALLOCATE
+
+/* Define to 1 if you have the `ppoll' function. */
+#undef HAVE_PPOLL
+
+/* Define to 1 if you have the `pread' function. */
+#undef HAVE_PREAD
+
+/* Define to 1 if you have the `pthread_is_threaded_np' function. */
+#define HAVE_PTHREAD_IS_THREADED_NP 1
+
+/* Define to 1 if you have the `pwrite' function. */
+#undef HAVE_PWRITE
+
+/* Define to 1 if you have the `rl_reset_screen_size' function. */
+#undef HAVE_RL_RESET_SCREEN_SIZE
+
+/* Define to 1 if you have the `snprintf' function. */
+#define HAVE_SNPRINTF 1
+
+/* Define to 1 if you have the `strchrnul' function. */
+#undef HAVE_STRCHRNUL
+
+/* Define to 1 if you have the `strerror_r' function. */
+#define HAVE_STRERROR_R 1
+
+/* Define to 1 if you have the `strlcat' function. */
+#define HAVE_STRLCAT 1
+
+/* Define to 1 if you have the `strlcpy' function. */
+#define HAVE_STRLCPY 1
+
+/* Define to 1 if `sa_len' is a member of `struct sockaddr'. */
+#define HAVE_STRUCT_SOCKADDR_SA_LEN 1
+
+/* Define to 1 if `ss_len' is a member of `struct sockaddr_storage'. */
+#define HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN 1
+
+/* Define to 1 if you have the `sync_file_range' function. */
+#undef HAVE_SYNC_FILE_RANGE
+
+/* Define to 1 if you have the <sys/epoll.h> header file. */
+#undef HAVE_SYS_EPOLL_H
+
+/* Define to 1 if you have the <sys/sockio.h> header file. */
+#define HAVE_SYS_SOCKIO_H 1
+
+/* Define to 1 if you have the <sys/ucred.h> header file. */
+#define HAVE_SYS_UCRED_H 1
+
+/* Define to 1 if you have the `towlower' function. */
+#define HAVE_TOWLOWER 1
+
+/* Define to 1 if you have the <uuid.h> header file. */
+/* #undef HAVE_UUID_H */
+
+/* Define to 1 if you have OSSP UUID support. */
+/* #undef HAVE_UUID_OSSP */
+
+/* Define to 1 if you have the `vsnprintf' function. */
+#define HAVE_VSNPRINTF 1
+
+/* Define to 1 if you have the `wcstombs_l' function. */
+#define HAVE_WCSTOMBS_L 1
+
+/* Define to 1 if `locale_t' requires <xlocale.h>. */
+#define LOCALE_T_IN_XLOCALE 1
+
+/* Define to gnu_printf if compiler supports it, else printf. */
+#undef PG_PRINTF_ATTRIBUTE
+#define PG_PRINTF_ATTRIBUTE printf
+
+/* Define to 1 if strerror_r() returns int. */
+#define STRERROR_R_INT 1
+
+/* Define to build with systemd support. (--with-systemd) */
+/* #undef USE_SYSTEMD */
+
+/* Define to select SysV-style semaphores. */
+#define USE_SYSV_SEMAPHORES 1
+
+/* Define to select unnamed POSIX semaphores. */
+/* #undef USE_UNNAMED_POSIX_SEMAPHORES */
+
+/* Define to 1 if `wcstombs_l' requires <xlocale.h>. */
+#define WCSTOMBS_L_IN_XLOCALE 1
diff --git a/contrib/libs/libpq/src/include/pg_config-win.h b/contrib/libs/libpq/src/include/pg_config-win.h
new file mode 100644
index 0000000000..9574513dc0
--- /dev/null
+++ b/contrib/libs/libpq/src/include/pg_config-win.h
@@ -0,0 +1,318 @@
+#pragma once
+
+#include "pg_config-linux.h"
+
+/* Define to the type of arg 1 of 'accept' */
+#define ACCEPT_TYPE_ARG1 unsigned int
+
+/* Define to the type of arg 3 of 'accept' */
+#define ACCEPT_TYPE_ARG3 int
+
+/* Define to the return type of 'accept' */
+#define ACCEPT_TYPE_RETURN unsigned int PASCAL
+
+/* Define to 1 if you have the `clock_gettime' function. */
+#undef HAVE_CLOCK_GETTIME
+
+/* Define to 1 if your compiler handles computed gotos. */
+#undef HAVE_COMPUTED_GOTO
+
+/* Define to 1 if you have the `crypt' function. */
+#undef HAVE_CRYPT
+
+/* Define to 1 if you have the <crypt.h> header file. */
+#undef HAVE_CRYPT_H
+
+/* Define to 1 if you have the declaration of `posix_fadvise', and to 0 if you
+ * don't. */
+#undef HAVE_DECL_POSIX_FADVISE
+
+/* Define to 1 if you have the declaration of `RTLD_GLOBAL', and to 0 if you
+ don't. */
+#undef HAVE_DECL_RTLD_GLOBAL
+
+/* Define to 1 if you have the declaration of `RTLD_NOW', and to 0 if you
+ don't. */
+#undef HAVE_DECL_RTLD_NOW
+
+/* Define to 1 if you have the declaration of `strlcat', and to 0 if you
+ don't. */
+#define HAVE_DECL_STRLCAT 0
+
+/* Define to 1 if you have the declaration of `strlcpy', and to 0 if you
+ don't. */
+#define HAVE_DECL_STRLCPY 0
+
+/* Define to 1 if you have the `dlopen' function. */
+#undef HAVE_DLOPEN
+
+/* Define to 1 if you have the `fdatasync' function. */
+#undef HAVE_FDATASYNC
+
+/* Define to 1 if you have __atomic_compare_exchange_n(int *, int *, int). */
+#undef HAVE_GCC__ATOMIC_INT32_CAS
+
+/* Define to 1 if you have __atomic_compare_exchange_n(int64 *, int64 *,
+ int64). */
+#undef HAVE_GCC__ATOMIC_INT64_CAS
+
+/* Define to 1 if you have __sync_lock_test_and_set(char *) and friends. */
+#undef HAVE_GCC__SYNC_CHAR_TAS
+
+/* Define to 1 if you have the `getaddrinfo' function. */
+#undef HAVE_GETADDRINFO
+
+/* Define to 1 if you have the `gethostbyname_r' function. */
+#undef HAVE_GETHOSTBYNAME_R
+
+/* Define to 1 if you have the `getopt' function. */
+#undef HAVE_GETOPT
+
+/* Define to 1 if you have the <getopt.h> header file. */
+#undef HAVE_GETOPT_H
+
+/* Define to 1 if you have the `getopt_long' function. */
+#undef HAVE_GETOPT_LONG
+
+/* Define to 1 if you have the `getpwuid_r' function. */
+#undef HAVE_GETPWUID_R
+
+/* Define to 1 if you have the `getrlimit' function. */
+#undef HAVE_RLIMIT
+
+/* Define to 1 if you have the `getrusage' function. */
+#undef HAVE_GETRUSAGE
+
+/* Define to 1 if you have the `inet_aton' function. */
+#undef HAVE_INET_ATON
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <langinfo.h> header file. */
+#undef HAVE_LANGINFO_H
+
+/* Define to 1 if you have the `crypto' library (-lcrypto). */
+#undef HAVE_LIBCRYPTO
+
+/* Define to 1 if `long int' works and is 64 bits. */
+#define HAVE_LONG_INT_64 1
+
+/* Define to 1 if the system has the type `long long int'. */
+#define HAVE_LONG_LONG_INT 1
+
+/* Define to 1 if you have the `mbstowcs_l' function. */
+#define HAVE_MBSTOWCS_L 1
+
+/* Define to 1 if the system has the type `MINIDUMP_TYPE'. */
+#define HAVE_MINIDUMP_TYPE 1
+
+/* Define to 1 if you have the `mkdtemp' function. */
+#undef HAVE_MKDTEMP
+
+/* Define to 1 if you have the <netinet/tcp.h> header file. */
+#undef HAVE_NETINET_TCP_H
+
+/* Define to 1 if you have the `poll' function. */
+#undef HAVE_POLL
+
+/* Define to 1 if you have the <poll.h> header file. */
+#undef HAVE_POLL_H
+
+/* Define to 1 if you have the `posix_fadvise' function. */
+#undef HAVE_POSIX_FADVISE
+
+/* Define to 1 if you have the `posix_fallocate' function. */
+#undef HAVE_POSIX_FALLOCATE
+
+/* Define to 1 if you have the `ppoll' function. */
+#undef HAVE_PPOLL
+
+/* Define to 1 if you have the `pread' function. */
+#undef HAVE_PREAD
+
+/* Define if you have POSIX threads libraries and header files. */
+#undef HAVE_PTHREAD
+
+/* Have PTHREAD_PRIO_INHERIT. */
+#define HAVE_PTHREAD_PRIO_INHERIT 1
+
+/* Define to 1 if you have the `pwrite' function. */
+#undef HAVE_PWRITE
+
+/* Define to 1 if you have the `readlink' function. */
+#undef HAVE_READLINK
+
+/* Define to 1 if you have the global variable
+ 'rl_completion_append_character'. */
+#undef HAVE_RL_COMPLETION_APPEND_CHARACTER
+
+/* Define to 1 if you have the `rl_completion_matches' function. */
+#undef HAVE_RL_COMPLETION_MATCHES
+
+/* Define to 1 if you have the `rl_filename_completion_function' function. */
+#undef HAVE_RL_FILENAME_COMPLETION_FUNCTION
+
+/* Define to 1 if you have the `setsid' function. */
+#undef HAVE_SETSID
+
+/* Define to 1 if you have the `strchrnul' function. */
+#undef HAVE_STRCHRNUL
+
+/* Define to 1 if you have the `strerror_r' function. */
+#undef HAVE_STRERROR_R
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the `strsignal' function. */
+#undef HAVE_STRSIGNAL
+
+/* Define to 1 if the system has the type `struct option'. */
+#undef HAVE_STRUCT_OPTION
+
+/* Define to 1 if `tm_zone' is member of `struct tm'. */
+#undef HAVE_STRUCT_TM_TM_ZONE
+
+/* Define to 1 if you have the `sync_file_range' function. */
+#undef HAVE_SYNC_FILE_RANGE
+
+/* Define to 1 if you have the syslog interface. */
+#undef HAVE_SYSLOG
+
+/* Define to 1 if you have the <sys/ipc.h> header file. */
+#undef HAVE_SYS_IPC_H
+
+/* Define to 1 if you have the <sys/personality.h> header file. */
+#undef HAVE_SYS_PERSONALITY_H
+
+/* Define to 1 if you have the <sys/prctl.h> header file. */
+#undef HAVE_SYS_PRCTL_H
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+#undef HAVE_SYS_SELECT_H
+
+/* Define to 1 if you have the <sys/sem.h> header file. */
+#undef HAVE_SYS_SEM_H
+
+/* Define to 1 if you have the <sys/shm.h> header file. */
+#undef HAVE_SYS_SHM_H
+
+/* Define to 1 if you have the <sys/un.h> header file. */
+#undef HAVE_SYS_UN_H
+
+/* Define to 1 if you have the <termios.h> header file. */
+#undef HAVE_TERMIOS_H
+
+/* Define to 1 if your `struct tm' has `tm_zone'. Deprecated, use
+ `HAVE_STRUCT_TM_TM_ZONE' instead. */
+#undef HAVE_TM_ZONE
+
+/* Define to 1 if your compiler understands `typeof' or something similar. */
+#undef HAVE_TYPEOF
+
+/* Define to 1 if you have the external array `tzname'. */
+#undef HAVE_TZNAME
+
+/* Define to 1 if you have unix sockets. */
+#undef HAVE_UNIX_SOCKETS
+
+/* Define to 1 if you have the `unsetenv' function. */
+#undef HAVE_UNSETENV
+
+/* Define to 1 if you have the `uselocale' function. */
+#undef HAVE_USELOCALE
+
+/* Define to 1 if you have the `utimes' function. */
+#undef HAVE_UTIMES
+
+/* Define to 1 if you have the `wcstombs_l' function. */
+#define HAVE_WCSTOMBS_L 1
+
+/* Define to 1 if the assembler supports X86_64's POPCNTQ instruction. */
+#undef HAVE_X86_64_POPCNTQ
+
+/* Define to 1 if the system has the type `_Bool'. */
+#undef HAVE__BOOL
+
+/* Define to 1 if your compiler understands __builtin_bswap16. */
+#undef HAVE__BUILTIN_BSWAP16
+
+/* Define to 1 if your compiler understands __builtin_bswap32. */
+#undef HAVE__BUILTIN_BSWAP32
+
+/* Define to 1 if your compiler understands __builtin_bswap64. */
+#undef HAVE__BUILTIN_BSWAP64
+
+/* Define to 1 if your compiler understands __builtin_clz. */
+#undef HAVE__BUILTIN_CLZ
+
+/* Define to 1 if your compiler understands __builtin_constant_p. */
+#undef HAVE__BUILTIN_CONSTANT_P
+
+/* Define to 1 if your compiler understands __builtin_ctz. */
+#undef HAVE__BUILTIN_CTZ
+
+/* Define to 1 if your compiler understands __builtin_$op_overflow. */
+#undef HAVE__BUILTIN_OP_OVERFLOW
+
+/* Define to 1 if your compiler understands __builtin_popcount. */
+#undef HAVE__BUILTIN_POPCOUNT
+
+/* Define to 1 if your compiler understands __builtin_types_compatible_p. */
+#undef HAVE__BUILTIN_TYPES_COMPATIBLE_P
+
+/* Define to 1 if your compiler understands __builtin_unreachable. */
+#undef HAVE__BUILTIN_UNREACHABLE
+
+/* Define to 1 if you have the `_configthreadlocale' function. */
+#define HAVE__CONFIGTHREADLOCALE 1
+
+/* Define to 1 if you have __cpuid. */
+#define HAVE__CPUID 1
+
+/* Define to 1 if you have __get_cpuid. */
+#undef HAVE__GET_CPUID
+
+/* Define to the appropriate printf length modifier for 64-bit ints. */
+#define INT64_MODIFIER "ll"
+
+/* Define to 1 if `locale_t' requires <xlocale.h>. */
+/* #undef LOCALE_T_IN_XLOCALE */
+
+/* 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. */
+#define PG_INT64_TYPE long long int
+
+/* The size of `size_t', as computed by sizeof. */
+#ifdef _WIN64
+#define SIZEOF_SIZE_T 8
+#else
+#define SIZEOF_SIZE_T 4
+#endif
+
+/* The size of `void *', as computed by sizeof. */
+#ifndef _WIN64
+#define SIZEOF_VOID_P 8
+#else
+#define SIZEOF_VOID_P 4
+#endif
+
+/* Define to select named POSIX semaphores. */
+#undef USE_NAMED_POSIX_SEMAPHORES
+
+/* Define to build with systemd support. (--with-systemd) */
+#undef USE_SYSTEMD
+
+/* Define to select unnamed POSIX semaphores. */
+#undef USE_UNNAMED_POSIX_SEMAPHORES
+
+/* Define to use native Windows API for random number generation */
+#define USE_WIN32_RANDOM 1
+
+/* Define to select Win32-style semaphores. */
+#define USE_WIN32_SEMAPHORES 1
+
+#define pg_restrict __restrict
diff --git a/contrib/libs/libpq/src/include/pg_config.h b/contrib/libs/libpq/src/include/pg_config.h
new file mode 100644
index 0000000000..b63bb45246
--- /dev/null
+++ b/contrib/libs/libpq/src/include/pg_config.h
@@ -0,0 +1,13 @@
+#pragma once
+
+#if defined(__APPLE__) && (defined(__aarch64__) || defined(_M_ARM64))
+# include "pg_config-osx-arm64.h"
+#elif defined(__APPLE__)
+# include "pg_config-osx.h"
+#elif defined(_MSC_VER)
+# include "pg_config-win.h"
+#elif defined(__linux__) && (defined(__aarch64__) || defined(_M_ARM64))
+# include "pg_config-linux-aarch64.h"
+#else
+# include "pg_config-linux.h"
+#endif
diff --git a/contrib/libs/libpq/src/include/pg_config_ext.h b/contrib/libs/libpq/src/include/pg_config_ext.h
new file mode 100644
index 0000000000..b4c07dd857
--- /dev/null
+++ b/contrib/libs/libpq/src/include/pg_config_ext.h
@@ -0,0 +1,8 @@
+/* src/include/pg_config_ext.h. Generated from pg_config_ext.h.in by configure. */
+/*
+ * 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. */
+#define PG_INT64_TYPE long int
diff --git a/contrib/libs/libpq/src/include/pg_config_manual.h b/contrib/libs/libpq/src/include/pg_config_manual.h
new file mode 100644
index 0000000000..a1a93ad706
--- /dev/null
+++ b/contrib/libs/libpq/src/include/pg_config_manual.h
@@ -0,0 +1,372 @@
+/*------------------------------------------------------------------------
+ * PostgreSQL manual configuration settings
+ *
+ * This file contains various configuration symbols and limits. In
+ * all cases, changing them is only useful in very rare situations or
+ * for developers. If you edit any of these, be sure to do a *full*
+ * rebuild (and an initdb if noted).
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/pg_config_manual.h
+ *------------------------------------------------------------------------
+ */
+
+/*
+ * This is the default value for wal_segment_size to be used when initdb is run
+ * without the --wal-segsize option. It must be a valid segment size.
+ */
+#define DEFAULT_XLOG_SEG_SIZE (16*1024*1024)
+
+/*
+ * Maximum length for identifiers (e.g. table names, column names,
+ * function names). Names actually are limited to one fewer byte than this,
+ * because the length must include a trailing zero byte.
+ *
+ * Changing this requires an initdb.
+ */
+#define NAMEDATALEN 64
+
+/*
+ * Maximum number of arguments to a function.
+ *
+ * The minimum value is 8 (GIN indexes use 8-argument support functions).
+ * The maximum possible value is around 600 (limited by index tuple size in
+ * pg_proc's index; BLCKSZ larger than 8K would allow more). Values larger
+ * than needed will waste memory and processing time, but do not directly
+ * cost disk space.
+ *
+ * Changing this does not require an initdb, but it does require a full
+ * backend recompile (including any user-defined C functions).
+ */
+#define FUNC_MAX_ARGS 100
+
+/*
+ * When creating a product derived from PostgreSQL with changes that cause
+ * incompatibilities for loadable modules, it is recommended to change this
+ * string so that dfmgr.c can refuse to load incompatible modules with a clean
+ * error message. Typical examples that cause incompatibilities are any
+ * changes to node tags or node structures. (Note that dfmgr.c already
+ * detects common sources of incompatibilities due to major version
+ * differences and due to some changed compile-time constants. This setting
+ * is for catching anything that cannot be detected in a straightforward way.)
+ *
+ * There is no prescribed format for the string. The suggestion is to include
+ * product or company name, and optionally any internally-relevant ABI
+ * version. Example: "ACME Postgres/1.2". Note that the string will appear
+ * in a user-facing error message if an ABI mismatch is detected.
+ */
+#define FMGR_ABI_EXTRA "PostgreSQL"
+
+/*
+ * Maximum number of columns in an index. There is little point in making
+ * this anything but a multiple of 32, because the main cost is associated
+ * with index tuple header size (see access/itup.h).
+ *
+ * Changing this requires an initdb.
+ */
+#define INDEX_MAX_KEYS 32
+
+/*
+ * Maximum number of columns in a partition key
+ */
+#define PARTITION_MAX_KEYS 32
+
+/*
+ * Decide whether built-in 8-byte types, including float8, int8, and
+ * timestamp, are passed by value. This is on by default if sizeof(Datum) >=
+ * 8 (that is, on 64-bit platforms). If sizeof(Datum) < 8 (32-bit platforms),
+ * this must be off. We keep this here as an option so that it is easy to
+ * test the pass-by-reference code paths on 64-bit platforms.
+ *
+ * Changing this requires an initdb.
+ */
+#if SIZEOF_VOID_P >= 8
+#define USE_FLOAT8_BYVAL 1
+#endif
+
+/*
+ * When we don't have native spinlocks, we use semaphores to simulate them.
+ * Decreasing this value reduces consumption of OS resources; increasing it
+ * may improve performance, but supplying a real spinlock implementation is
+ * probably far better.
+ */
+#define NUM_SPINLOCK_SEMAPHORES 128
+
+/*
+ * When we have neither spinlocks nor atomic operations support we're
+ * implementing atomic operations on top of spinlock on top of semaphores. To
+ * be safe against atomic operations while holding a spinlock separate
+ * semaphores have to be used.
+ */
+#define NUM_ATOMICS_SEMAPHORES 64
+
+/*
+ * MAXPGPATH: standard size of a pathname buffer in PostgreSQL (hence,
+ * maximum usable pathname length is one less).
+ *
+ * We'd use a standard system header symbol for this, if there weren't
+ * so many to choose from: MAXPATHLEN, MAX_PATH, PATH_MAX are all
+ * defined by different "standards", and often have different values
+ * on the same platform! So we just punt and use a reasonably
+ * generous setting here.
+ */
+#define MAXPGPATH 1024
+
+/*
+ * You can try changing this if you have a machine with bytes of
+ * another size, but no guarantee...
+ */
+#define BITS_PER_BYTE 8
+
+/*
+ * Preferred alignment for disk I/O buffers. On some CPUs, copies between
+ * user space and kernel space are significantly faster if the user buffer
+ * is aligned on a larger-than-MAXALIGN boundary. Ideally this should be
+ * a platform-dependent value, but for now we just hard-wire it.
+ */
+#define ALIGNOF_BUFFER 32
+
+/*
+ * If EXEC_BACKEND is defined, the postmaster uses an alternative method for
+ * starting subprocesses: Instead of simply using fork(), as is standard on
+ * Unix platforms, it uses fork()+exec() or something equivalent on Windows,
+ * as well as lots of extra code to bring the required global state to those
+ * new processes. This must be enabled on Windows (because there is no
+ * fork()). On other platforms, it's only useful for verifying those
+ * otherwise Windows-specific code paths.
+ */
+#if defined(WIN32) && !defined(__CYGWIN__)
+#define EXEC_BACKEND
+#endif
+
+/*
+ * USE_POSIX_FADVISE controls whether Postgres will attempt to use the
+ * posix_fadvise() kernel call. Usually the automatic configure tests are
+ * sufficient, but some older Linux distributions had broken versions of
+ * posix_fadvise(). If necessary you can remove the #define here.
+ */
+#if HAVE_DECL_POSIX_FADVISE && defined(HAVE_POSIX_FADVISE)
+#define USE_POSIX_FADVISE
+#endif
+
+/*
+ * USE_PREFETCH code should be compiled only if we have a way to implement
+ * prefetching. (This is decoupled from USE_POSIX_FADVISE because there
+ * might in future be support for alternative low-level prefetch APIs.
+ * If you change this, you probably need to adjust the error message in
+ * check_effective_io_concurrency.)
+ */
+#ifdef USE_POSIX_FADVISE
+#define USE_PREFETCH
+#endif
+
+/*
+ * Default and maximum values for backend_flush_after, bgwriter_flush_after
+ * and checkpoint_flush_after; measured in blocks. Currently, these are
+ * enabled by default if sync_file_range() exists, ie, only on Linux. Perhaps
+ * we could also enable by default if we have mmap and msync(MS_ASYNC)?
+ */
+#ifdef HAVE_SYNC_FILE_RANGE
+#define DEFAULT_BACKEND_FLUSH_AFTER 0 /* never enabled by default */
+#define DEFAULT_BGWRITER_FLUSH_AFTER 64
+#define DEFAULT_CHECKPOINT_FLUSH_AFTER 32
+#else
+#define DEFAULT_BACKEND_FLUSH_AFTER 0
+#define DEFAULT_BGWRITER_FLUSH_AFTER 0
+#define DEFAULT_CHECKPOINT_FLUSH_AFTER 0
+#endif
+/* upper limit for all three variables */
+#define WRITEBACK_MAX_PENDING_FLUSHES 256
+
+/*
+ * USE_SSL code should be compiled only when compiling with an SSL
+ * implementation.
+ */
+#ifdef USE_OPENSSL
+#define USE_SSL
+#endif
+
+/*
+ * This is the default directory in which AF_UNIX socket files are
+ * placed. Caution: changing this risks breaking your existing client
+ * applications, which are likely to continue to look in the old
+ * directory. But if you just hate the idea of sockets in /tmp,
+ * here's where to twiddle it. You can also override this at runtime
+ * with the postmaster's -k switch.
+ *
+ * If set to an empty string, then AF_UNIX sockets are not used by default: A
+ * server will not create an AF_UNIX socket unless the run-time configuration
+ * is changed, a client will connect via TCP/IP by default and will only use
+ * an AF_UNIX socket if one is explicitly specified.
+ *
+ * This is done by default on Windows because there is no good standard
+ * location for AF_UNIX sockets and many installations on Windows don't
+ * support them yet.
+ */
+#ifndef WIN32
+#define DEFAULT_PGSOCKET_DIR "/tmp"
+#else
+#define DEFAULT_PGSOCKET_DIR ""
+#endif
+
+/*
+ * This is the default event source for Windows event log.
+ */
+#define DEFAULT_EVENT_SOURCE "PostgreSQL"
+
+/*
+ * Assumed cache line size. This doesn't affect correctness, but can be used
+ * for low-level optimizations. Currently, this is used to pad some data
+ * structures in xlog.c, to ensure that highly-contended fields are on
+ * different cache lines. Too small a value can hurt performance due to false
+ * sharing, while the only downside of too large a value is a few bytes of
+ * wasted memory. The default is 128, which should be large enough for all
+ * supported platforms.
+ */
+#define PG_CACHE_LINE_SIZE 128
+
+/*
+ * Assumed alignment requirement for direct I/O. 4K corresponds to common
+ * sector and memory page size.
+ */
+#define PG_IO_ALIGN_SIZE 4096
+
+/*
+ *------------------------------------------------------------------------
+ * The following symbols are for enabling debugging code, not for
+ * controlling user-visible features or resource limits.
+ *------------------------------------------------------------------------
+ */
+
+/*
+ * Include Valgrind "client requests", mostly in the memory allocator, so
+ * Valgrind understands PostgreSQL memory contexts. This permits detecting
+ * memory errors that Valgrind would not detect on a vanilla build. It also
+ * enables detection of buffer accesses that take place without holding a
+ * buffer pin (or without holding a buffer lock in the case of index access
+ * methods that superimpose their own custom client requests on top of the
+ * generic bufmgr.c requests).
+ *
+ * "make installcheck" is significantly slower under Valgrind. The client
+ * requests fall in hot code paths, so USE_VALGRIND slows execution by a few
+ * percentage points even when not run under Valgrind.
+ *
+ * Do not try to test the server under Valgrind without having built the
+ * server with USE_VALGRIND; else you will get false positives from sinval
+ * messaging (see comments in AddCatcacheInvalidationMessage). It's also
+ * important to use the suppression file src/tools/valgrind.supp to
+ * exclude other known false positives.
+ *
+ * You should normally use MEMORY_CONTEXT_CHECKING with USE_VALGRIND;
+ * instrumentation of repalloc() is inferior without it.
+ */
+/* #define USE_VALGRIND */
+
+/*
+ * Define this to cause pfree()'d memory to be cleared immediately, to
+ * facilitate catching bugs that refer to already-freed values.
+ * Right now, this gets defined automatically if --enable-cassert.
+ */
+#ifdef USE_ASSERT_CHECKING
+#define CLOBBER_FREED_MEMORY
+#endif
+
+/*
+ * Define this to check memory allocation errors (scribbling on more
+ * bytes than were allocated). Right now, this gets defined
+ * automatically if --enable-cassert or USE_VALGRIND.
+ */
+#if defined(USE_ASSERT_CHECKING) || defined(USE_VALGRIND)
+#define MEMORY_CONTEXT_CHECKING
+#endif
+
+/*
+ * Define this to cause palloc()'d memory to be filled with random data, to
+ * facilitate catching code that depends on the contents of uninitialized
+ * memory. Caution: this is horrendously expensive.
+ */
+/* #define RANDOMIZE_ALLOCATED_MEMORY */
+
+/*
+ * For cache-invalidation debugging, define DISCARD_CACHES_ENABLED to enable
+ * use of the debug_discard_caches GUC to aggressively flush syscache/relcache
+ * entries whenever it's possible to deliver invalidations. See
+ * AcceptInvalidationMessages() in src/backend/utils/cache/inval.c for
+ * details.
+ *
+ * USE_ASSERT_CHECKING builds default to enabling this. It's possible to use
+ * DISCARD_CACHES_ENABLED without a cassert build and the implied
+ * CLOBBER_FREED_MEMORY and MEMORY_CONTEXT_CHECKING options, but it's unlikely
+ * to be as effective at identifying problems.
+ */
+/* #define DISCARD_CACHES_ENABLED */
+
+#if defined(USE_ASSERT_CHECKING) && !defined(DISCARD_CACHES_ENABLED)
+#define DISCARD_CACHES_ENABLED
+#endif
+
+/*
+ * Backwards compatibility for the older compile-time-only clobber-cache
+ * macros.
+ */
+#if !defined(DISCARD_CACHES_ENABLED) && (defined(CLOBBER_CACHE_ALWAYS) || defined(CLOBBER_CACHE_RECURSIVELY))
+#define DISCARD_CACHES_ENABLED
+#endif
+
+/*
+ * Recover memory used for relcache entries when invalidated. See
+ * RelationBuildDesc() in src/backend/utils/cache/relcache.c.
+ *
+ * This is active automatically for clobber-cache builds when clobbering is
+ * active, but can be overridden here by explicitly defining
+ * RECOVER_RELATION_BUILD_MEMORY. Define to 1 to always free relation cache
+ * memory even when clobber is off, or to 0 to never free relation cache
+ * memory even when clobbering is on.
+ */
+ /* #define RECOVER_RELATION_BUILD_MEMORY 0 */ /* Force disable */
+ /* #define RECOVER_RELATION_BUILD_MEMORY 1 */ /* Force enable */
+
+/*
+ * Define this to force all parse and plan trees to be passed through
+ * copyObject(), to facilitate catching errors and omissions in
+ * copyObject().
+ */
+/* #define COPY_PARSE_PLAN_TREES */
+
+/*
+ * Define this to force all parse and plan trees to be passed through
+ * outfuncs.c/readfuncs.c, to facilitate catching errors and omissions in
+ * those modules.
+ */
+/* #define WRITE_READ_PARSE_PLAN_TREES */
+
+/*
+ * Define this to force all raw parse trees for DML statements to be scanned
+ * by raw_expression_tree_walker(), to facilitate catching errors and
+ * omissions in that function.
+ */
+/* #define RAW_EXPRESSION_COVERAGE_TEST */
+
+/*
+ * Enable debugging print statements for lock-related operations.
+ */
+/* #define LOCK_DEBUG */
+
+/*
+ * Enable debugging print statements for WAL-related operations; see
+ * also the wal_debug GUC var.
+ */
+/* #define WAL_DEBUG */
+
+/*
+ * Enable tracing of resource consumption during sort operations;
+ * see also the trace_sort GUC var. For 8.1 this is enabled by default.
+ */
+#define TRACE_SORT 1
+
+/*
+ * Enable tracing of syncscan operations (see also the trace_syncscan GUC var).
+ */
+/* #define TRACE_SYNCSCAN */
diff --git a/contrib/libs/libpq/src/include/pg_config_os-linux.h b/contrib/libs/libpq/src/include/pg_config_os-linux.h
new file mode 100644
index 0000000000..331e1b2cf1
--- /dev/null
+++ b/contrib/libs/libpq/src/include/pg_config_os-linux.h
@@ -0,0 +1 @@
+#include <contrib/libs/libpq/src/include/port/linux.h>
diff --git a/contrib/libs/libpq/src/include/pg_config_os-osx.h b/contrib/libs/libpq/src/include/pg_config_os-osx.h
new file mode 100644
index 0000000000..f77fb9d4da
--- /dev/null
+++ b/contrib/libs/libpq/src/include/pg_config_os-osx.h
@@ -0,0 +1 @@
+#include <contrib/libs/libpq/src/include/port/darwin.h>
diff --git a/contrib/libs/libpq/src/include/pg_config_os-win.h b/contrib/libs/libpq/src/include/pg_config_os-win.h
new file mode 100644
index 0000000000..e26ba92209
--- /dev/null
+++ b/contrib/libs/libpq/src/include/pg_config_os-win.h
@@ -0,0 +1 @@
+#include <contrib/libs/libpq/src/include/port/win32.h>
diff --git a/contrib/libs/libpq/src/include/pg_config_os.h b/contrib/libs/libpq/src/include/pg_config_os.h
new file mode 100644
index 0000000000..86db251be2
--- /dev/null
+++ b/contrib/libs/libpq/src/include/pg_config_os.h
@@ -0,0 +1,9 @@
+#pragma once
+
+#if defined(__APPLE__)
+# include "pg_config_os-osx.h"
+#elif defined(_MSC_VER)
+# include "pg_config_os-win.h"
+#else
+# include "pg_config_os-linux.h"
+#endif
diff --git a/contrib/libs/libpq/src/include/pgtar.h b/contrib/libs/libpq/src/include/pgtar.h
new file mode 100644
index 0000000000..661f9d7c59
--- /dev/null
+++ b/contrib/libs/libpq/src/include/pgtar.h
@@ -0,0 +1,45 @@
+/*-------------------------------------------------------------------------
+ *
+ * pgtar.h
+ * Functions for manipulating tarfile datastructures (src/port/tar.c)
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/pgtar.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_TAR_H
+#define PG_TAR_H
+
+#define TAR_BLOCK_SIZE 512
+
+enum tarError
+{
+ TAR_OK = 0,
+ TAR_NAME_TOO_LONG,
+ TAR_SYMLINK_TOO_LONG
+};
+
+extern enum tarError tarCreateHeader(char *h, const char *filename,
+ const char *linktarget, pgoff_t size,
+ mode_t mode, uid_t uid, gid_t gid,
+ time_t mtime);
+extern uint64 read_tar_number(const char *s, int len);
+extern void print_tar_number(char *s, int len, uint64 val);
+extern int tarChecksum(char *header);
+
+/*
+ * Compute the number of padding bytes required for an entry in a tar
+ * archive. We must pad out to a multiple of TAR_BLOCK_SIZE. Since that's
+ * a power of 2, we can use TYPEALIGN().
+ */
+static inline size_t
+tarPaddingBytesRequired(size_t len)
+{
+ return TYPEALIGN(TAR_BLOCK_SIZE, len) - len;
+}
+
+#endif
diff --git a/contrib/libs/libpq/src/include/pgtime.h b/contrib/libs/libpq/src/include/pgtime.h
new file mode 100644
index 0000000000..9d4b2efe94
--- /dev/null
+++ b/contrib/libs/libpq/src/include/pgtime.h
@@ -0,0 +1,94 @@
+/*-------------------------------------------------------------------------
+ *
+ * pgtime.h
+ * PostgreSQL internal timezone library
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/include/pgtime.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef _PGTIME_H
+#define _PGTIME_H
+
+
+/*
+ * The API of this library is generally similar to the corresponding
+ * C library functions, except that we use pg_time_t which (we hope) is
+ * 64 bits wide, and which is most definitely signed not unsigned.
+ */
+
+typedef int64 pg_time_t;
+
+/*
+ * Data structure representing a broken-down timestamp.
+ *
+ * CAUTION: the IANA timezone library (src/timezone/) follows the POSIX
+ * convention that tm_mon counts from 0 and tm_year is relative to 1900.
+ * However, Postgres' datetime functions generally treat tm_mon as counting
+ * from 1 and tm_year as relative to 1 BC. Be sure to make the appropriate
+ * adjustments when moving from one code domain to the other.
+ */
+struct pg_tm
+{
+ int tm_sec;
+ int tm_min;
+ int tm_hour;
+ int tm_mday;
+ int tm_mon; /* see above */
+ int tm_year; /* see above */
+ int tm_wday;
+ int tm_yday;
+ int tm_isdst;
+ long int tm_gmtoff;
+ const char *tm_zone;
+};
+
+/* These structs are opaque outside the timezone library */
+typedef struct pg_tz pg_tz;
+typedef struct pg_tzenum pg_tzenum;
+
+/* Maximum length of a timezone name (not including trailing null) */
+#define TZ_STRLEN_MAX 255
+
+/* these functions are in localtime.c */
+
+extern struct pg_tm *pg_localtime(const pg_time_t *timep, const pg_tz *tz);
+extern struct pg_tm *pg_gmtime(const pg_time_t *timep);
+extern int pg_next_dst_boundary(const pg_time_t *timep,
+ long int *before_gmtoff,
+ int *before_isdst,
+ pg_time_t *boundary,
+ long int *after_gmtoff,
+ int *after_isdst,
+ const pg_tz *tz);
+extern bool pg_interpret_timezone_abbrev(const char *abbrev,
+ const pg_time_t *timep,
+ long int *gmtoff,
+ int *isdst,
+ const pg_tz *tz);
+extern bool pg_get_timezone_offset(const pg_tz *tz, long int *gmtoff);
+extern const char *pg_get_timezone_name(pg_tz *tz);
+extern bool pg_tz_acceptable(pg_tz *tz);
+
+/* these functions are in strftime.c */
+
+extern size_t pg_strftime(char *s, size_t maxsize, const char *format,
+ const struct pg_tm *t);
+
+/* these functions and variables are in pgtz.c */
+
+extern PGDLLIMPORT pg_tz *session_timezone;
+extern PGDLLIMPORT pg_tz *log_timezone;
+
+extern void pg_timezone_initialize(void);
+extern pg_tz *pg_tzset(const char *tzname);
+extern pg_tz *pg_tzset_offset(long gmtoffset);
+
+extern pg_tzenum *pg_tzenumerate_start(void);
+extern pg_tz *pg_tzenumerate_next(pg_tzenum *dir);
+extern void pg_tzenumerate_end(pg_tzenum *dir);
+
+#endif /* _PGTIME_H */
diff --git a/contrib/libs/libpq/src/include/port.h b/contrib/libs/libpq/src/include/port.h
new file mode 100644
index 0000000000..a88d403483
--- /dev/null
+++ b/contrib/libs/libpq/src/include/port.h
@@ -0,0 +1,520 @@
+/*-------------------------------------------------------------------------
+ *
+ * port.h
+ * Header for src/port/ compatibility functions.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/port.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_PORT_H
+#define PG_PORT_H
+
+#include <ctype.h>
+
+/*
+ * Windows has enough specialized port stuff that we push most of it off
+ * into another file.
+ * Note: Some CYGWIN includes might #define WIN32.
+ */
+#if defined(WIN32) && !defined(__CYGWIN__)
+#include "port/win32_port.h"
+#endif
+
+/* socket has a different definition on WIN32 */
+#ifndef WIN32
+typedef int pgsocket;
+
+#define PGINVALID_SOCKET (-1)
+#else
+typedef SOCKET pgsocket;
+
+#define PGINVALID_SOCKET INVALID_SOCKET
+#endif
+
+/* if platform lacks socklen_t, we assume this will work */
+#ifndef HAVE_SOCKLEN_T
+typedef unsigned int socklen_t;
+#endif
+
+/* non-blocking */
+extern bool pg_set_noblock(pgsocket sock);
+extern bool pg_set_block(pgsocket sock);
+
+/* Portable path handling for Unix/Win32 (in path.c) */
+
+extern bool has_drive_prefix(const char *path);
+extern char *first_dir_separator(const char *filename);
+extern char *last_dir_separator(const char *filename);
+extern char *first_path_var_separator(const char *pathlist);
+extern void join_path_components(char *ret_path,
+ const char *head, const char *tail);
+extern void canonicalize_path(char *path);
+extern void make_native_path(char *filename);
+extern void cleanup_path(char *path);
+extern bool path_contains_parent_reference(const char *path);
+extern bool path_is_relative_and_below_cwd(const char *path);
+extern bool path_is_prefix_of_path(const char *path1, const char *path2);
+extern char *make_absolute_path(const char *path);
+extern const char *get_progname(const char *argv0);
+extern void get_share_path(const char *my_exec_path, char *ret_path);
+extern void get_etc_path(const char *my_exec_path, char *ret_path);
+extern void get_include_path(const char *my_exec_path, char *ret_path);
+extern void get_pkginclude_path(const char *my_exec_path, char *ret_path);
+extern void get_includeserver_path(const char *my_exec_path, char *ret_path);
+extern void get_lib_path(const char *my_exec_path, char *ret_path);
+extern void get_pkglib_path(const char *my_exec_path, char *ret_path);
+extern void get_locale_path(const char *my_exec_path, char *ret_path);
+extern void get_doc_path(const char *my_exec_path, char *ret_path);
+extern void get_html_path(const char *my_exec_path, char *ret_path);
+extern void get_man_path(const char *my_exec_path, char *ret_path);
+extern bool get_home_path(char *ret_path);
+extern void get_parent_directory(char *path);
+
+/* common/pgfnames.c */
+extern char **pgfnames(const char *path);
+extern void pgfnames_cleanup(char **filenames);
+
+#define IS_NONWINDOWS_DIR_SEP(ch) ((ch) == '/')
+#define is_nonwindows_absolute_path(filename) \
+( \
+ IS_NONWINDOWS_DIR_SEP((filename)[0]) \
+)
+
+#define IS_WINDOWS_DIR_SEP(ch) ((ch) == '/' || (ch) == '\\')
+/* See path_is_relative_and_below_cwd() for how we handle 'E:abc'. */
+#define is_windows_absolute_path(filename) \
+( \
+ IS_WINDOWS_DIR_SEP((filename)[0]) || \
+ (isalpha((unsigned char) ((filename)[0])) && (filename)[1] == ':' && \
+ IS_WINDOWS_DIR_SEP((filename)[2])) \
+)
+
+/*
+ * is_absolute_path and IS_DIR_SEP
+ *
+ * By using macros here we avoid needing to include path.c in libpq.
+ */
+#ifndef WIN32
+#define IS_DIR_SEP(ch) IS_NONWINDOWS_DIR_SEP(ch)
+#define is_absolute_path(filename) is_nonwindows_absolute_path(filename)
+#else
+#define IS_DIR_SEP(ch) IS_WINDOWS_DIR_SEP(ch)
+#define is_absolute_path(filename) is_windows_absolute_path(filename)
+#endif
+
+/*
+ * This macro provides a centralized list of all errnos that identify
+ * hard failure of a previously-established network connection.
+ * The macro is intended to be used in a switch statement, in the form
+ * "case ALL_CONNECTION_FAILURE_ERRNOS:".
+ *
+ * Note: this groups EPIPE and ECONNRESET, which we take to indicate a
+ * probable server crash, with other errors that indicate loss of network
+ * connectivity without proving much about the server's state. Places that
+ * are actually reporting errors typically single out EPIPE and ECONNRESET,
+ * while allowing the network failures to be reported generically.
+ */
+#define ALL_CONNECTION_FAILURE_ERRNOS \
+ EPIPE: \
+ case ECONNRESET: \
+ case ECONNABORTED: \
+ case EHOSTDOWN: \
+ case EHOSTUNREACH: \
+ case ENETDOWN: \
+ case ENETRESET: \
+ case ENETUNREACH: \
+ case ETIMEDOUT
+
+/* Portable locale initialization (in exec.c) */
+extern void set_pglocale_pgservice(const char *argv0, const char *app);
+
+/* Portable way to find and execute binaries (in exec.c) */
+extern int validate_exec(const char *path);
+extern int find_my_exec(const char *argv0, char *retpath);
+extern int find_other_exec(const char *argv0, const char *target,
+ const char *versionstr, char *retpath);
+extern char *pipe_read_line(char *cmd, char *line, int maxsize);
+
+/* Doesn't belong here, but this is used with find_other_exec(), so... */
+#define PG_BACKEND_VERSIONSTR "postgres (PostgreSQL) " PG_VERSION "\n"
+
+#ifdef EXEC_BACKEND
+/* Disable ASLR before exec, for developer builds only (in exec.c) */
+extern int pg_disable_aslr(void);
+#endif
+
+
+#if defined(WIN32) || defined(__CYGWIN__)
+#define EXE ".exe"
+#else
+#define EXE ""
+#endif
+
+#if defined(WIN32) && !defined(__CYGWIN__)
+#define DEVNULL "nul"
+#else
+#define DEVNULL "/dev/null"
+#endif
+
+/* Portable delay handling */
+extern void pg_usleep(long microsec);
+
+/* Portable SQL-like case-independent comparisons and conversions */
+extern int pg_strcasecmp(const char *s1, const char *s2);
+extern int pg_strncasecmp(const char *s1, const char *s2, size_t n);
+extern unsigned char pg_toupper(unsigned char ch);
+extern unsigned char pg_tolower(unsigned char ch);
+extern unsigned char pg_ascii_toupper(unsigned char ch);
+extern unsigned char pg_ascii_tolower(unsigned char ch);
+
+/*
+ * Beginning in v12, we always replace snprintf() and friends with our own
+ * implementation. This symbol is no longer consulted by the core code,
+ * but keep it defined anyway in case any extensions are looking at it.
+ */
+#define USE_REPL_SNPRINTF 1
+
+/*
+ * Versions of libintl >= 0.13 try to replace printf() and friends with
+ * macros to their own versions that understand the %$ format. We do the
+ * same, so disable their macros, if they exist.
+ */
+#ifdef vsnprintf
+#undef vsnprintf
+#endif
+#ifdef snprintf
+#undef snprintf
+#endif
+#ifdef vsprintf
+#undef vsprintf
+#endif
+#ifdef sprintf
+#undef sprintf
+#endif
+#ifdef vfprintf
+#undef vfprintf
+#endif
+#ifdef fprintf
+#undef fprintf
+#endif
+#ifdef vprintf
+#undef vprintf
+#endif
+#ifdef printf
+#undef printf
+#endif
+
+extern int pg_vsnprintf(char *str, size_t count, const char *fmt, va_list args) pg_attribute_printf(3, 0);
+extern int pg_snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3, 4);
+extern int pg_vsprintf(char *str, const char *fmt, va_list args) pg_attribute_printf(2, 0);
+extern int pg_sprintf(char *str, const char *fmt,...) pg_attribute_printf(2, 3);
+extern int pg_vfprintf(FILE *stream, const char *fmt, va_list args) pg_attribute_printf(2, 0);
+extern int pg_fprintf(FILE *stream, const char *fmt,...) pg_attribute_printf(2, 3);
+extern int pg_vprintf(const char *fmt, va_list args) pg_attribute_printf(1, 0);
+extern int pg_printf(const char *fmt,...) pg_attribute_printf(1, 2);
+
+#ifndef WIN32
+/*
+ * We add a pg_ prefix as a warning that the Windows implementations have the
+ * non-standard side-effect of changing the current file position.
+ */
+#define pg_pread pread
+#define pg_pwrite pwrite
+#endif
+
+/*
+ * We use __VA_ARGS__ for printf to prevent replacing references to
+ * the "printf" format archetype in format() attribute declarations.
+ * That unfortunately means that taking a function pointer to printf
+ * will not do what we'd wish. (If you need to do that, you must name
+ * pg_printf explicitly.) For printf's sibling functions, use
+ * parameterless macros so that function pointers will work unsurprisingly.
+ */
+#define vsnprintf pg_vsnprintf
+#define snprintf pg_snprintf
+#define vsprintf pg_vsprintf
+#define sprintf pg_sprintf
+#define vfprintf pg_vfprintf
+#define fprintf pg_fprintf
+#define vprintf pg_vprintf
+#define printf(...) pg_printf(__VA_ARGS__)
+
+/* This is also provided by snprintf.c */
+extern int pg_strfromd(char *str, size_t count, int precision, double value);
+
+/* Replace strerror() with our own, somewhat more robust wrapper */
+extern char *pg_strerror(int errnum);
+#define strerror pg_strerror
+
+/* Likewise for strerror_r(); note we prefer the GNU API for that */
+extern char *pg_strerror_r(int errnum, char *buf, size_t buflen);
+#define strerror_r pg_strerror_r
+#define PG_STRERROR_R_BUFLEN 256 /* Recommended buffer size for strerror_r */
+
+/* Wrap strsignal(), or provide our own version if necessary */
+extern const char *pg_strsignal(int signum);
+
+extern int pclose_check(FILE *stream);
+
+/* Global variable holding time zone information. */
+#if defined(WIN32) || defined(__CYGWIN__)
+#define TIMEZONE_GLOBAL _timezone
+#define TZNAME_GLOBAL _tzname
+#else
+#define TIMEZONE_GLOBAL timezone
+#define TZNAME_GLOBAL tzname
+#endif
+
+#if defined(WIN32) || defined(__CYGWIN__)
+/*
+ * Win32 doesn't have reliable rename/unlink during concurrent access.
+ */
+extern int pgrename(const char *from, const char *to);
+extern int pgunlink(const char *path);
+
+/* Include this first so later includes don't see these defines */
+#ifdef _MSC_VER
+#include <io.h>
+#endif
+
+#define rename(from, to) pgrename(from, to)
+#define unlink(path) pgunlink(path)
+#endif /* defined(WIN32) || defined(__CYGWIN__) */
+
+/*
+ * Win32 also doesn't have symlinks, but we can emulate them with
+ * junction points on newer Win32 versions.
+ *
+ * Cygwin has its own symlinks which work on Win95/98/ME where
+ * junction points don't, so use those instead. We have no way of
+ * knowing what type of system Cygwin binaries will be run on.
+ * Note: Some CYGWIN includes might #define WIN32.
+ */
+#if defined(WIN32) && !defined(__CYGWIN__)
+extern int pgsymlink(const char *oldpath, const char *newpath);
+extern int pgreadlink(const char *path, char *buf, size_t size);
+
+#define symlink(oldpath, newpath) pgsymlink(oldpath, newpath)
+#define readlink(path, buf, size) pgreadlink(path, buf, size)
+#endif
+
+extern bool rmtree(const char *path, bool rmtopdir);
+
+#if defined(WIN32) && !defined(__CYGWIN__)
+
+/*
+ * open() and fopen() replacements to allow deletion of open files and
+ * passing of other special options.
+ */
+#define O_DIRECT 0x80000000
+extern HANDLE pgwin32_open_handle(const char *, int, bool);
+extern int pgwin32_open(const char *, int,...);
+extern FILE *pgwin32_fopen(const char *, const char *);
+#define open(a,b,c) pgwin32_open(a,b,c)
+#define fopen(a,b) pgwin32_fopen(a,b)
+
+/*
+ * Mingw-w64 headers #define popen and pclose to _popen and _pclose. We want
+ * to use our popen wrapper, rather than plain _popen, so override that. For
+ * consistency, use our version of pclose, too.
+ */
+#ifdef popen
+#undef popen
+#endif
+#ifdef pclose
+#undef pclose
+#endif
+
+/*
+ * system() and popen() replacements to enclose the command in an extra
+ * pair of quotes.
+ */
+extern int pgwin32_system(const char *command);
+extern FILE *pgwin32_popen(const char *command, const char *type);
+
+#define system(a) pgwin32_system(a)
+#define popen(a,b) pgwin32_popen(a,b)
+#define pclose(a) _pclose(a)
+
+#else /* !WIN32 */
+
+/*
+ * Win32 requires a special close for sockets and pipes, while on Unix
+ * close() does them all.
+ */
+#define closesocket close
+#endif /* WIN32 */
+
+/*
+ * On Windows, setvbuf() does not support _IOLBF mode, and interprets that
+ * as _IOFBF. To add insult to injury, setvbuf(file, NULL, _IOFBF, 0)
+ * crashes outright if "parameter validation" is enabled. Therefore, in
+ * places where we'd like to select line-buffered mode, we fall back to
+ * unbuffered mode instead on Windows. Always use PG_IOLBF not _IOLBF
+ * directly in order to implement this behavior.
+ */
+#ifndef WIN32
+#define PG_IOLBF _IOLBF
+#else
+#define PG_IOLBF _IONBF
+#endif
+
+/*
+ * Default "extern" declarations or macro substitutes for library routines.
+ * When necessary, these routines are provided by files in src/port/.
+ */
+
+/* Type to use with fseeko/ftello */
+#ifndef WIN32 /* WIN32 is handled in port/win32_port.h */
+#define pgoff_t off_t
+#endif
+
+#ifndef HAVE_GETPEEREID
+/* On Windows, Perl might have incompatible definitions of uid_t and gid_t. */
+#ifndef PLPERL_HAVE_UID_GID
+extern int getpeereid(int sock, uid_t *uid, gid_t *gid);
+#endif
+#endif
+
+/*
+ * Glibc doesn't use the builtin for clang due to a *gcc* bug in a version
+ * newer than the gcc compatibility clang claims to have. This would cause a
+ * *lot* of superfluous function calls, therefore revert when using clang. In
+ * C++ there's issues with libc++ (not libstdc++), so disable as well.
+ */
+#if defined(__clang__) && !defined(__cplusplus)
+/* needs to be separate to not confuse other compilers */
+#if __has_builtin(__builtin_isinf)
+/* need to include before, to avoid getting overwritten */
+#include <math.h>
+#undef isinf
+#define isinf __builtin_isinf
+#endif /* __has_builtin(isinf) */
+#endif /* __clang__ && !__cplusplus */
+
+#ifndef HAVE_EXPLICIT_BZERO
+extern void explicit_bzero(void *buf, size_t len);
+#endif
+
+#ifdef HAVE_BUGGY_STRTOF
+extern float pg_strtof(const char *nptr, char **endptr);
+#define strtof(a,b) (pg_strtof((a),(b)))
+#endif
+
+#ifdef WIN32
+/* src/port/win32link.c */
+extern int link(const char *src, const char *dst);
+#endif
+
+#ifndef HAVE_MKDTEMP
+extern char *mkdtemp(char *path);
+#endif
+
+#ifndef HAVE_INET_ATON
+#include <netinet/in.h>
+#include <arpa/inet.h>
+extern int inet_aton(const char *cp, struct in_addr *addr);
+#endif
+
+#if !HAVE_DECL_STRLCAT
+extern size_t strlcat(char *dst, const char *src, size_t siz);
+#endif
+
+#if !HAVE_DECL_STRLCPY
+extern size_t strlcpy(char *dst, const char *src, size_t siz);
+#endif
+
+#if !HAVE_DECL_STRNLEN
+extern size_t strnlen(const char *str, size_t maxlen);
+#endif
+
+/* thread.c */
+#ifndef WIN32
+extern bool pg_get_user_name(uid_t user_id, char *buffer, size_t buflen);
+extern bool pg_get_user_home_dir(uid_t user_id, char *buffer, size_t buflen);
+#endif
+
+extern void pg_qsort(void *base, size_t nel, size_t elsize,
+ int (*cmp) (const void *, const void *));
+extern int pg_qsort_strcmp(const void *a, const void *b);
+
+#define qsort(a,b,c,d) pg_qsort(a,b,c,d)
+
+typedef int (*qsort_arg_comparator) (const void *a, const void *b, void *arg);
+
+extern void qsort_arg(void *base, size_t nel, size_t elsize,
+ qsort_arg_comparator cmp, void *arg);
+
+extern void qsort_interruptible(void *base, size_t nel, size_t elsize,
+ qsort_arg_comparator cmp, void *arg);
+
+extern void *bsearch_arg(const void *key, const void *base0,
+ size_t nmemb, size_t size,
+ int (*compar) (const void *, const void *, void *),
+ void *arg);
+
+/* port/chklocale.c */
+extern int pg_get_encoding_from_locale(const char *ctype, bool write_message);
+
+#if defined(WIN32) && !defined(FRONTEND)
+extern int pg_codepage_to_encoding(UINT cp);
+#endif
+
+/* port/inet_net_ntop.c */
+extern char *pg_inet_net_ntop(int af, const void *src, int bits,
+ char *dst, size_t size);
+
+/* port/pg_strong_random.c */
+extern void pg_strong_random_init(void);
+extern bool pg_strong_random(void *buf, size_t len);
+
+/*
+ * pg_backend_random used to be a wrapper for pg_strong_random before
+ * Postgres 12 for the backend code.
+ */
+#define pg_backend_random pg_strong_random
+
+/* port/pgcheckdir.c */
+extern int pg_check_dir(const char *dir);
+
+/* port/pgmkdirp.c */
+extern int pg_mkdir_p(char *path, int omode);
+
+/* port/pqsignal.c */
+typedef void (*pqsigfunc) (SIGNAL_ARGS);
+extern pqsigfunc pqsignal(int signo, pqsigfunc func);
+
+/* port/quotes.c */
+extern char *escape_single_quotes_ascii(const char *src);
+
+/* common/wait_error.c */
+extern char *wait_result_to_str(int exitstatus);
+extern bool wait_result_is_signal(int exit_status, int signum);
+extern bool wait_result_is_any_signal(int exit_status, bool include_command_not_found);
+extern int wait_result_to_exit_code(int exit_status);
+
+/*
+ * Interfaces that we assume all Unix system have. We retain individual macros
+ * for better documentation.
+ *
+ * For symlink-related functions, there is often no need to test these macros,
+ * because we provided basic support on Windows that can work with absolute
+ * paths to directories. Code that wants to test for complete symlink support
+ * (including relative paths and non-directories) should be conditional on
+ * HAVE_READLINK or HAVE_SYMLINK.
+ */
+#ifndef WIN32
+#define HAVE_GETRLIMIT 1
+#define HAVE_POLL 1
+#define HAVE_POLL_H 1
+#define HAVE_READLINK 1
+#define HAVE_SETSID 1
+#define HAVE_SHM_OPEN 1
+#define HAVE_SYMLINK 1
+#endif
+
+#endif /* PG_PORT_H */
diff --git a/contrib/libs/libpq/src/include/port/darwin.h b/contrib/libs/libpq/src/include/port/darwin.h
new file mode 100644
index 0000000000..15fb69d6db
--- /dev/null
+++ b/contrib/libs/libpq/src/include/port/darwin.h
@@ -0,0 +1,8 @@
+/* src/include/port/darwin.h */
+
+#define __darwin__ 1
+
+#if HAVE_DECL_F_FULLFSYNC /* not present before macOS 10.3 */
+#define HAVE_FSYNC_WRITETHROUGH
+
+#endif
diff --git a/contrib/libs/libpq/src/include/port/linux.h b/contrib/libs/libpq/src/include/port/linux.h
new file mode 100644
index 0000000000..7a6e46cdbb
--- /dev/null
+++ b/contrib/libs/libpq/src/include/port/linux.h
@@ -0,0 +1,22 @@
+/* src/include/port/linux.h */
+
+/*
+ * As of July 2007, all known versions of the Linux kernel will sometimes
+ * return EIDRM for a shmctl() operation when EINVAL is correct (it happens
+ * when the low-order 15 bits of the supplied shm ID match the slot number
+ * assigned to a newer shmem segment). We deal with this by assuming that
+ * EIDRM means EINVAL in PGSharedMemoryIsInUse(). This is reasonably safe
+ * since in fact Linux has no excuse for ever returning EIDRM; it doesn't
+ * track removed segments in a way that would allow distinguishing them from
+ * private ones. But someday that code might get upgraded, and we'd have
+ * to have a kernel version test here.
+ */
+#define HAVE_LINUX_EIDRM_BUG
+
+/*
+ * Set the default wal_sync_method to fdatasync. With recent Linux versions,
+ * xlogdefs.h's normal rules will prefer open_datasync, which (a) doesn't
+ * perform better and (b) causes outright failures on ext4 data=journal
+ * filesystems, because those don't support O_DIRECT.
+ */
+#define PLATFORM_DEFAULT_SYNC_METHOD SYNC_METHOD_FDATASYNC
diff --git a/contrib/libs/libpq/src/include/port/pg_bitutils.h b/contrib/libs/libpq/src/include/port/pg_bitutils.h
new file mode 100644
index 0000000000..21a4fa0341
--- /dev/null
+++ b/contrib/libs/libpq/src/include/port/pg_bitutils.h
@@ -0,0 +1,339 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_bitutils.h
+ * Miscellaneous functions for bit-wise operations.
+ *
+ *
+ * Copyright (c) 2019-2023, PostgreSQL Global Development Group
+ *
+ * src/include/port/pg_bitutils.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_BITUTILS_H
+#define PG_BITUTILS_H
+
+#ifdef _MSC_VER
+#include <intrin.h>
+#define HAVE_BITSCAN_FORWARD
+#define HAVE_BITSCAN_REVERSE
+
+#else
+#if defined(HAVE__BUILTIN_CTZ)
+#define HAVE_BITSCAN_FORWARD
+#endif
+
+#if defined(HAVE__BUILTIN_CLZ)
+#define HAVE_BITSCAN_REVERSE
+#endif
+#endif /* _MSC_VER */
+
+extern PGDLLIMPORT const uint8 pg_leftmost_one_pos[256];
+extern PGDLLIMPORT const uint8 pg_rightmost_one_pos[256];
+extern PGDLLIMPORT const uint8 pg_number_of_ones[256];
+
+/*
+ * pg_leftmost_one_pos32
+ * Returns the position of the most significant set bit in "word",
+ * measured from the least significant bit. word must not be 0.
+ */
+static inline int
+pg_leftmost_one_pos32(uint32 word)
+{
+#ifdef HAVE__BUILTIN_CLZ
+ Assert(word != 0);
+
+ return 31 - __builtin_clz(word);
+#elif defined(_MSC_VER)
+ unsigned long result;
+ bool non_zero;
+
+ non_zero = _BitScanReverse(&result, word);
+ Assert(non_zero);
+ return (int) result;
+#else
+ int shift = 32 - 8;
+
+ Assert(word != 0);
+
+ while ((word >> shift) == 0)
+ shift -= 8;
+
+ return shift + pg_leftmost_one_pos[(word >> shift) & 255];
+#endif /* HAVE__BUILTIN_CLZ */
+}
+
+/*
+ * pg_leftmost_one_pos64
+ * As above, but for a 64-bit word.
+ */
+static inline int
+pg_leftmost_one_pos64(uint64 word)
+{
+#ifdef HAVE__BUILTIN_CLZ
+ Assert(word != 0);
+
+#if defined(HAVE_LONG_INT_64)
+ 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 */
+
+#elif defined(_MSC_VER) && (defined(_M_AMD64) || defined(_M_ARM64))
+ unsigned long result;
+ bool non_zero;
+
+ non_zero = _BitScanReverse64(&result, word);
+ Assert(non_zero);
+ return (int) result;
+#else
+ int shift = 64 - 8;
+
+ Assert(word != 0);
+
+ while ((word >> shift) == 0)
+ shift -= 8;
+
+ return shift + pg_leftmost_one_pos[(word >> shift) & 255];
+#endif /* HAVE__BUILTIN_CLZ */
+}
+
+/*
+ * pg_rightmost_one_pos32
+ * Returns the position of the least significant set bit in "word",
+ * measured from the least significant bit. word must not be 0.
+ */
+static inline int
+pg_rightmost_one_pos32(uint32 word)
+{
+#ifdef HAVE__BUILTIN_CTZ
+ Assert(word != 0);
+
+ return __builtin_ctz(word);
+#elif defined(_MSC_VER)
+ unsigned long result;
+ bool non_zero;
+
+ non_zero = _BitScanForward(&result, word);
+ Assert(non_zero);
+ return (int) result;
+#else
+ int result = 0;
+
+ Assert(word != 0);
+
+ while ((word & 255) == 0)
+ {
+ word >>= 8;
+ result += 8;
+ }
+ result += pg_rightmost_one_pos[word & 255];
+ return result;
+#endif /* HAVE__BUILTIN_CTZ */
+}
+
+/*
+ * pg_rightmost_one_pos64
+ * As above, but for a 64-bit word.
+ */
+static inline int
+pg_rightmost_one_pos64(uint64 word)
+{
+#ifdef HAVE__BUILTIN_CTZ
+ Assert(word != 0);
+
+#if defined(HAVE_LONG_INT_64)
+ 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 */
+
+#elif defined(_MSC_VER) && (defined(_M_AMD64) || defined(_M_ARM64))
+ unsigned long result;
+ bool non_zero;
+
+ non_zero = _BitScanForward64(&result, word);
+ Assert(non_zero);
+ return (int) result;
+#else
+ int result = 0;
+
+ Assert(word != 0);
+
+ while ((word & 255) == 0)
+ {
+ word >>= 8;
+ result += 8;
+ }
+ result += pg_rightmost_one_pos[word & 255];
+ return result;
+#endif /* HAVE__BUILTIN_CTZ */
+}
+
+/*
+ * pg_nextpower2_32
+ * Returns the next higher power of 2 above 'num', or 'num' if it's
+ * already a power of 2.
+ *
+ * 'num' mustn't be 0 or be above PG_UINT32_MAX / 2 + 1.
+ */
+static inline uint32
+pg_nextpower2_32(uint32 num)
+{
+ Assert(num > 0 && num <= PG_UINT32_MAX / 2 + 1);
+
+ /*
+ * A power 2 number has only 1 bit set. Subtracting 1 from such a number
+ * will turn on all previous bits resulting in no common bits being set
+ * between num and num-1.
+ */
+ if ((num & (num - 1)) == 0)
+ return num; /* already power 2 */
+
+ return ((uint32) 1) << (pg_leftmost_one_pos32(num) + 1);
+}
+
+/*
+ * pg_nextpower2_64
+ * Returns the next higher power of 2 above 'num', or 'num' if it's
+ * already a power of 2.
+ *
+ * 'num' mustn't be 0 or be above PG_UINT64_MAX / 2 + 1.
+ */
+static inline uint64
+pg_nextpower2_64(uint64 num)
+{
+ Assert(num > 0 && num <= PG_UINT64_MAX / 2 + 1);
+
+ /*
+ * A power 2 number has only 1 bit set. Subtracting 1 from such a number
+ * will turn on all previous bits resulting in no common bits being set
+ * between num and num-1.
+ */
+ if ((num & (num - 1)) == 0)
+ return num; /* already power 2 */
+
+ return ((uint64) 1) << (pg_leftmost_one_pos64(num) + 1);
+}
+
+/*
+ * pg_prevpower2_32
+ * Returns the next lower power of 2 below 'num', or 'num' if it's
+ * already a power of 2.
+ *
+ * 'num' mustn't be 0.
+ */
+static inline uint32
+pg_prevpower2_32(uint32 num)
+{
+ return ((uint32) 1) << pg_leftmost_one_pos32(num);
+}
+
+/*
+ * pg_prevpower2_64
+ * Returns the next lower power of 2 below 'num', or 'num' if it's
+ * already a power of 2.
+ *
+ * 'num' mustn't be 0.
+ */
+static inline uint64
+pg_prevpower2_64(uint64 num)
+{
+ return ((uint64) 1) << pg_leftmost_one_pos64(num);
+}
+
+/*
+ * pg_ceil_log2_32
+ * Returns equivalent of ceil(log2(num))
+ */
+static inline uint32
+pg_ceil_log2_32(uint32 num)
+{
+ if (num < 2)
+ return 0;
+ else
+ return pg_leftmost_one_pos32(num - 1) + 1;
+}
+
+/*
+ * pg_ceil_log2_64
+ * Returns equivalent of ceil(log2(num))
+ */
+static inline uint64
+pg_ceil_log2_64(uint64 num)
+{
+ if (num < 2)
+ return 0;
+ else
+ return pg_leftmost_one_pos64(num - 1) + 1;
+}
+
+/*
+ * With MSVC on x86_64 builds, try using native popcnt instructions via the
+ * __popcnt and __popcnt64 intrinsics. These don't work the same as GCC's
+ * __builtin_popcount* intrinsic functions as they always emit popcnt
+ * instructions.
+ */
+#if defined(_MSC_VER) && defined(_M_AMD64)
+#define HAVE_X86_64_POPCNTQ
+#endif
+
+/*
+ * On x86_64, we can use the hardware popcount instruction, but only if
+ * we can verify that the CPU supports it via the cpuid instruction.
+ *
+ * Otherwise, we fall back to a hand-rolled implementation.
+ */
+#ifdef HAVE_X86_64_POPCNTQ
+#if defined(HAVE__GET_CPUID) || defined(HAVE__CPUID)
+#define TRY_POPCNT_FAST 1
+#endif
+#endif
+
+#ifdef TRY_POPCNT_FAST
+/* Attempt to use the POPCNT instruction, but perform a runtime check first */
+extern int (*pg_popcount32) (uint32 word);
+extern int (*pg_popcount64) (uint64 word);
+
+#else
+/* Use a portable implementation -- no need for a function pointer. */
+extern int pg_popcount32(uint32 word);
+extern int pg_popcount64(uint64 word);
+
+#endif /* TRY_POPCNT_FAST */
+
+/* Count the number of one-bits in a byte array */
+extern uint64 pg_popcount(const char *buf, int bytes);
+
+/*
+ * Rotate the bits of "word" to the right/left by n bits.
+ */
+static inline uint32
+pg_rotate_right32(uint32 word, int n)
+{
+ return (word >> n) | (word << (32 - n));
+}
+
+static inline uint32
+pg_rotate_left32(uint32 word, int n)
+{
+ return (word << n) | (word >> (32 - n));
+}
+
+/* size_t variants of the above, as required */
+
+#if SIZEOF_SIZE_T == 4
+#define pg_leftmost_one_pos_size_t pg_leftmost_one_pos32
+#define pg_nextpower2_size_t pg_nextpower2_32
+#define pg_prevpower2_size_t pg_prevpower2_32
+#else
+#define pg_leftmost_one_pos_size_t pg_leftmost_one_pos64
+#define pg_nextpower2_size_t pg_nextpower2_64
+#define pg_prevpower2_size_t pg_prevpower2_64
+#endif
+
+#endif /* PG_BITUTILS_H */
diff --git a/contrib/libs/libpq/src/include/port/pg_bswap.h b/contrib/libs/libpq/src/include/port/pg_bswap.h
new file mode 100644
index 0000000000..80abd750d4
--- /dev/null
+++ b/contrib/libs/libpq/src/include/port/pg_bswap.h
@@ -0,0 +1,161 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_bswap.h
+ * Byte swapping.
+ *
+ * Macros for reversing the byte order of 16, 32 and 64-bit unsigned integers.
+ * For example, 0xAABBCCDD becomes 0xDDCCBBAA. These are just wrappers for
+ * built-in functions provided by the compiler where support exists.
+ *
+ * Note that all of these functions accept unsigned integers as arguments and
+ * return the same. Use caution when using these wrapper macros with signed
+ * integers.
+ *
+ * Copyright (c) 2015-2023, PostgreSQL Global Development Group
+ *
+ * src/include/port/pg_bswap.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_BSWAP_H
+#define PG_BSWAP_H
+
+
+/*
+ * In all supported versions msvc provides _byteswap_* functions in stdlib.h,
+ * already included by c.h.
+ */
+
+
+/* implementation of uint16 pg_bswap16(uint16) */
+#if defined(HAVE__BUILTIN_BSWAP16)
+
+#define pg_bswap16(x) __builtin_bswap16(x)
+
+#elif defined(_MSC_VER)
+
+#define pg_bswap16(x) _byteswap_ushort(x)
+
+#else
+
+static inline uint16
+pg_bswap16(uint16 x)
+{
+ return
+ ((x << 8) & 0xff00) |
+ ((x >> 8) & 0x00ff);
+}
+
+#endif /* HAVE__BUILTIN_BSWAP16 */
+
+
+/* implementation of uint32 pg_bswap32(uint32) */
+#if defined(HAVE__BUILTIN_BSWAP32)
+
+#define pg_bswap32(x) __builtin_bswap32(x)
+
+#elif defined(_MSC_VER)
+
+#define pg_bswap32(x) _byteswap_ulong(x)
+
+#else
+
+static inline uint32
+pg_bswap32(uint32 x)
+{
+ return
+ ((x << 24) & 0xff000000) |
+ ((x << 8) & 0x00ff0000) |
+ ((x >> 8) & 0x0000ff00) |
+ ((x >> 24) & 0x000000ff);
+}
+
+#endif /* HAVE__BUILTIN_BSWAP32 */
+
+
+/* implementation of uint64 pg_bswap64(uint64) */
+#if defined(HAVE__BUILTIN_BSWAP64)
+
+#define pg_bswap64(x) __builtin_bswap64(x)
+
+
+#elif defined(_MSC_VER)
+
+#define pg_bswap64(x) _byteswap_uint64(x)
+
+#else
+
+static inline uint64
+pg_bswap64(uint64 x)
+{
+ return
+ ((x << 56) & UINT64CONST(0xff00000000000000)) |
+ ((x << 40) & UINT64CONST(0x00ff000000000000)) |
+ ((x << 24) & UINT64CONST(0x0000ff0000000000)) |
+ ((x << 8) & UINT64CONST(0x000000ff00000000)) |
+ ((x >> 8) & UINT64CONST(0x00000000ff000000)) |
+ ((x >> 24) & UINT64CONST(0x0000000000ff0000)) |
+ ((x >> 40) & UINT64CONST(0x000000000000ff00)) |
+ ((x >> 56) & UINT64CONST(0x00000000000000ff));
+}
+#endif /* HAVE__BUILTIN_BSWAP64 */
+
+
+/*
+ * Portable and fast equivalents for ntohs, ntohl, htons, htonl,
+ * additionally extended to 64 bits.
+ */
+#ifdef WORDS_BIGENDIAN
+
+#define pg_hton16(x) (x)
+#define pg_hton32(x) (x)
+#define pg_hton64(x) (x)
+
+#define pg_ntoh16(x) (x)
+#define pg_ntoh32(x) (x)
+#define pg_ntoh64(x) (x)
+
+#else
+
+#define pg_hton16(x) pg_bswap16(x)
+#define pg_hton32(x) pg_bswap32(x)
+#define pg_hton64(x) pg_bswap64(x)
+
+#define pg_ntoh16(x) pg_bswap16(x)
+#define pg_ntoh32(x) pg_bswap32(x)
+#define pg_ntoh64(x) pg_bswap64(x)
+
+#endif /* WORDS_BIGENDIAN */
+
+
+/*
+ * Rearrange the bytes of a Datum from big-endian order into the native byte
+ * order. On big-endian machines, this does nothing at all. Note that the C
+ * type Datum is an unsigned integer type on all platforms.
+ *
+ * One possible application of the DatumBigEndianToNative() macro is to make
+ * bitwise comparisons cheaper. A simple 3-way comparison of Datums
+ * transformed by the macro (based on native, unsigned comparisons) will return
+ * the same result as a memcmp() of the corresponding original Datums, but can
+ * be much cheaper. It's generally safe to do this on big-endian systems
+ * without any special transformation occurring first.
+ *
+ * If SIZEOF_DATUM is not defined, then postgres.h wasn't included and these
+ * macros probably shouldn't be used, so we define nothing. Note that
+ * SIZEOF_DATUM == 8 would evaluate as 0 == 8 in that case, potentially
+ * leading to the wrong implementation being selected and confusing errors, so
+ * defining nothing is safest.
+ */
+#ifdef SIZEOF_DATUM
+#ifdef WORDS_BIGENDIAN
+#define DatumBigEndianToNative(x) (x)
+#else /* !WORDS_BIGENDIAN */
+#if SIZEOF_DATUM == 8
+#define DatumBigEndianToNative(x) pg_bswap64(x)
+#else /* SIZEOF_DATUM != 8 */
+#define DatumBigEndianToNative(x) pg_bswap32(x)
+#endif /* SIZEOF_DATUM == 8 */
+#endif /* WORDS_BIGENDIAN */
+#endif /* SIZEOF_DATUM */
+
+#endif /* PG_BSWAP_H */
diff --git a/contrib/libs/libpq/src/include/port/pg_crc32c.h b/contrib/libs/libpq/src/include/port/pg_crc32c.h
new file mode 100644
index 0000000000..7f8779261c
--- /dev/null
+++ b/contrib/libs/libpq/src/include/port/pg_crc32c.h
@@ -0,0 +1,101 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_crc32c.h
+ * Routines for computing CRC-32C checksums.
+ *
+ * The speed of CRC-32C calculation has a big impact on performance, so we
+ * jump through some hoops to get the best implementation for each
+ * platform. Some CPU architectures have special instructions for speeding
+ * up CRC calculations (e.g. Intel SSE 4.2), on other platforms we use the
+ * Slicing-by-8 algorithm which uses lookup tables.
+ *
+ * The public interface consists of four macros:
+ *
+ * INIT_CRC32C(crc)
+ * Initialize a CRC accumulator
+ *
+ * COMP_CRC32C(crc, data, len)
+ * Accumulate some (more) bytes into a CRC
+ *
+ * FIN_CRC32C(crc)
+ * Finish a CRC calculation
+ *
+ * EQ_CRC32C(c1, c2)
+ * Check for equality of two CRCs.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/port/pg_crc32c.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_CRC32C_H
+#define PG_CRC32C_H
+
+#include "port/pg_bswap.h"
+
+typedef uint32 pg_crc32c;
+
+/* The INIT and EQ macros are the same for all implementations. */
+#define INIT_CRC32C(crc) ((crc) = 0xFFFFFFFF)
+#define EQ_CRC32C(c1, c2) ((c1) == (c2))
+
+#if defined(USE_SSE42_CRC32C)
+/* Use Intel SSE4.2 instructions. */
+#define COMP_CRC32C(crc, data, len) \
+ ((crc) = pg_comp_crc32c_sse42((crc), (data), (len)))
+#define FIN_CRC32C(crc) ((crc) ^= 0xFFFFFFFF)
+
+extern pg_crc32c pg_comp_crc32c_sse42(pg_crc32c crc, const void *data, size_t len);
+
+#elif defined(USE_ARMV8_CRC32C)
+/* Use ARMv8 CRC Extension instructions. */
+
+#define COMP_CRC32C(crc, data, len) \
+ ((crc) = pg_comp_crc32c_armv8((crc), (data), (len)))
+#define FIN_CRC32C(crc) ((crc) ^= 0xFFFFFFFF)
+
+extern pg_crc32c pg_comp_crc32c_armv8(pg_crc32c crc, const void *data, size_t len);
+
+#elif defined(USE_SSE42_CRC32C_WITH_RUNTIME_CHECK) || defined(USE_ARMV8_CRC32C_WITH_RUNTIME_CHECK)
+
+/*
+ * Use Intel SSE 4.2 or ARMv8 instructions, but perform a runtime check first
+ * to check that they are available.
+ */
+#define COMP_CRC32C(crc, data, len) \
+ ((crc) = pg_comp_crc32c((crc), (data), (len)))
+#define FIN_CRC32C(crc) ((crc) ^= 0xFFFFFFFF)
+
+extern pg_crc32c pg_comp_crc32c_sb8(pg_crc32c crc, const void *data, size_t len);
+extern pg_crc32c (*pg_comp_crc32c) (pg_crc32c crc, const void *data, size_t len);
+
+#ifdef USE_SSE42_CRC32C_WITH_RUNTIME_CHECK
+extern pg_crc32c pg_comp_crc32c_sse42(pg_crc32c crc, const void *data, size_t len);
+#endif
+#ifdef USE_ARMV8_CRC32C_WITH_RUNTIME_CHECK
+extern pg_crc32c pg_comp_crc32c_armv8(pg_crc32c crc, const void *data, size_t len);
+#endif
+
+#else
+/*
+ * Use slicing-by-8 algorithm.
+ *
+ * On big-endian systems, the intermediate value is kept in reverse byte
+ * order, to avoid byte-swapping during the calculation. FIN_CRC32C reverses
+ * the bytes to the final order.
+ */
+#define COMP_CRC32C(crc, data, len) \
+ ((crc) = pg_comp_crc32c_sb8((crc), (data), (len)))
+#ifdef WORDS_BIGENDIAN
+#define FIN_CRC32C(crc) ((crc) = pg_bswap32(crc) ^ 0xFFFFFFFF)
+#else
+#define FIN_CRC32C(crc) ((crc) ^= 0xFFFFFFFF)
+#endif
+
+extern pg_crc32c pg_comp_crc32c_sb8(pg_crc32c crc, const void *data, size_t len);
+
+#endif
+
+#endif /* PG_CRC32C_H */
diff --git a/contrib/libs/libpq/src/include/port/pg_iovec.h b/contrib/libs/libpq/src/include/port/pg_iovec.h
new file mode 100644
index 0000000000..689799c425
--- /dev/null
+++ b/contrib/libs/libpq/src/include/port/pg_iovec.h
@@ -0,0 +1,55 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_iovec.h
+ * Header for vectored I/O functions, to use in place of <sys/uio.h>.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/port/pg_iovec.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_IOVEC_H
+#define PG_IOVEC_H
+
+#ifndef WIN32
+
+#include <limits.h>
+#include <sys/uio.h>
+
+#else
+
+/* POSIX requires at least 16 as a maximum iovcnt. */
+#define IOV_MAX 16
+
+/* Define our own POSIX-compatible iovec struct. */
+struct iovec
+{
+ void *iov_base;
+ size_t iov_len;
+};
+
+#endif
+
+/* Define a reasonable maximum that is safe to use on the stack. */
+#define PG_IOV_MAX Min(IOV_MAX, 32)
+
+/*
+ * Note that pg_preadv and pg_pwritev have a pg_ prefix as a warning that the
+ * Windows implementations have the side-effect of changing the file position.
+ */
+
+#if HAVE_DECL_PREADV
+#define pg_preadv preadv
+#else
+extern ssize_t pg_preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset);
+#endif
+
+#if HAVE_DECL_PWRITEV
+#define pg_pwritev pwritev
+#else
+extern ssize_t pg_pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset);
+#endif
+
+#endif /* PG_IOVEC_H */
diff --git a/contrib/libs/libpq/src/include/port/pg_lfind.h b/contrib/libs/libpq/src/include/port/pg_lfind.h
new file mode 100644
index 0000000000..59aa8245ed
--- /dev/null
+++ b/contrib/libs/libpq/src/include/port/pg_lfind.h
@@ -0,0 +1,180 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_lfind.h
+ * Optimized linear search routines using SIMD intrinsics where
+ * available.
+ *
+ * Copyright (c) 2022-2023, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/include/port/pg_lfind.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_LFIND_H
+#define PG_LFIND_H
+
+#include "port/simd.h"
+
+/*
+ * pg_lfind8
+ *
+ * Return true if there is an element in 'base' that equals 'key', otherwise
+ * return false.
+ */
+static inline bool
+pg_lfind8(uint8 key, uint8 *base, uint32 nelem)
+{
+ uint32 i;
+
+ /* round down to multiple of vector length */
+ uint32 tail_idx = nelem & ~(sizeof(Vector8) - 1);
+ Vector8 chunk;
+
+ for (i = 0; i < tail_idx; i += sizeof(Vector8))
+ {
+ vector8_load(&chunk, &base[i]);
+ if (vector8_has(chunk, key))
+ return true;
+ }
+
+ /* Process the remaining elements one at a time. */
+ for (; i < nelem; i++)
+ {
+ if (key == base[i])
+ return true;
+ }
+
+ return false;
+}
+
+/*
+ * pg_lfind8_le
+ *
+ * Return true if there is an element in 'base' that is less than or equal to
+ * 'key', otherwise return false.
+ */
+static inline bool
+pg_lfind8_le(uint8 key, uint8 *base, uint32 nelem)
+{
+ uint32 i;
+
+ /* round down to multiple of vector length */
+ uint32 tail_idx = nelem & ~(sizeof(Vector8) - 1);
+ Vector8 chunk;
+
+ for (i = 0; i < tail_idx; i += sizeof(Vector8))
+ {
+ vector8_load(&chunk, &base[i]);
+ if (vector8_has_le(chunk, key))
+ return true;
+ }
+
+ /* Process the remaining elements one at a time. */
+ for (; i < nelem; i++)
+ {
+ if (base[i] <= key)
+ return true;
+ }
+
+ return false;
+}
+
+/*
+ * pg_lfind32
+ *
+ * Return true if there is an element in 'base' that equals 'key', otherwise
+ * return false.
+ */
+static inline bool
+pg_lfind32(uint32 key, uint32 *base, uint32 nelem)
+{
+ uint32 i = 0;
+
+#ifndef USE_NO_SIMD
+
+ /*
+ * For better instruction-level parallelism, each loop iteration operates
+ * on a block of four registers. Testing for SSE2 has showed this is ~40%
+ * faster than using a block of two registers.
+ */
+ const Vector32 keys = vector32_broadcast(key); /* load copies of key */
+ const uint32 nelem_per_vector = sizeof(Vector32) / sizeof(uint32);
+ const uint32 nelem_per_iteration = 4 * nelem_per_vector;
+
+ /* round down to multiple of elements per iteration */
+ const uint32 tail_idx = nelem & ~(nelem_per_iteration - 1);
+
+#if defined(USE_ASSERT_CHECKING)
+ bool assert_result = false;
+
+ /* pre-compute the result for assert checking */
+ for (i = 0; i < nelem; i++)
+ {
+ if (key == base[i])
+ {
+ assert_result = true;
+ break;
+ }
+ }
+#endif
+
+ for (i = 0; i < tail_idx; i += nelem_per_iteration)
+ {
+ Vector32 vals1,
+ vals2,
+ vals3,
+ vals4,
+ result1,
+ result2,
+ result3,
+ result4,
+ tmp1,
+ tmp2,
+ result;
+
+ /* load the next block into 4 registers */
+ vector32_load(&vals1, &base[i]);
+ vector32_load(&vals2, &base[i + nelem_per_vector]);
+ vector32_load(&vals3, &base[i + nelem_per_vector * 2]);
+ vector32_load(&vals4, &base[i + nelem_per_vector * 3]);
+
+ /* compare each value to the key */
+ result1 = vector32_eq(keys, vals1);
+ result2 = vector32_eq(keys, vals2);
+ result3 = vector32_eq(keys, vals3);
+ result4 = vector32_eq(keys, vals4);
+
+ /* combine the results into a single variable */
+ tmp1 = vector32_or(result1, result2);
+ tmp2 = vector32_or(result3, result4);
+ result = vector32_or(tmp1, tmp2);
+
+ /* see if there was a match */
+ if (vector32_is_highbit_set(result))
+ {
+ Assert(assert_result == true);
+ return true;
+ }
+ }
+#endif /* ! USE_NO_SIMD */
+
+ /* Process the remaining elements one at a time. */
+ for (; i < nelem; i++)
+ {
+ if (key == base[i])
+ {
+#ifndef USE_NO_SIMD
+ Assert(assert_result == true);
+#endif
+ return true;
+ }
+ }
+
+#ifndef USE_NO_SIMD
+ Assert(assert_result == false);
+#endif
+ return false;
+}
+
+#endif /* PG_LFIND_H */
diff --git a/contrib/libs/libpq/src/include/port/simd.h b/contrib/libs/libpq/src/include/port/simd.h
new file mode 100644
index 0000000000..1fa6c3bc6c
--- /dev/null
+++ b/contrib/libs/libpq/src/include/port/simd.h
@@ -0,0 +1,375 @@
+/*-------------------------------------------------------------------------
+ *
+ * simd.h
+ * Support for platform-specific vector operations.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/port/simd.h
+ *
+ * NOTES
+ * - VectorN in this file refers to a register where the element operands
+ * are N bits wide. The vector width is platform-specific, so users that care
+ * about that will need to inspect "sizeof(VectorN)".
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SIMD_H
+#define SIMD_H
+
+#if (defined(__x86_64__) || defined(_M_AMD64))
+/*
+ * SSE2 instructions are part of the spec for the 64-bit x86 ISA. We assume
+ * that compilers targeting this architecture understand SSE2 intrinsics.
+ *
+ * We use emmintrin.h rather than the comprehensive header immintrin.h in
+ * order to exclude extensions beyond SSE2. This is because MSVC, at least,
+ * will allow the use of intrinsics that haven't been enabled at compile
+ * time.
+ */
+#include <emmintrin.h>
+#define USE_SSE2
+typedef __m128i Vector8;
+typedef __m128i Vector32;
+
+#elif defined(__aarch64__) && defined(__ARM_NEON)
+/*
+ * We use the Neon instructions if the compiler provides access to them (as
+ * indicated by __ARM_NEON) and we are on aarch64. While Neon support is
+ * technically optional for aarch64, it appears that all available 64-bit
+ * hardware does have it. Neon exists in some 32-bit hardware too, but we
+ * could not realistically use it there without a run-time check, which seems
+ * not worth the trouble for now.
+ */
+#include <arm_neon.h>
+#define USE_NEON
+typedef uint8x16_t Vector8;
+typedef uint32x4_t Vector32;
+
+#else
+/*
+ * If no SIMD instructions are available, we can in some cases emulate vector
+ * operations using bitwise operations on unsigned integers. Note that many
+ * of the functions in this file presently do not have non-SIMD
+ * implementations. In particular, none of the functions involving Vector32
+ * are implemented without SIMD since it's likely not worthwhile to represent
+ * two 32-bit integers using a uint64.
+ */
+#define USE_NO_SIMD
+typedef uint64 Vector8;
+#endif
+
+/* load/store operations */
+static inline void vector8_load(Vector8 *v, const uint8 *s);
+#ifndef USE_NO_SIMD
+static inline void vector32_load(Vector32 *v, const uint32 *s);
+#endif
+
+/* assignment operations */
+static inline Vector8 vector8_broadcast(const uint8 c);
+#ifndef USE_NO_SIMD
+static inline Vector32 vector32_broadcast(const uint32 c);
+#endif
+
+/* element-wise comparisons to a scalar */
+static inline bool vector8_has(const Vector8 v, const uint8 c);
+static inline bool vector8_has_zero(const Vector8 v);
+static inline bool vector8_has_le(const Vector8 v, const uint8 c);
+static inline bool vector8_is_highbit_set(const Vector8 v);
+#ifndef USE_NO_SIMD
+static inline bool vector32_is_highbit_set(const Vector32 v);
+#endif
+
+/* arithmetic operations */
+static inline Vector8 vector8_or(const Vector8 v1, const Vector8 v2);
+#ifndef USE_NO_SIMD
+static inline Vector32 vector32_or(const Vector32 v1, const Vector32 v2);
+static inline Vector8 vector8_ssub(const Vector8 v1, const Vector8 v2);
+#endif
+
+/*
+ * comparisons between vectors
+ *
+ * Note: These return a vector rather than boolean, which is why we don't
+ * have non-SIMD implementations.
+ */
+#ifndef USE_NO_SIMD
+static inline Vector8 vector8_eq(const Vector8 v1, const Vector8 v2);
+static inline Vector32 vector32_eq(const Vector32 v1, const Vector32 v2);
+#endif
+
+/*
+ * Load a chunk of memory into the given vector.
+ */
+static inline void
+vector8_load(Vector8 *v, const uint8 *s)
+{
+#if defined(USE_SSE2)
+ *v = _mm_loadu_si128((const __m128i *) s);
+#elif defined(USE_NEON)
+ *v = vld1q_u8(s);
+#else
+ memcpy(v, s, sizeof(Vector8));
+#endif
+}
+
+#ifndef USE_NO_SIMD
+static inline void
+vector32_load(Vector32 *v, const uint32 *s)
+{
+#ifdef USE_SSE2
+ *v = _mm_loadu_si128((const __m128i *) s);
+#elif defined(USE_NEON)
+ *v = vld1q_u32(s);
+#endif
+}
+#endif /* ! USE_NO_SIMD */
+
+/*
+ * Create a vector with all elements set to the same value.
+ */
+static inline Vector8
+vector8_broadcast(const uint8 c)
+{
+#if defined(USE_SSE2)
+ return _mm_set1_epi8(c);
+#elif defined(USE_NEON)
+ return vdupq_n_u8(c);
+#else
+ return ~UINT64CONST(0) / 0xFF * c;
+#endif
+}
+
+#ifndef USE_NO_SIMD
+static inline Vector32
+vector32_broadcast(const uint32 c)
+{
+#ifdef USE_SSE2
+ return _mm_set1_epi32(c);
+#elif defined(USE_NEON)
+ return vdupq_n_u32(c);
+#endif
+}
+#endif /* ! USE_NO_SIMD */
+
+/*
+ * Return true if any elements in the vector are equal to the given scalar.
+ */
+static inline bool
+vector8_has(const Vector8 v, const uint8 c)
+{
+ bool result;
+
+ /* pre-compute the result for assert checking */
+#ifdef USE_ASSERT_CHECKING
+ bool assert_result = false;
+
+ for (Size i = 0; i < sizeof(Vector8); i++)
+ {
+ if (((const uint8 *) &v)[i] == c)
+ {
+ assert_result = true;
+ break;
+ }
+ }
+#endif /* USE_ASSERT_CHECKING */
+
+#if defined(USE_NO_SIMD)
+ /* any bytes in v equal to c will evaluate to zero via XOR */
+ result = vector8_has_zero(v ^ vector8_broadcast(c));
+#else
+ result = vector8_is_highbit_set(vector8_eq(v, vector8_broadcast(c)));
+#endif
+
+ Assert(assert_result == result);
+ return result;
+}
+
+/*
+ * Convenience function equivalent to vector8_has(v, 0)
+ */
+static inline bool
+vector8_has_zero(const Vector8 v)
+{
+#if defined(USE_NO_SIMD)
+ /*
+ * We cannot call vector8_has() here, because that would lead to a
+ * circular definition.
+ */
+ return vector8_has_le(v, 0);
+#else
+ return vector8_has(v, 0);
+#endif
+}
+
+/*
+ * Return true if any elements in the vector are less than or equal to the
+ * given scalar.
+ */
+static inline bool
+vector8_has_le(const Vector8 v, const uint8 c)
+{
+ bool result = false;
+
+ /* pre-compute the result for assert checking */
+#ifdef USE_ASSERT_CHECKING
+ bool assert_result = false;
+
+ for (Size i = 0; i < sizeof(Vector8); i++)
+ {
+ if (((const uint8 *) &v)[i] <= c)
+ {
+ assert_result = true;
+ break;
+ }
+ }
+#endif /* USE_ASSERT_CHECKING */
+
+#if defined(USE_NO_SIMD)
+
+ /*
+ * To find bytes <= c, we can use bitwise operations to find bytes < c+1,
+ * but it only works if c+1 <= 128 and if the highest bit in v is not set.
+ * Adapted from
+ * https://graphics.stanford.edu/~seander/bithacks.html#HasLessInWord
+ */
+ if ((int64) v >= 0 && c < 0x80)
+ result = (v - vector8_broadcast(c + 1)) & ~v & vector8_broadcast(0x80);
+ else
+ {
+ /* one byte at a time */
+ for (Size i = 0; i < sizeof(Vector8); i++)
+ {
+ if (((const uint8 *) &v)[i] <= c)
+ {
+ result = true;
+ break;
+ }
+ }
+ }
+#else
+
+ /*
+ * Use saturating subtraction to find bytes <= c, which will present as
+ * NUL bytes. This approach is a workaround for the lack of unsigned
+ * comparison instructions on some architectures.
+ */
+ result = vector8_has_zero(vector8_ssub(v, vector8_broadcast(c)));
+#endif
+
+ Assert(assert_result == result);
+ return result;
+}
+
+/*
+ * Return true if the high bit of any element is set
+ */
+static inline bool
+vector8_is_highbit_set(const Vector8 v)
+{
+#ifdef USE_SSE2
+ return _mm_movemask_epi8(v) != 0;
+#elif defined(USE_NEON)
+ return vmaxvq_u8(v) > 0x7F;
+#else
+ return v & vector8_broadcast(0x80);
+#endif
+}
+
+/*
+ * Exactly like vector8_is_highbit_set except for the input type, so it
+ * looks at each byte separately.
+ *
+ * XXX x86 uses the same underlying type for 8-bit, 16-bit, and 32-bit
+ * integer elements, but Arm does not, hence the need for a separate
+ * function. We could instead adopt the behavior of Arm's vmaxvq_u32(), i.e.
+ * check each 32-bit element, but that would require an additional mask
+ * operation on x86.
+ */
+#ifndef USE_NO_SIMD
+static inline bool
+vector32_is_highbit_set(const Vector32 v)
+{
+#if defined(USE_NEON)
+ return vector8_is_highbit_set((Vector8) v);
+#else
+ return vector8_is_highbit_set(v);
+#endif
+}
+#endif /* ! USE_NO_SIMD */
+
+/*
+ * Return the bitwise OR of the inputs
+ */
+static inline Vector8
+vector8_or(const Vector8 v1, const Vector8 v2)
+{
+#ifdef USE_SSE2
+ return _mm_or_si128(v1, v2);
+#elif defined(USE_NEON)
+ return vorrq_u8(v1, v2);
+#else
+ return v1 | v2;
+#endif
+}
+
+#ifndef USE_NO_SIMD
+static inline Vector32
+vector32_or(const Vector32 v1, const Vector32 v2)
+{
+#ifdef USE_SSE2
+ return _mm_or_si128(v1, v2);
+#elif defined(USE_NEON)
+ return vorrq_u32(v1, v2);
+#endif
+}
+#endif /* ! USE_NO_SIMD */
+
+/*
+ * Return the result of subtracting the respective elements of the input
+ * vectors using saturation (i.e., if the operation would yield a value less
+ * than zero, zero is returned instead). For more information on saturation
+ * arithmetic, see https://en.wikipedia.org/wiki/Saturation_arithmetic
+ */
+#ifndef USE_NO_SIMD
+static inline Vector8
+vector8_ssub(const Vector8 v1, const Vector8 v2)
+{
+#ifdef USE_SSE2
+ return _mm_subs_epu8(v1, v2);
+#elif defined(USE_NEON)
+ return vqsubq_u8(v1, v2);
+#endif
+}
+#endif /* ! USE_NO_SIMD */
+
+/*
+ * Return a vector with all bits set in each lane where the corresponding
+ * lanes in the inputs are equal.
+ */
+#ifndef USE_NO_SIMD
+static inline Vector8
+vector8_eq(const Vector8 v1, const Vector8 v2)
+{
+#ifdef USE_SSE2
+ return _mm_cmpeq_epi8(v1, v2);
+#elif defined(USE_NEON)
+ return vceqq_u8(v1, v2);
+#endif
+}
+#endif /* ! USE_NO_SIMD */
+
+#ifndef USE_NO_SIMD
+static inline Vector32
+vector32_eq(const Vector32 v1, const Vector32 v2)
+{
+#ifdef USE_SSE2
+ return _mm_cmpeq_epi32(v1, v2);
+#elif defined(USE_NEON)
+ return vceqq_u32(v1, v2);
+#endif
+}
+#endif /* ! USE_NO_SIMD */
+
+#endif /* SIMD_H */
diff --git a/contrib/libs/libpq/src/include/port/win32.h b/contrib/libs/libpq/src/include/port/win32.h
new file mode 100644
index 0000000000..5867e5622f
--- /dev/null
+++ b/contrib/libs/libpq/src/include/port/win32.h
@@ -0,0 +1,60 @@
+/* src/include/port/win32.h */
+#pragma once
+
+/*
+ * We always rely on the WIN32 macro being set by our build system,
+ * but _WIN32 is the compiler pre-defined macro. So make sure we define
+ * WIN32 whenever _WIN32 is set, to facilitate standalone building.
+ */
+#if defined(_WIN32) && !defined(WIN32)
+#define WIN32
+#endif
+
+/*
+ * Make sure _WIN32_WINNT has the minimum required value.
+ * Leave a higher value in place. The minimum requirement is Windows 10.
+ */
+#ifdef _WIN32_WINNT
+#undef _WIN32_WINNT
+#endif
+
+#define _WIN32_WINNT 0x0A00
+
+/*
+ * We need to prevent <crtdefs.h> from defining a symbol conflicting with
+ * our errcode() function. Since it's likely to get included by standard
+ * system headers, pre-emptively include it now.
+ */
+#if defined(_MSC_VER) || defined(HAVE_CRTDEFS_H)
+#define errcode __msvc_errcode
+#include <crtdefs.h>
+#undef errcode
+#endif
+
+/*
+ * defines for dynamic linking on Win32 platform
+ */
+
+/*
+ * Variables declared in the core backend and referenced by loadable
+ * modules need to be marked "dllimport" in the core build, but
+ * "dllexport" when the declaration is read in a loadable module.
+ * No special markings should be used when compiling frontend code.
+ */
+#ifndef FRONTEND
+#ifdef BUILDING_DLL
+#define PGDLLIMPORT __declspec (dllexport)
+#else
+#define PGDLLIMPORT __declspec (dllimport)
+#endif
+#endif
+
+/*
+ * Functions exported by a loadable module must be marked "dllexport".
+ *
+ * While mingw would otherwise fall back to
+ * __attribute__((visibility("default"))), that appears to only work as long
+ * as no symbols are declared with __declspec(dllexport). But we can end up
+ * with some, e.g. plpython's Py_Init.
+ */
+#define PGDLLEXPORT __declspec (dllexport)
diff --git a/contrib/libs/libpq/src/include/port/win32/arpa/inet.h b/contrib/libs/libpq/src/include/port/win32/arpa/inet.h
new file mode 100644
index 0000000000..ad1803179c
--- /dev/null
+++ b/contrib/libs/libpq/src/include/port/win32/arpa/inet.h
@@ -0,0 +1,3 @@
+/* src/include/port/win32/arpa/inet.h */
+
+#include <sys/socket.h>
diff --git a/contrib/libs/libpq/src/include/port/win32/netdb.h b/contrib/libs/libpq/src/include/port/win32/netdb.h
new file mode 100644
index 0000000000..9ed13e457b
--- /dev/null
+++ b/contrib/libs/libpq/src/include/port/win32/netdb.h
@@ -0,0 +1,7 @@
+/* src/include/port/win32/netdb.h */
+#ifndef WIN32_NETDB_H
+#define WIN32_NETDB_H
+
+#include <ws2tcpip.h>
+
+#endif
diff --git a/contrib/libs/libpq/src/include/port/win32/netinet/in.h b/contrib/libs/libpq/src/include/port/win32/netinet/in.h
new file mode 100644
index 0000000000..a4e22f89f4
--- /dev/null
+++ b/contrib/libs/libpq/src/include/port/win32/netinet/in.h
@@ -0,0 +1,3 @@
+/* src/include/port/win32/netinet/in.h */
+
+#include <sys/socket.h>
diff --git a/contrib/libs/libpq/src/include/port/win32/netinet/tcp.h b/contrib/libs/libpq/src/include/port/win32/netinet/tcp.h
new file mode 100644
index 0000000000..1d377b6adc
--- /dev/null
+++ b/contrib/libs/libpq/src/include/port/win32/netinet/tcp.h
@@ -0,0 +1,7 @@
+/* src/include/port/win32/netinet/tcp.h */
+#ifndef WIN32_NETINET_TCP_H
+#define WIN32_NETINET_TCP_H
+
+#include <sys/socket.h>
+
+#endif
diff --git a/contrib/libs/libpq/src/include/port/win32/pwd.h b/contrib/libs/libpq/src/include/port/win32/pwd.h
new file mode 100644
index 0000000000..b8c7178fc0
--- /dev/null
+++ b/contrib/libs/libpq/src/include/port/win32/pwd.h
@@ -0,0 +1,3 @@
+/*
+ * src/include/port/win32/pwd.h
+ */
diff --git a/contrib/libs/libpq/src/include/port/win32/sys/select.h b/contrib/libs/libpq/src/include/port/win32/sys/select.h
new file mode 100644
index 0000000000..f8a877accd
--- /dev/null
+++ b/contrib/libs/libpq/src/include/port/win32/sys/select.h
@@ -0,0 +1,3 @@
+/*
+ * src/include/port/win32/sys/select.h
+ */
diff --git a/contrib/libs/libpq/src/include/port/win32/sys/socket.h b/contrib/libs/libpq/src/include/port/win32/sys/socket.h
new file mode 100644
index 0000000000..0c32c0f7b2
--- /dev/null
+++ b/contrib/libs/libpq/src/include/port/win32/sys/socket.h
@@ -0,0 +1,26 @@
+/*
+ * src/include/port/win32/sys/socket.h
+ */
+#ifndef WIN32_SYS_SOCKET_H
+#define WIN32_SYS_SOCKET_H
+
+/*
+ * Unfortunately, <wingdi.h> of VC++ also defines ERROR.
+ * To avoid the conflict, we include <windows.h> here and undefine ERROR
+ * immediately.
+ *
+ * Note: Don't include <wingdi.h> directly. It causes compile errors.
+ */
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <windows.h>
+
+#undef ERROR
+#undef small
+
+/* Restore old ERROR value */
+#ifdef PGERROR
+#define ERROR PGERROR
+#endif
+
+#endif /* WIN32_SYS_SOCKET_H */
diff --git a/contrib/libs/libpq/src/include/port/win32/sys/un.h b/contrib/libs/libpq/src/include/port/win32/sys/un.h
new file mode 100644
index 0000000000..4fc13a23fd
--- /dev/null
+++ b/contrib/libs/libpq/src/include/port/win32/sys/un.h
@@ -0,0 +1,17 @@
+/*
+ * src/include/port/win32/sys/un.h
+ */
+#ifndef WIN32_SYS_UN_H
+#define WIN32_SYS_UN_H
+
+/*
+ * Windows defines this structure in <afunix.h>, but not all tool chains have
+ * the header yet, so we define it here for now.
+ */
+struct sockaddr_un
+{
+ unsigned short sun_family;
+ char sun_path[108];
+};
+
+#endif
diff --git a/contrib/libs/libpq/src/include/port/win32/sys/wait.h b/contrib/libs/libpq/src/include/port/win32/sys/wait.h
new file mode 100644
index 0000000000..eaeb5661c9
--- /dev/null
+++ b/contrib/libs/libpq/src/include/port/win32/sys/wait.h
@@ -0,0 +1,3 @@
+/*
+ * src/include/port/win32/sys/wait.h
+ */
diff --git a/contrib/libs/libpq/src/include/port/win32_msvc/dirent.h b/contrib/libs/libpq/src/include/port/win32_msvc/dirent.h
new file mode 100644
index 0000000000..62799db001
--- /dev/null
+++ b/contrib/libs/libpq/src/include/port/win32_msvc/dirent.h
@@ -0,0 +1,34 @@
+/*
+ * Headers for port/dirent.c, win32 native implementation of dirent functions
+ *
+ * src/include/port/win32_msvc/dirent.h
+ */
+
+#ifndef _WIN32VC_DIRENT_H
+#define _WIN32VC_DIRENT_H
+struct dirent
+{
+ long d_ino;
+ unsigned short d_reclen;
+ unsigned char d_type;
+ unsigned short d_namlen;
+ char d_name[MAX_PATH];
+};
+
+typedef struct DIR DIR;
+
+DIR *opendir(const char *);
+struct dirent *readdir(DIR *);
+int closedir(DIR *);
+
+/* File types for 'd_type'. */
+#define DT_UNKNOWN 0
+#define DT_FIFO 1
+#define DT_CHR 2
+#define DT_DIR 4
+#define DT_BLK 6
+#define DT_REG 8
+#define DT_LNK 10
+#define DT_SOCK 12
+#define DT_WHT 14
+#endif
diff --git a/contrib/libs/libpq/src/include/port/win32_msvc/sys/file.h b/contrib/libs/libpq/src/include/port/win32_msvc/sys/file.h
new file mode 100644
index 0000000000..76be3e7774
--- /dev/null
+++ b/contrib/libs/libpq/src/include/port/win32_msvc/sys/file.h
@@ -0,0 +1 @@
+/* src/include/port/win32_msvc/sys/file.h */
diff --git a/contrib/libs/libpq/src/include/port/win32_msvc/sys/param.h b/contrib/libs/libpq/src/include/port/win32_msvc/sys/param.h
new file mode 100644
index 0000000000..160df3b25e
--- /dev/null
+++ b/contrib/libs/libpq/src/include/port/win32_msvc/sys/param.h
@@ -0,0 +1 @@
+/* src/include/port/win32_msvc/sys/param.h */
diff --git a/contrib/libs/libpq/src/include/port/win32_msvc/sys/time.h b/contrib/libs/libpq/src/include/port/win32_msvc/sys/time.h
new file mode 100644
index 0000000000..9d943ecc6f
--- /dev/null
+++ b/contrib/libs/libpq/src/include/port/win32_msvc/sys/time.h
@@ -0,0 +1 @@
+/* src/include/port/win32_msvc/sys/time.h */
diff --git a/contrib/libs/libpq/src/include/port/win32_msvc/unistd.h b/contrib/libs/libpq/src/include/port/win32_msvc/unistd.h
new file mode 100644
index 0000000000..b7795ba03c
--- /dev/null
+++ b/contrib/libs/libpq/src/include/port/win32_msvc/unistd.h
@@ -0,0 +1,9 @@
+/* src/include/port/win32_msvc/unistd.h */
+
+/*
+ * MSVC does not define these, nor does _fileno(stdin) etc reliably work
+ * (returns -1 if stdin/out/err are closed).
+ */
+#define STDIN_FILENO 0
+#define STDOUT_FILENO 1
+#define STDERR_FILENO 2
diff --git a/contrib/libs/libpq/src/include/port/win32_port.h b/contrib/libs/libpq/src/include/port/win32_port.h
new file mode 100644
index 0000000000..b957d5c598
--- /dev/null
+++ b/contrib/libs/libpq/src/include/port/win32_port.h
@@ -0,0 +1,594 @@
+/*-------------------------------------------------------------------------
+ *
+ * win32_port.h
+ * Windows-specific compatibility stuff.
+ *
+ * Note this is read in MinGW as well as native Windows builds,
+ * but not in Cygwin builds.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/port/win32_port.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_WIN32_PORT_H
+#define PG_WIN32_PORT_H
+
+/*
+ * Always build with SSPI support. Keep it as a #define in case
+ * we want a switch to disable it sometime in the future.
+ */
+#define ENABLE_SSPI 1
+
+/* undefine and redefine after #include */
+#undef mkdir
+
+#undef ERROR
+
+/*
+ * VS2013 and later issue warnings about using the old Winsock API,
+ * which we don't really want to hear about.
+ */
+#ifdef _MSC_VER
+#define _WINSOCK_DEPRECATED_NO_WARNINGS
+#endif
+
+/*
+ * The MinGW64 headers choke if this is already defined - they
+ * define it themselves.
+ */
+#if !defined(__MINGW64_VERSION_MAJOR) || defined(_MSC_VER)
+#define _WINSOCKAPI_
+#endif
+
+/*
+ * windows.h includes a lot of other headers, slowing down compilation
+ * significantly. WIN32_LEAN_AND_MEAN reduces that a bit. It'd be better to
+ * remove the include of windows.h (as well as indirect inclusions of it) from
+ * such a central place, but until then...
+ *
+ * To be able to include ntstatus.h tell windows.h to not declare NTSTATUS by
+ * temporarily defining UMDF_USING_NTSTATUS, otherwise we'll get warning about
+ * macro redefinitions, as windows.h also defines NTSTATUS (yuck). That in
+ * turn requires including ntstatus.h, winternl.h to get common symbols.
+ */
+#define WIN32_LEAN_AND_MEAN
+#define UMDF_USING_NTSTATUS
+
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <windows.h>
+#include <ntstatus.h>
+#include <winternl.h>
+
+#undef small
+#include <process.h>
+#include <signal.h>
+#include <direct.h>
+#undef near
+
+/* needed before sys/stat hacking below: */
+#define fstat microsoft_native_fstat
+#define stat microsoft_native_stat
+#include <sys/stat.h>
+#undef fstat
+#undef stat
+
+/* Must be here to avoid conflicting with prototype in windows.h */
+#define mkdir(a,b) mkdir(a)
+
+#define ftruncate(a,b) chsize(a,b)
+
+/* Windows doesn't have fsync() as such, use _commit() */
+#define fsync(fd) _commit(fd)
+
+/*
+ * For historical reasons, we allow setting wal_sync_method to
+ * fsync_writethrough on Windows, even though it's really identical to fsync
+ * (both code paths wind up at _commit()).
+ */
+#define HAVE_FSYNC_WRITETHROUGH
+#define FSYNC_WRITETHROUGH_IS_FSYNC
+
+#define USES_WINSOCK
+
+/*
+ * IPC defines
+ */
+#undef HAVE_UNION_SEMUN
+#define HAVE_UNION_SEMUN 1
+
+#define IPC_RMID 256
+#define IPC_CREAT 512
+#define IPC_EXCL 1024
+#define IPC_PRIVATE 234564
+#define IPC_NOWAIT 2048
+#define IPC_STAT 4096
+
+#define EACCESS 2048
+#ifndef EIDRM
+#define EIDRM 4096
+#endif
+
+#define SETALL 8192
+#define GETNCNT 16384
+#define GETVAL 65536
+#define SETVAL 131072
+#define GETPID 262144
+
+
+/*
+ * Signal stuff
+ *
+ * For WIN32, there is no wait() call so there are no wait() macros
+ * to interpret the return value of system(). Instead, system()
+ * return values < 0x100 are used for exit() termination, and higher
+ * values are used to indicate non-exit() termination, which is
+ * similar to a unix-style signal exit (think SIGSEGV ==
+ * STATUS_ACCESS_VIOLATION). Return values are broken up into groups:
+ *
+ * https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/using-ntstatus-values
+ *
+ * NT_SUCCESS 0 - 0x3FFFFFFF
+ * NT_INFORMATION 0x40000000 - 0x7FFFFFFF
+ * NT_WARNING 0x80000000 - 0xBFFFFFFF
+ * NT_ERROR 0xC0000000 - 0xFFFFFFFF
+ *
+ * Effectively, we don't care on the severity of the return value from
+ * system(), we just need to know if it was because of exit() or generated
+ * by the system, and it seems values >= 0x100 are system-generated.
+ * See this URL for a list of WIN32 STATUS_* values:
+ *
+ * Wine (URL used in our error messages) -
+ * http://source.winehq.org/source/include/ntstatus.h
+ * Descriptions -
+ * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/596a1078-e883-4972-9bbc-49e60bebca55
+ *
+ * The comprehensive exception list is included in ntstatus.h from the
+ * Windows Driver Kit (WDK). A subset of the list is also included in
+ * winnt.h from the Windows SDK. Defining WIN32_NO_STATUS before including
+ * windows.h helps to avoid any conflicts.
+ *
+ * Some day we might want to print descriptions for the most common
+ * exceptions, rather than printing an include file name. We could use
+ * RtlNtStatusToDosError() and pass to FormatMessage(), which can print
+ * the text of error values, but MinGW does not support
+ * RtlNtStatusToDosError().
+ */
+#define WIFEXITED(w) (((w) & 0XFFFFFF00) == 0)
+#define WIFSIGNALED(w) (!WIFEXITED(w))
+#define WEXITSTATUS(w) (w)
+#define WTERMSIG(w) (w)
+
+#define sigmask(sig) ( 1 << ((sig)-1) )
+
+/* Signal function return values */
+#undef SIG_DFL
+#undef SIG_ERR
+#undef SIG_IGN
+#define SIG_DFL ((pqsigfunc)0)
+#define SIG_ERR ((pqsigfunc)-1)
+#define SIG_IGN ((pqsigfunc)1)
+
+/* Some extra signals */
+#define SIGHUP 1
+#define SIGQUIT 3
+#define SIGTRAP 5
+#define SIGABRT 22 /* Set to match W32 value -- not UNIX value */
+#define SIGKILL 9
+#define SIGPIPE 13
+#define SIGALRM 14
+#define SIGSTOP 17
+#define SIGTSTP 18
+#define SIGCONT 19
+#define SIGCHLD 20
+#define SIGWINCH 28
+#define SIGUSR1 30
+#define SIGUSR2 31
+
+/* MinGW has gettimeofday(), but MSVC doesn't */
+#ifdef _MSC_VER
+/* Last parameter not used */
+extern int gettimeofday(struct timeval *tp, void *tzp);
+#endif
+
+/* for setitimer in backend/port/win32/timer.c */
+#define ITIMER_REAL 0
+struct itimerval
+{
+ struct timeval it_interval;
+ struct timeval it_value;
+};
+
+int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue);
+
+/* Convenience wrapper for GetFileType() */
+extern DWORD pgwin32_get_file_type(HANDLE hFile);
+
+/*
+ * WIN32 does not provide 64-bit off_t, but does provide the functions operating
+ * with 64-bit offsets. Also, fseek() might not give an error for unseekable
+ * streams, so harden that function with our version.
+ */
+#define pgoff_t __int64
+
+#ifdef _MSC_VER
+extern int _pgfseeko64(FILE *stream, pgoff_t offset, int origin);
+extern pgoff_t _pgftello64(FILE *stream);
+#define fseeko(stream, offset, origin) _pgfseeko64(stream, offset, origin)
+#define ftello(stream) _pgftello64(stream)
+#else
+#ifndef fseeko
+#define fseeko(stream, offset, origin) fseeko64(stream, offset, origin)
+#endif
+#ifndef ftello
+#define ftello(stream) ftello64(stream)
+#endif
+#endif
+
+/*
+ * Win32 also doesn't have symlinks, but we can emulate them with
+ * junction points on newer Win32 versions.
+ *
+ * Cygwin has its own symlinks which work on Win95/98/ME where
+ * junction points don't, so use those instead. We have no way of
+ * knowing what type of system Cygwin binaries will be run on.
+ * Note: Some CYGWIN includes might #define WIN32.
+ */
+extern int pgsymlink(const char *oldpath, const char *newpath);
+extern int pgreadlink(const char *path, char *buf, size_t size);
+
+#define symlink(oldpath, newpath) pgsymlink(oldpath, newpath)
+#define readlink(path, buf, size) pgreadlink(path, buf, size)
+
+/*
+ * Supplement to <sys/types.h>.
+ *
+ * Perl already has typedefs for uid_t and gid_t.
+ */
+#ifndef PLPERL_HAVE_UID_GID
+typedef int uid_t;
+typedef int gid_t;
+#endif
+typedef long key_t;
+
+#ifdef _MSC_VER
+typedef int pid_t;
+#endif
+
+/*
+ * Supplement to <sys/stat.h>.
+ *
+ * We must pull in sys/stat.h before this part, else our overrides lose.
+ *
+ * stat() is not guaranteed to set the st_size field on win32, so we
+ * redefine it to our own implementation. See src/port/win32stat.c.
+ *
+ * The struct stat is 32 bit in MSVC, so we redefine it as a copy of
+ * struct __stat64. This also fixes the struct size for MINGW builds.
+ */
+struct stat /* This should match struct __stat64 */
+{
+ _dev_t st_dev;
+ _ino_t st_ino;
+ unsigned short st_mode;
+ short st_nlink;
+ short st_uid;
+ short st_gid;
+ _dev_t st_rdev;
+ __int64 st_size;
+ __time64_t st_atime;
+ __time64_t st_mtime;
+ __time64_t st_ctime;
+};
+
+extern int _pgfstat64(int fileno, struct stat *buf);
+extern int _pgstat64(const char *name, struct stat *buf);
+extern int _pglstat64(const char *name, struct stat *buf);
+
+#define fstat(fileno, sb) _pgfstat64(fileno, sb)
+#define stat(path, sb) _pgstat64(path, sb)
+#define lstat(path, sb) _pglstat64(path, sb)
+
+/* These macros are not provided by older MinGW, nor by MSVC */
+#ifndef S_IRUSR
+#define S_IRUSR _S_IREAD
+#endif
+#ifndef S_IWUSR
+#define S_IWUSR _S_IWRITE
+#endif
+#ifndef S_IXUSR
+#define S_IXUSR _S_IEXEC
+#endif
+#ifndef S_IRWXU
+#define S_IRWXU (S_IRUSR | S_IWUSR | S_IXUSR)
+#endif
+#ifndef S_IRGRP
+#define S_IRGRP 0
+#endif
+#ifndef S_IWGRP
+#define S_IWGRP 0
+#endif
+#ifndef S_IXGRP
+#define S_IXGRP 0
+#endif
+#ifndef S_IRWXG
+#define S_IRWXG 0
+#endif
+#ifndef S_IROTH
+#define S_IROTH 0
+#endif
+#ifndef S_IWOTH
+#define S_IWOTH 0
+#endif
+#ifndef S_IXOTH
+#define S_IXOTH 0
+#endif
+#ifndef S_IRWXO
+#define S_IRWXO 0
+#endif
+#ifndef S_ISDIR
+#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+#endif
+#ifndef S_ISREG
+#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+#endif
+
+/*
+ * In order for lstat() to be able to report junction points as symlinks, we
+ * need to hijack a bit in st_mode, since neither MSVC nor MinGW provides
+ * S_ISLNK and there aren't any spare bits. We'll steal the one for character
+ * devices, because we don't otherwise make use of those.
+ */
+#ifdef S_ISLNK
+#error "S_ISLNK is already defined"
+#endif
+#ifdef S_IFLNK
+#error "S_IFLNK is already defined"
+#endif
+#define S_IFLNK S_IFCHR
+#define S_ISLNK(m) (((m) & S_IFLNK) == S_IFLNK)
+
+/*
+ * Supplement to <fcntl.h>.
+ * This is the same value as _O_NOINHERIT in the MS header file. This is
+ * to ensure that we don't collide with a future definition. It means
+ * we cannot use _O_NOINHERIT ourselves.
+ */
+#define O_DSYNC 0x0080
+
+/*
+ * Our open() replacement does not create inheritable handles, so it is safe to
+ * ignore O_CLOEXEC. (If we were using Windows' own open(), it might be
+ * necessary to convert this to _O_NOINHERIT.)
+ */
+#define O_CLOEXEC 0
+
+/*
+ * Supplement to <errno.h>.
+ *
+ * We redefine network-related Berkeley error symbols as the corresponding WSA
+ * constants. This allows strerror.c to recognize them as being in the Winsock
+ * error code range and pass them off to win32_socket_strerror(), since
+ * Windows' version of plain strerror() won't cope. Note that this will break
+ * if these names are used for anything else besides Windows Sockets errors.
+ * See TranslateSocketError() when changing this list.
+ */
+#undef EAGAIN
+#define EAGAIN WSAEWOULDBLOCK
+#undef EINTR
+#define EINTR WSAEINTR
+#undef EMSGSIZE
+#define EMSGSIZE WSAEMSGSIZE
+#undef EAFNOSUPPORT
+#define EAFNOSUPPORT WSAEAFNOSUPPORT
+#undef EWOULDBLOCK
+#define EWOULDBLOCK WSAEWOULDBLOCK
+#undef ECONNABORTED
+#define ECONNABORTED WSAECONNABORTED
+#undef ECONNRESET
+#define ECONNRESET WSAECONNRESET
+#undef EINPROGRESS
+#define EINPROGRESS WSAEINPROGRESS
+#undef EISCONN
+#define EISCONN WSAEISCONN
+#undef ENOBUFS
+#define ENOBUFS WSAENOBUFS
+#undef EPROTONOSUPPORT
+#define EPROTONOSUPPORT WSAEPROTONOSUPPORT
+#undef ECONNREFUSED
+#define ECONNREFUSED WSAECONNREFUSED
+#undef ENOTSOCK
+#define ENOTSOCK WSAENOTSOCK
+#undef EOPNOTSUPP
+#define EOPNOTSUPP WSAEOPNOTSUPP
+#undef EADDRINUSE
+#define EADDRINUSE WSAEADDRINUSE
+#undef EADDRNOTAVAIL
+#define EADDRNOTAVAIL WSAEADDRNOTAVAIL
+#undef EHOSTDOWN
+#define EHOSTDOWN WSAEHOSTDOWN
+#undef EHOSTUNREACH
+#define EHOSTUNREACH WSAEHOSTUNREACH
+#undef ENETDOWN
+#define ENETDOWN WSAENETDOWN
+#undef ENETRESET
+#define ENETRESET WSAENETRESET
+#undef ENETUNREACH
+#define ENETUNREACH WSAENETUNREACH
+#undef ENOTCONN
+#define ENOTCONN WSAENOTCONN
+#undef ETIMEDOUT
+#define ETIMEDOUT WSAETIMEDOUT
+
+/*
+ * Locale stuff.
+ *
+ * Extended locale functions with gratuitous underscore prefixes.
+ * (These APIs are nevertheless fully documented by Microsoft.)
+ */
+#define locale_t _locale_t
+#define tolower_l _tolower_l
+#define toupper_l _toupper_l
+#define towlower_l _towlower_l
+#define towupper_l _towupper_l
+#define isdigit_l _isdigit_l
+#define iswdigit_l _iswdigit_l
+#define isalpha_l _isalpha_l
+#define iswalpha_l _iswalpha_l
+#define isalnum_l _isalnum_l
+#define iswalnum_l _iswalnum_l
+#define isupper_l _isupper_l
+#define iswupper_l _iswupper_l
+#define islower_l _islower_l
+#define iswlower_l _iswlower_l
+#define isgraph_l _isgraph_l
+#define iswgraph_l _iswgraph_l
+#define isprint_l _isprint_l
+#define iswprint_l _iswprint_l
+#define ispunct_l _ispunct_l
+#define iswpunct_l _iswpunct_l
+#define isspace_l _isspace_l
+#define iswspace_l _iswspace_l
+#define strcoll_l _strcoll_l
+#define strxfrm_l _strxfrm_l
+#define wcscoll_l _wcscoll_l
+#define wcstombs_l _wcstombs_l
+#define mbstowcs_l _mbstowcs_l
+
+/*
+ * Versions of libintl >= 0.18? try to replace setlocale() with a macro
+ * to their own versions. Remove the macro, if it exists, because it
+ * ends up calling the wrong version when the backend and libintl use
+ * different versions of msvcrt.
+ */
+#if defined(setlocale)
+#undef setlocale
+#endif
+
+/*
+ * Define our own wrapper macro around setlocale() to work around bugs in
+ * Windows' native setlocale() function.
+ */
+extern char *pgwin32_setlocale(int category, const char *locale);
+
+#define setlocale(a,b) pgwin32_setlocale(a,b)
+
+
+/* In backend/port/win32/signal.c */
+extern PGDLLIMPORT volatile int pg_signal_queue;
+extern PGDLLIMPORT int pg_signal_mask;
+extern PGDLLIMPORT HANDLE pgwin32_signal_event;
+extern PGDLLIMPORT HANDLE pgwin32_initial_signal_pipe;
+
+#define UNBLOCKED_SIGNAL_QUEUE() (pg_signal_queue & ~pg_signal_mask)
+#define PG_SIGNAL_COUNT 32
+
+extern void pgwin32_signal_initialize(void);
+extern HANDLE pgwin32_create_signal_listener(pid_t pid);
+extern void pgwin32_dispatch_queued_signals(void);
+extern void pg_queue_signal(int signum);
+
+/* In src/port/kill.c */
+#define kill(pid,sig) pgkill(pid,sig)
+extern int pgkill(int pid, int sig);
+
+/* In backend/port/win32/socket.c */
+#ifndef FRONTEND
+#define socket(af, type, protocol) pgwin32_socket(af, type, protocol)
+#define bind(s, addr, addrlen) pgwin32_bind(s, addr, addrlen)
+#define listen(s, backlog) pgwin32_listen(s, backlog)
+#define accept(s, addr, addrlen) pgwin32_accept(s, addr, addrlen)
+#define connect(s, name, namelen) pgwin32_connect(s, name, namelen)
+#define select(n, r, w, e, timeout) pgwin32_select(n, r, w, e, timeout)
+#define recv(s, buf, len, flags) pgwin32_recv(s, buf, len, flags)
+#define send(s, buf, len, flags) pgwin32_send(s, buf, len, flags)
+
+extern SOCKET pgwin32_socket(int af, int type, int protocol);
+extern int pgwin32_bind(SOCKET s, struct sockaddr *addr, int addrlen);
+extern int pgwin32_listen(SOCKET s, int backlog);
+extern SOCKET pgwin32_accept(SOCKET s, struct sockaddr *addr, int *addrlen);
+extern int pgwin32_connect(SOCKET s, const struct sockaddr *name, int namelen);
+extern int pgwin32_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timeval *timeout);
+extern int pgwin32_recv(SOCKET s, char *buf, int len, int flags);
+extern int pgwin32_send(SOCKET s, const void *buf, int len, int flags);
+extern int pgwin32_waitforsinglesocket(SOCKET s, int what, int timeout);
+
+extern PGDLLIMPORT int pgwin32_noblock;
+
+#endif /* FRONTEND */
+
+/* in backend/port/win32_shmem.c */
+extern int pgwin32_ReserveSharedMemoryRegion(HANDLE);
+
+/* in backend/port/win32/crashdump.c */
+extern void pgwin32_install_crashdump_handler(void);
+
+/* in port/win32dlopen.c */
+extern void *dlopen(const char *file, int mode);
+extern void *dlsym(void *handle, const char *symbol);
+extern int dlclose(void *handle);
+extern char *dlerror(void);
+
+#define RTLD_NOW 1
+#define RTLD_GLOBAL 0
+
+/* in port/win32error.c */
+extern void _dosmaperr(unsigned long);
+
+/* in port/win32env.c */
+extern int pgwin32_putenv(const char *);
+extern int pgwin32_setenv(const char *name, const char *value, int overwrite);
+extern int pgwin32_unsetenv(const char *name);
+
+#define putenv(x) pgwin32_putenv(x)
+#define setenv(x,y,z) pgwin32_setenv(x,y,z)
+#define unsetenv(x) pgwin32_unsetenv(x)
+
+/* in port/win32security.c */
+extern int pgwin32_is_service(void);
+extern int pgwin32_is_admin(void);
+
+/* Windows security token manipulation (in src/common/exec.c) */
+extern BOOL AddUserToTokenDacl(HANDLE hToken);
+
+/* Things that exist in MinGW headers, but need to be added to MSVC */
+#ifdef _MSC_VER
+
+#ifndef _WIN64
+typedef long ssize_t;
+#else
+typedef __int64 ssize_t;
+#endif
+
+typedef unsigned short mode_t;
+
+#define F_OK 0
+#define W_OK 2
+#define R_OK 4
+
+#endif /* _MSC_VER */
+
+#if defined(__MINGW32__) || defined(__MINGW64__)
+/*
+ * Mingw claims to have a strtof, and my reading of its source code suggests
+ * that it ought to work (and not need this hack), but the regression test
+ * results disagree with me; whether this is a version issue or not is not
+ * clear. However, using our wrapper (and the misrounded-input variant file,
+ * already required for supporting ancient systems) can't make things any
+ * worse, except for a tiny performance loss when reading zeros.
+ *
+ * See also cygwin.h for another instance of this.
+ */
+#define HAVE_BUGGY_STRTOF 1
+#endif
+
+/* in port/win32pread.c */
+extern ssize_t pg_pread(int fd, void *buf, size_t nbyte, off_t offset);
+
+/* in port/win32pwrite.c */
+extern ssize_t pg_pwrite(int fd, const void *buf, size_t nbyte, off_t offset);
+
+#endif /* PG_WIN32_PORT_H */
diff --git a/contrib/libs/libpq/src/include/port/win32ntdll.h b/contrib/libs/libpq/src/include/port/win32ntdll.h
new file mode 100644
index 0000000000..1ce9360ec1
--- /dev/null
+++ b/contrib/libs/libpq/src/include/port/win32ntdll.h
@@ -0,0 +1,34 @@
+/*-------------------------------------------------------------------------
+ *
+ * win32ntdll.h
+ * Dynamically loaded Windows NT functions.
+ *
+ * Portions Copyright (c) 2021-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/port/win32ntdll.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef WIN32NTDLL_H
+#define WIN32NTDLL_H
+
+#include <ntstatus.h>
+#include <winternl.h>
+
+#ifndef FLUSH_FLAGS_FILE_DATA_SYNC_ONLY
+#define FLUSH_FLAGS_FILE_DATA_SYNC_ONLY 0x4
+#endif
+
+typedef NTSTATUS (__stdcall * RtlGetLastNtStatus_t) (void);
+typedef ULONG (__stdcall * RtlNtStatusToDosError_t) (NTSTATUS);
+typedef NTSTATUS (__stdcall * NtFlushBuffersFileEx_t) (HANDLE, ULONG, PVOID, ULONG, PIO_STATUS_BLOCK);
+
+extern PGDLLIMPORT RtlGetLastNtStatus_t pg_RtlGetLastNtStatus;
+extern PGDLLIMPORT RtlNtStatusToDosError_t pg_RtlNtStatusToDosError;
+extern PGDLLIMPORT NtFlushBuffersFileEx_t pg_NtFlushBuffersFileEx;
+
+extern int initialize_ntdll(void);
+
+#endif /* WIN32NTDLL_H */
diff --git a/contrib/libs/libpq/src/include/postgres.h b/contrib/libs/libpq/src/include/postgres.h
new file mode 100644
index 0000000000..8a028ff789
--- /dev/null
+++ b/contrib/libs/libpq/src/include/postgres.h
@@ -0,0 +1,579 @@
+/*-------------------------------------------------------------------------
+ *
+ * postgres.h
+ * Primary include file for PostgreSQL server .c files
+ *
+ * This should be the first file included by PostgreSQL backend modules.
+ * Client-side code should include postgres_fe.h instead.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1995, Regents of the University of California
+ *
+ * src/include/postgres.h
+ *
+ *-------------------------------------------------------------------------
+ */
+/*
+ *----------------------------------------------------------------
+ * TABLE OF CONTENTS
+ *
+ * When adding stuff to this file, please try to put stuff
+ * into the relevant section, or add new sections as appropriate.
+ *
+ * section description
+ * ------- ------------------------------------------------
+ * 1) Datum type + support functions
+ * 2) miscellaneous
+ *
+ * NOTES
+ *
+ * In general, this file should contain declarations that are widely needed
+ * in the backend environment, but are of no interest outside the backend.
+ *
+ * Simple type definitions live in c.h, where they are shared with
+ * postgres_fe.h. We do that since those type definitions are needed by
+ * frontend modules that want to deal with binary data transmission to or
+ * from the backend. Type definitions in this file should be for
+ * representations that never escape the backend, such as Datum.
+ *
+ *----------------------------------------------------------------
+ */
+#ifndef POSTGRES_H
+#define POSTGRES_H
+
+#include "c.h"
+#include "utils/elog.h"
+#include "utils/palloc.h"
+
+/* ----------------------------------------------------------------
+ * Section 1: Datum type + support functions
+ * ----------------------------------------------------------------
+ */
+
+/*
+ * A Datum contains either a value of a pass-by-value type or a pointer to a
+ * value of a pass-by-reference type. Therefore, we require:
+ *
+ * sizeof(Datum) == sizeof(void *) == 4 or 8
+ *
+ * The functions below and the analogous functions for other types should be used to
+ * convert between a Datum and the appropriate C type.
+ */
+
+typedef uintptr_t Datum;
+
+/*
+ * A NullableDatum is used in places where both a Datum and its nullness needs
+ * to be stored. This can be more efficient than storing datums and nullness
+ * in separate arrays, due to better spatial locality, even if more space may
+ * be wasted due to padding.
+ */
+typedef struct NullableDatum
+{
+#define FIELDNO_NULLABLE_DATUM_DATUM 0
+ Datum value;
+#define FIELDNO_NULLABLE_DATUM_ISNULL 1
+ bool isnull;
+ /* due to alignment padding this could be used for flags for free */
+} NullableDatum;
+
+#define SIZEOF_DATUM SIZEOF_VOID_P
+
+/*
+ * DatumGetBool
+ * Returns boolean value of a datum.
+ *
+ * Note: any nonzero value will be considered true.
+ */
+static inline bool
+DatumGetBool(Datum X)
+{
+ return (X != 0);
+}
+
+/*
+ * BoolGetDatum
+ * Returns datum representation for a boolean.
+ *
+ * Note: any nonzero value will be considered true.
+ */
+static inline Datum
+BoolGetDatum(bool X)
+{
+ return (Datum) (X ? 1 : 0);
+}
+
+/*
+ * DatumGetChar
+ * Returns character value of a datum.
+ */
+static inline char
+DatumGetChar(Datum X)
+{
+ return (char) X;
+}
+
+/*
+ * CharGetDatum
+ * Returns datum representation for a character.
+ */
+static inline Datum
+CharGetDatum(char X)
+{
+ return (Datum) X;
+}
+
+/*
+ * Int8GetDatum
+ * Returns datum representation for an 8-bit integer.
+ */
+static inline Datum
+Int8GetDatum(int8 X)
+{
+ return (Datum) X;
+}
+
+/*
+ * DatumGetUInt8
+ * Returns 8-bit unsigned integer value of a datum.
+ */
+static inline uint8
+DatumGetUInt8(Datum X)
+{
+ return (uint8) X;
+}
+
+/*
+ * UInt8GetDatum
+ * Returns datum representation for an 8-bit unsigned integer.
+ */
+static inline Datum
+UInt8GetDatum(uint8 X)
+{
+ return (Datum) X;
+}
+
+/*
+ * DatumGetInt16
+ * Returns 16-bit integer value of a datum.
+ */
+static inline int16
+DatumGetInt16(Datum X)
+{
+ return (int16) X;
+}
+
+/*
+ * Int16GetDatum
+ * Returns datum representation for a 16-bit integer.
+ */
+static inline Datum
+Int16GetDatum(int16 X)
+{
+ return (Datum) X;
+}
+
+/*
+ * DatumGetUInt16
+ * Returns 16-bit unsigned integer value of a datum.
+ */
+static inline uint16
+DatumGetUInt16(Datum X)
+{
+ return (uint16) X;
+}
+
+/*
+ * UInt16GetDatum
+ * Returns datum representation for a 16-bit unsigned integer.
+ */
+static inline Datum
+UInt16GetDatum(uint16 X)
+{
+ return (Datum) X;
+}
+
+/*
+ * DatumGetInt32
+ * Returns 32-bit integer value of a datum.
+ */
+static inline int32
+DatumGetInt32(Datum X)
+{
+ return (int32) X;
+}
+
+/*
+ * Int32GetDatum
+ * Returns datum representation for a 32-bit integer.
+ */
+static inline Datum
+Int32GetDatum(int32 X)
+{
+ return (Datum) X;
+}
+
+/*
+ * DatumGetUInt32
+ * Returns 32-bit unsigned integer value of a datum.
+ */
+static inline uint32
+DatumGetUInt32(Datum X)
+{
+ return (uint32) X;
+}
+
+/*
+ * UInt32GetDatum
+ * Returns datum representation for a 32-bit unsigned integer.
+ */
+static inline Datum
+UInt32GetDatum(uint32 X)
+{
+ return (Datum) X;
+}
+
+/*
+ * DatumGetObjectId
+ * Returns object identifier value of a datum.
+ */
+static inline Oid
+DatumGetObjectId(Datum X)
+{
+ return (Oid) X;
+}
+
+/*
+ * ObjectIdGetDatum
+ * Returns datum representation for an object identifier.
+ */
+static inline Datum
+ObjectIdGetDatum(Oid X)
+{
+ return (Datum) X;
+}
+
+/*
+ * DatumGetTransactionId
+ * Returns transaction identifier value of a datum.
+ */
+static inline TransactionId
+DatumGetTransactionId(Datum X)
+{
+ return (TransactionId) X;
+}
+
+/*
+ * TransactionIdGetDatum
+ * Returns datum representation for a transaction identifier.
+ */
+static inline Datum
+TransactionIdGetDatum(TransactionId X)
+{
+ return (Datum) X;
+}
+
+/*
+ * MultiXactIdGetDatum
+ * Returns datum representation for a multixact identifier.
+ */
+static inline Datum
+MultiXactIdGetDatum(MultiXactId X)
+{
+ return (Datum) X;
+}
+
+/*
+ * DatumGetCommandId
+ * Returns command identifier value of a datum.
+ */
+static inline CommandId
+DatumGetCommandId(Datum X)
+{
+ return (CommandId) X;
+}
+
+/*
+ * CommandIdGetDatum
+ * Returns datum representation for a command identifier.
+ */
+static inline Datum
+CommandIdGetDatum(CommandId X)
+{
+ return (Datum) X;
+}
+
+/*
+ * DatumGetPointer
+ * Returns pointer value of a datum.
+ */
+static inline Pointer
+DatumGetPointer(Datum X)
+{
+ return (Pointer) X;
+}
+
+/*
+ * PointerGetDatum
+ * Returns datum representation for a pointer.
+ */
+static inline Datum
+PointerGetDatum(const void *X)
+{
+ return (Datum) X;
+}
+
+/*
+ * DatumGetCString
+ * Returns C string (null-terminated string) value of a datum.
+ *
+ * Note: C string is not a full-fledged Postgres type at present,
+ * but type input functions use this conversion for their inputs.
+ */
+static inline char *
+DatumGetCString(Datum X)
+{
+ return (char *) DatumGetPointer(X);
+}
+
+/*
+ * CStringGetDatum
+ * Returns datum representation for a C string (null-terminated string).
+ *
+ * Note: C string is not a full-fledged Postgres type at present,
+ * but type output functions use this conversion for their outputs.
+ * Note: CString is pass-by-reference; caller must ensure the pointed-to
+ * value has adequate lifetime.
+ */
+static inline Datum
+CStringGetDatum(const char *X)
+{
+ return PointerGetDatum(X);
+}
+
+/*
+ * DatumGetName
+ * Returns name value of a datum.
+ */
+static inline Name
+DatumGetName(Datum X)
+{
+ return (Name) DatumGetPointer(X);
+}
+
+/*
+ * NameGetDatum
+ * Returns datum representation for a name.
+ *
+ * Note: Name is pass-by-reference; caller must ensure the pointed-to
+ * value has adequate lifetime.
+ */
+static inline Datum
+NameGetDatum(const NameData *X)
+{
+ return CStringGetDatum(NameStr(*X));
+}
+
+/*
+ * DatumGetInt64
+ * Returns 64-bit integer value of a datum.
+ *
+ * Note: this function hides whether int64 is pass by value or by reference.
+ */
+static inline int64
+DatumGetInt64(Datum X)
+{
+#ifdef USE_FLOAT8_BYVAL
+ return (int64) X;
+#else
+ return *((int64 *) DatumGetPointer(X));
+#endif
+}
+
+/*
+ * Int64GetDatum
+ * Returns datum representation for a 64-bit integer.
+ *
+ * Note: if int64 is pass by reference, this function returns a reference
+ * to palloc'd space.
+ */
+#ifdef USE_FLOAT8_BYVAL
+static inline Datum
+Int64GetDatum(int64 X)
+{
+ return (Datum) X;
+}
+#else
+extern Datum Int64GetDatum(int64 X);
+#endif
+
+
+/*
+ * DatumGetUInt64
+ * Returns 64-bit unsigned integer value of a datum.
+ *
+ * Note: this function hides whether int64 is pass by value or by reference.
+ */
+static inline uint64
+DatumGetUInt64(Datum X)
+{
+#ifdef USE_FLOAT8_BYVAL
+ return (uint64) X;
+#else
+ return *((uint64 *) DatumGetPointer(X));
+#endif
+}
+
+/*
+ * UInt64GetDatum
+ * Returns datum representation for a 64-bit unsigned integer.
+ *
+ * Note: if int64 is pass by reference, this function returns a reference
+ * to palloc'd space.
+ */
+static inline Datum
+UInt64GetDatum(uint64 X)
+{
+#ifdef USE_FLOAT8_BYVAL
+ return (Datum) X;
+#else
+ return Int64GetDatum((int64) X);
+#endif
+}
+
+/*
+ * Float <-> Datum conversions
+ *
+ * These have to be implemented as inline functions rather than macros, when
+ * passing by value, because many machines pass int and float function
+ * parameters/results differently; so we need to play weird games with unions.
+ */
+
+/*
+ * DatumGetFloat4
+ * Returns 4-byte floating point value of a datum.
+ */
+static inline float4
+DatumGetFloat4(Datum X)
+{
+ union
+ {
+ int32 value;
+ float4 retval;
+ } myunion;
+
+ myunion.value = DatumGetInt32(X);
+ return myunion.retval;
+}
+
+/*
+ * Float4GetDatum
+ * Returns datum representation for a 4-byte floating point number.
+ */
+static inline Datum
+Float4GetDatum(float4 X)
+{
+ union
+ {
+ float4 value;
+ int32 retval;
+ } myunion;
+
+ myunion.value = X;
+ return Int32GetDatum(myunion.retval);
+}
+
+/*
+ * DatumGetFloat8
+ * Returns 8-byte floating point value of a datum.
+ *
+ * Note: this function hides whether float8 is pass by value or by reference.
+ */
+static inline float8
+DatumGetFloat8(Datum X)
+{
+#ifdef USE_FLOAT8_BYVAL
+ union
+ {
+ int64 value;
+ float8 retval;
+ } myunion;
+
+ myunion.value = DatumGetInt64(X);
+ return myunion.retval;
+#else
+ return *((float8 *) DatumGetPointer(X));
+#endif
+}
+
+/*
+ * Float8GetDatum
+ * Returns datum representation for an 8-byte floating point number.
+ *
+ * Note: if float8 is pass by reference, this function returns a reference
+ * to palloc'd space.
+ */
+#ifdef USE_FLOAT8_BYVAL
+static inline Datum
+Float8GetDatum(float8 X)
+{
+ union
+ {
+ float8 value;
+ int64 retval;
+ } myunion;
+
+ myunion.value = X;
+ return Int64GetDatum(myunion.retval);
+}
+#else
+extern Datum Float8GetDatum(float8 X);
+#endif
+
+
+/*
+ * Int64GetDatumFast
+ * Float8GetDatumFast
+ *
+ * These macros are intended to allow writing code that does not depend on
+ * whether int64 and float8 are pass-by-reference types, while not
+ * sacrificing performance when they are. The argument must be a variable
+ * that will exist and have the same value for as long as the Datum is needed.
+ * In the pass-by-ref case, the address of the variable is taken to use as
+ * the Datum. In the pass-by-val case, these are the same as the non-Fast
+ * functions, except for asserting that the variable is of the correct type.
+ */
+
+#ifdef USE_FLOAT8_BYVAL
+#define Int64GetDatumFast(X) \
+ (AssertVariableIsOfTypeMacro(X, int64), Int64GetDatum(X))
+#define Float8GetDatumFast(X) \
+ (AssertVariableIsOfTypeMacro(X, double), Float8GetDatum(X))
+#else
+#define Int64GetDatumFast(X) \
+ (AssertVariableIsOfTypeMacro(X, int64), PointerGetDatum(&(X)))
+#define Float8GetDatumFast(X) \
+ (AssertVariableIsOfTypeMacro(X, double), PointerGetDatum(&(X)))
+#endif
+
+
+/* ----------------------------------------------------------------
+ * Section 2: miscellaneous
+ * ----------------------------------------------------------------
+ */
+
+/*
+ * NON_EXEC_STATIC: It's sometimes useful to define a variable or function
+ * that is normally static but extern when using EXEC_BACKEND (see
+ * pg_config_manual.h). There would then typically be some code in
+ * postmaster.c that uses those extern symbols to transfer state between
+ * processes or do whatever other things it needs to do in EXEC_BACKEND mode.
+ */
+#ifdef EXEC_BACKEND
+#define NON_EXEC_STATIC
+#else
+#define NON_EXEC_STATIC static
+#endif
+
+#endif /* POSTGRES_H */
diff --git a/contrib/libs/libpq/src/include/postgres_ext.h b/contrib/libs/libpq/src/include/postgres_ext.h
new file mode 100644
index 0000000000..240ad4e93b
--- /dev/null
+++ b/contrib/libs/libpq/src/include/postgres_ext.h
@@ -0,0 +1,73 @@
+/*-------------------------------------------------------------------------
+ *
+ * postgres_ext.h
+ *
+ * This file contains declarations of things that are visible everywhere
+ * in PostgreSQL *and* are visible to clients of frontend interface libraries.
+ * For example, the Oid type is part of the API of libpq and other libraries.
+ *
+ * Declarations which are specific to a particular interface should
+ * go in the header file for that interface (such as libpq-fe.h). This
+ * file is only for fundamental Postgres declarations.
+ *
+ * User-written C functions don't count as "external to Postgres."
+ * Those function much as local modifications to the backend itself, and
+ * use header files that are otherwise internal to Postgres to interface
+ * with the backend.
+ *
+ * src/include/postgres_ext.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef POSTGRES_EXT_H
+#define POSTGRES_EXT_H
+
+#include "pg_config_ext.h"
+
+/*
+ * Object ID is a fundamental type in Postgres.
+ */
+typedef unsigned int Oid;
+
+#ifdef __cplusplus
+#define InvalidOid (Oid(0))
+#else
+#define InvalidOid ((Oid) 0)
+#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. */
+typedef PG_INT64_TYPE pg_int64;
+
+/*
+ * Identifiers of error message fields. Kept here to keep common
+ * between frontend and backend, and also to export them to libpq
+ * applications.
+ */
+#define PG_DIAG_SEVERITY 'S'
+#define PG_DIAG_SEVERITY_NONLOCALIZED 'V'
+#define PG_DIAG_SQLSTATE 'C'
+#define PG_DIAG_MESSAGE_PRIMARY 'M'
+#define PG_DIAG_MESSAGE_DETAIL 'D'
+#define PG_DIAG_MESSAGE_HINT 'H'
+#define PG_DIAG_STATEMENT_POSITION 'P'
+#define PG_DIAG_INTERNAL_POSITION 'p'
+#define PG_DIAG_INTERNAL_QUERY 'q'
+#define PG_DIAG_CONTEXT 'W'
+#define PG_DIAG_SCHEMA_NAME 's'
+#define PG_DIAG_TABLE_NAME 't'
+#define PG_DIAG_COLUMN_NAME 'c'
+#define PG_DIAG_DATATYPE_NAME 'd'
+#define PG_DIAG_CONSTRAINT_NAME 'n'
+#define PG_DIAG_SOURCE_FILE 'F'
+#define PG_DIAG_SOURCE_LINE 'L'
+#define PG_DIAG_SOURCE_FUNCTION 'R'
+
+#endif /* POSTGRES_EXT_H */
diff --git a/contrib/libs/libpq/src/include/postgres_fe.h b/contrib/libs/libpq/src/include/postgres_fe.h
new file mode 100644
index 0000000000..5bc71dd0b3
--- /dev/null
+++ b/contrib/libs/libpq/src/include/postgres_fe.h
@@ -0,0 +1,29 @@
+/*-------------------------------------------------------------------------
+ *
+ * postgres_fe.h
+ * Primary include file for PostgreSQL client-side .c files
+ *
+ * This should be the first file included by PostgreSQL client libraries and
+ * application programs --- but not by backend modules, which should include
+ * postgres.h.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1995, Regents of the University of California
+ *
+ * src/include/postgres_fe.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef POSTGRES_FE_H
+#define POSTGRES_FE_H
+
+#ifndef FRONTEND
+#define FRONTEND 1
+#endif
+
+#include "c.h"
+
+#include "common/fe_memutils.h"
+
+#endif /* POSTGRES_FE_H */
diff --git a/contrib/libs/libpq/src/include/storage/backendid.h b/contrib/libs/libpq/src/include/storage/backendid.h
new file mode 100644
index 0000000000..1e90b602f0
--- /dev/null
+++ b/contrib/libs/libpq/src/include/storage/backendid.h
@@ -0,0 +1,37 @@
+/*-------------------------------------------------------------------------
+ *
+ * backendid.h
+ * POSTGRES backend id communication definitions
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/backendid.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef BACKENDID_H
+#define BACKENDID_H
+
+/* ----------------
+ * -cim 8/17/90
+ * ----------------
+ */
+typedef int BackendId; /* unique currently active backend identifier */
+
+#define InvalidBackendId (-1)
+
+extern PGDLLIMPORT BackendId MyBackendId; /* backend id of this backend */
+
+/* backend id of our parallel session leader, or InvalidBackendId if none */
+extern PGDLLIMPORT BackendId ParallelLeaderBackendId;
+
+/*
+ * The BackendId to use for our session's temp relations is normally our own,
+ * but parallel workers should use their leader's ID.
+ */
+#define BackendIdForTempRelations() \
+ (ParallelLeaderBackendId == InvalidBackendId ? MyBackendId : ParallelLeaderBackendId)
+
+#endif /* BACKENDID_H */
diff --git a/contrib/libs/libpq/src/include/storage/block.h b/contrib/libs/libpq/src/include/storage/block.h
new file mode 100644
index 0000000000..31a036df0d
--- /dev/null
+++ b/contrib/libs/libpq/src/include/storage/block.h
@@ -0,0 +1,108 @@
+/*-------------------------------------------------------------------------
+ *
+ * block.h
+ * POSTGRES disk block definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/block.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef BLOCK_H
+#define BLOCK_H
+
+/*
+ * BlockNumber:
+ *
+ * each data file (heap or index) is divided into postgres disk blocks
+ * (which may be thought of as the unit of i/o -- a postgres buffer
+ * contains exactly one disk block). the blocks are numbered
+ * sequentially, 0 to 0xFFFFFFFE.
+ *
+ * InvalidBlockNumber is the same thing as P_NEW in bufmgr.h.
+ *
+ * the access methods, the buffer manager and the storage manager are
+ * more or less the only pieces of code that should be accessing disk
+ * blocks directly.
+ */
+typedef uint32 BlockNumber;
+
+#define InvalidBlockNumber ((BlockNumber) 0xFFFFFFFF)
+
+#define MaxBlockNumber ((BlockNumber) 0xFFFFFFFE)
+
+/*
+ * BlockId:
+ *
+ * this is a storage type for BlockNumber. in other words, this type
+ * is used for on-disk structures (e.g., in HeapTupleData) whereas
+ * BlockNumber is the type on which calculations are performed (e.g.,
+ * in access method code).
+ *
+ * there doesn't appear to be any reason to have separate types except
+ * for the fact that BlockIds can be SHORTALIGN'd (and therefore any
+ * structures that contains them, such as ItemPointerData, can also be
+ * SHORTALIGN'd). this is an important consideration for reducing the
+ * space requirements of the line pointer (ItemIdData) array on each
+ * page and the header of each heap or index tuple, so it doesn't seem
+ * wise to change this without good reason.
+ */
+typedef struct BlockIdData
+{
+ uint16 bi_hi;
+ uint16 bi_lo;
+} BlockIdData;
+
+typedef BlockIdData *BlockId; /* block identifier */
+
+/* ----------------
+ * support functions
+ * ----------------
+ */
+
+/*
+ * BlockNumberIsValid
+ * True iff blockNumber is valid.
+ */
+static inline bool
+BlockNumberIsValid(BlockNumber blockNumber)
+{
+ return blockNumber != InvalidBlockNumber;
+}
+
+/*
+ * BlockIdSet
+ * Sets a block identifier to the specified value.
+ */
+static inline void
+BlockIdSet(BlockIdData *blockId, BlockNumber blockNumber)
+{
+ blockId->bi_hi = blockNumber >> 16;
+ blockId->bi_lo = blockNumber & 0xffff;
+}
+
+/*
+ * BlockIdEquals
+ * Check for block number equality.
+ */
+static inline bool
+BlockIdEquals(const BlockIdData *blockId1, const BlockIdData *blockId2)
+{
+ return (blockId1->bi_hi == blockId2->bi_hi &&
+ blockId1->bi_lo == blockId2->bi_lo);
+}
+
+/*
+ * BlockIdGetBlockNumber
+ * Retrieve the block number from a block identifier.
+ */
+static inline BlockNumber
+BlockIdGetBlockNumber(const BlockIdData *blockId)
+{
+ return (((BlockNumber) blockId->bi_hi) << 16) | ((BlockNumber) blockId->bi_lo);
+}
+
+#endif /* BLOCK_H */
diff --git a/contrib/libs/libpq/src/include/storage/buf.h b/contrib/libs/libpq/src/include/storage/buf.h
new file mode 100644
index 0000000000..6520d9ae1e
--- /dev/null
+++ b/contrib/libs/libpq/src/include/storage/buf.h
@@ -0,0 +1,46 @@
+/*-------------------------------------------------------------------------
+ *
+ * buf.h
+ * Basic buffer manager data types.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/buf.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef BUF_H
+#define BUF_H
+
+/*
+ * Buffer identifiers.
+ *
+ * Zero is invalid, positive is the index of a shared buffer (1..NBuffers),
+ * negative is the index of a local buffer (-1 .. -NLocBuffer).
+ */
+typedef int Buffer;
+
+#define InvalidBuffer 0
+
+/*
+ * BufferIsInvalid
+ * True iff the buffer is invalid.
+ */
+#define BufferIsInvalid(buffer) ((buffer) == InvalidBuffer)
+
+/*
+ * BufferIsLocal
+ * True iff the buffer is local (not visible to other backends).
+ */
+#define BufferIsLocal(buffer) ((buffer) < 0)
+
+/*
+ * Buffer access strategy objects.
+ *
+ * BufferAccessStrategyData is private to freelist.c
+ */
+typedef struct BufferAccessStrategyData *BufferAccessStrategy;
+
+#endif /* BUF_H */
diff --git a/contrib/libs/libpq/src/include/storage/relfilelocator.h b/contrib/libs/libpq/src/include/storage/relfilelocator.h
new file mode 100644
index 0000000000..61cf0169bd
--- /dev/null
+++ b/contrib/libs/libpq/src/include/storage/relfilelocator.h
@@ -0,0 +1,99 @@
+/*-------------------------------------------------------------------------
+ *
+ * relfilelocator.h
+ * Physical access information for relations.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/relfilelocator.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef RELFILELOCATOR_H
+#define RELFILELOCATOR_H
+
+#include "common/relpath.h"
+#include "storage/backendid.h"
+
+/*
+ * RelFileLocator must provide all that we need to know to physically access
+ * a relation, with the exception of the backend ID, which can be provided
+ * separately. Note, however, that a "physical" relation is comprised of
+ * multiple files on the filesystem, as each fork is stored as a separate
+ * file, and each fork can be divided into multiple segments. See md.c.
+ *
+ * spcOid identifies the tablespace of the relation. It corresponds to
+ * pg_tablespace.oid.
+ *
+ * dbOid identifies the database of the relation. It is zero for
+ * "shared" relations (those common to all databases of a cluster).
+ * Nonzero dbOid values correspond to pg_database.oid.
+ *
+ * relNumber identifies the specific relation. relNumber corresponds to
+ * pg_class.relfilenode (NOT pg_class.oid, because we need to be able
+ * to assign new physical files to relations in some situations).
+ * Notice that relNumber is only unique within a database in a particular
+ * tablespace.
+ *
+ * Note: spcOid must be GLOBALTABLESPACE_OID if and only if dbOid is
+ * zero. We support shared relations only in the "global" tablespace.
+ *
+ * Note: in pg_class we allow reltablespace == 0 to denote that the
+ * relation is stored in its database's "default" tablespace (as
+ * identified by pg_database.dattablespace). However this shorthand
+ * is NOT allowed in RelFileLocator structs --- the real tablespace ID
+ * must be supplied when setting spcOid.
+ *
+ * Note: in pg_class, relfilenode can be zero to denote that the relation
+ * is a "mapped" relation, whose current true filenode number is available
+ * from relmapper.c. Again, this case is NOT allowed in RelFileLocators.
+ *
+ * Note: various places use RelFileLocator in hashtable keys. Therefore,
+ * there *must not* be any unused padding bytes in this struct. That
+ * should be safe as long as all the fields are of type Oid.
+ */
+typedef struct RelFileLocator
+{
+ Oid spcOid; /* tablespace */
+ Oid dbOid; /* database */
+ RelFileNumber relNumber; /* relation */
+} RelFileLocator;
+
+/*
+ * Augmenting a relfilelocator with the backend ID provides all the information
+ * we need to locate the physical storage. The backend ID is InvalidBackendId
+ * for regular relations (those accessible to more than one backend), or the
+ * owning backend's ID for backend-local relations. Backend-local relations
+ * are always transient and removed in case of a database crash; they are
+ * never WAL-logged or fsync'd.
+ */
+typedef struct RelFileLocatorBackend
+{
+ RelFileLocator locator;
+ BackendId backend;
+} RelFileLocatorBackend;
+
+#define RelFileLocatorBackendIsTemp(rlocator) \
+ ((rlocator).backend != InvalidBackendId)
+
+/*
+ * Note: RelFileLocatorEquals and RelFileLocatorBackendEquals compare relNumber
+ * first since that is most likely to be different in two unequal
+ * RelFileLocators. It is probably redundant to compare spcOid if the other
+ * fields are found equal, but do it anyway to be sure. Likewise for checking
+ * the backend ID in RelFileLocatorBackendEquals.
+ */
+#define RelFileLocatorEquals(locator1, locator2) \
+ ((locator1).relNumber == (locator2).relNumber && \
+ (locator1).dbOid == (locator2).dbOid && \
+ (locator1).spcOid == (locator2).spcOid)
+
+#define RelFileLocatorBackendEquals(locator1, locator2) \
+ ((locator1).locator.relNumber == (locator2).locator.relNumber && \
+ (locator1).locator.dbOid == (locator2).locator.dbOid && \
+ (locator1).backend == (locator2).backend && \
+ (locator1).locator.spcOid == (locator2).locator.spcOid)
+
+#endif /* RELFILELOCATOR_H */
diff --git a/contrib/libs/libpq/src/include/utils/elog.h b/contrib/libs/libpq/src/include/utils/elog.h
new file mode 100644
index 0000000000..0292e88b4f
--- /dev/null
+++ b/contrib/libs/libpq/src/include/utils/elog.h
@@ -0,0 +1,545 @@
+/*-------------------------------------------------------------------------
+ *
+ * elog.h
+ * POSTGRES error reporting/logging definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/elog.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef ELOG_H
+#define ELOG_H
+
+#include <setjmp.h>
+
+#include "lib/stringinfo.h"
+
+/* We cannot include nodes.h yet, so forward-declare struct Node */
+struct Node;
+
+
+/* Error level codes */
+#define DEBUG5 10 /* Debugging messages, in categories of
+ * decreasing detail. */
+#define DEBUG4 11
+#define DEBUG3 12
+#define DEBUG2 13
+#define DEBUG1 14 /* used by GUC debug_* variables */
+#define LOG 15 /* Server operational messages; sent only to
+ * server log by default. */
+#define LOG_SERVER_ONLY 16 /* Same as LOG for server reporting, but never
+ * sent to client. */
+#define COMMERROR LOG_SERVER_ONLY /* Client communication problems; same as
+ * LOG for server reporting, but never
+ * sent to client. */
+#define INFO 17 /* Messages specifically requested by user (eg
+ * VACUUM VERBOSE output); always sent to
+ * client regardless of client_min_messages,
+ * but by default not sent to server log. */
+#define NOTICE 18 /* Helpful messages to users about query
+ * operation; sent to client and not to server
+ * log by default. */
+#define WARNING 19 /* Warnings. NOTICE is for expected messages
+ * like implicit sequence creation by SERIAL.
+ * WARNING is for unexpected messages. */
+#define PGWARNING 19 /* Must equal WARNING; see NOTE below. */
+#define WARNING_CLIENT_ONLY 20 /* Warnings to be sent to client as usual, but
+ * never to the server log. */
+#define ERROR 21 /* user error - abort transaction; return to
+ * known state */
+#define PGERROR 21 /* Must equal ERROR; see NOTE below. */
+#define FATAL 22 /* fatal error - abort process */
+#define PANIC 23 /* take down the other backends with me */
+
+/*
+ * NOTE: the alternate names PGWARNING and PGERROR are useful for dealing
+ * with third-party headers that make other definitions of WARNING and/or
+ * ERROR. One can, for example, re-define ERROR as PGERROR after including
+ * such a header.
+ */
+
+
+/* macros for representing SQLSTATE strings compactly */
+#define PGSIXBIT(ch) (((ch) - '0') & 0x3F)
+#define PGUNSIXBIT(val) (((val) & 0x3F) + '0')
+
+#define MAKE_SQLSTATE(ch1,ch2,ch3,ch4,ch5) \
+ (PGSIXBIT(ch1) + (PGSIXBIT(ch2) << 6) + (PGSIXBIT(ch3) << 12) + \
+ (PGSIXBIT(ch4) << 18) + (PGSIXBIT(ch5) << 24))
+
+/* These macros depend on the fact that '0' becomes a zero in PGSIXBIT */
+#define ERRCODE_TO_CATEGORY(ec) ((ec) & ((1 << 12) - 1))
+#define ERRCODE_IS_CATEGORY(ec) (((ec) & ~((1 << 12) - 1)) == 0)
+
+/* SQLSTATE codes for errors are defined in a separate file */
+#include "utils/errcodes.h"
+
+/*
+ * Provide a way to prevent "errno" from being accidentally used inside an
+ * elog() or ereport() invocation. Since we know that some operating systems
+ * define errno as something involving a function call, we'll put a local
+ * variable of the same name as that function in the local scope to force a
+ * compile error. On platforms that don't define errno in that way, nothing
+ * happens, so we get no warning ... but we can live with that as long as it
+ * happens on some popular platforms.
+ */
+#if defined(errno) && defined(__linux__)
+#define pg_prevent_errno_in_scope() int __errno_location pg_attribute_unused()
+#elif defined(errno) && (defined(__darwin__) || defined(__FreeBSD__))
+#define pg_prevent_errno_in_scope() int __error pg_attribute_unused()
+#else
+#define pg_prevent_errno_in_scope()
+#endif
+
+
+/*----------
+ * New-style error reporting API: to be used in this way:
+ * ereport(ERROR,
+ * errcode(ERRCODE_UNDEFINED_CURSOR),
+ * errmsg("portal \"%s\" not found", stmt->portalname),
+ * ... other errxxx() fields as needed ...);
+ *
+ * The error level is required, and so is a primary error message (errmsg
+ * or errmsg_internal). All else is optional. errcode() defaults to
+ * ERRCODE_INTERNAL_ERROR if elevel is ERROR or more, ERRCODE_WARNING
+ * if elevel is WARNING, or ERRCODE_SUCCESSFUL_COMPLETION if elevel is
+ * NOTICE or below.
+ *
+ * Before Postgres v12, extra parentheses were required around the
+ * list of auxiliary function calls; that's now optional.
+ *
+ * ereport_domain() allows a message domain to be specified, for modules that
+ * wish to use a different message catalog from the backend's. To avoid having
+ * one copy of the default text domain per .o file, we define it as NULL here
+ * and have errstart insert the default text domain. Modules can either use
+ * ereport_domain() directly, or preferably they can override the TEXTDOMAIN
+ * macro.
+ *
+ * When __builtin_constant_p is available and elevel >= ERROR we make a call
+ * to errstart_cold() instead of errstart(). This version of the function is
+ * marked with pg_attribute_cold which will coax supporting compilers into
+ * generating code which is more optimized towards non-ERROR cases. Because
+ * we use __builtin_constant_p() in the condition, when elevel is not a
+ * compile-time constant, or if it is, but it's < ERROR, the compiler has no
+ * need to generate any code for this branch. It can simply call errstart()
+ * unconditionally.
+ *
+ * If elevel >= ERROR, the call will not return; we try to inform the compiler
+ * of that via pg_unreachable(). However, no useful optimization effect is
+ * obtained unless the compiler sees elevel as a compile-time constant, else
+ * we're just adding code bloat. So, if __builtin_constant_p is available,
+ * use that to cause the second if() to vanish completely for non-constant
+ * cases. We avoid using a local variable because it's not necessary and
+ * prevents gcc from making the unreachability deduction at optlevel -O0.
+ *----------
+ */
+#ifdef HAVE__BUILTIN_CONSTANT_P
+#define ereport_domain(elevel, domain, ...) \
+ do { \
+ pg_prevent_errno_in_scope(); \
+ if (__builtin_constant_p(elevel) && (elevel) >= ERROR ? \
+ errstart_cold(elevel, domain) : \
+ errstart(elevel, domain)) \
+ __VA_ARGS__, errfinish(__FILE__, __LINE__, __func__); \
+ if (__builtin_constant_p(elevel) && (elevel) >= ERROR) \
+ pg_unreachable(); \
+ } while(0)
+#else /* !HAVE__BUILTIN_CONSTANT_P */
+#define ereport_domain(elevel, domain, ...) \
+ do { \
+ const int elevel_ = (elevel); \
+ pg_prevent_errno_in_scope(); \
+ if (errstart(elevel_, domain)) \
+ __VA_ARGS__, errfinish(__FILE__, __LINE__, __func__); \
+ if (elevel_ >= ERROR) \
+ pg_unreachable(); \
+ } while(0)
+#endif /* HAVE__BUILTIN_CONSTANT_P */
+
+#define ereport(elevel, ...) \
+ ereport_domain(elevel, TEXTDOMAIN, __VA_ARGS__)
+
+#define TEXTDOMAIN NULL
+
+extern bool message_level_is_interesting(int elevel);
+
+extern bool errstart(int elevel, const char *domain);
+extern pg_attribute_cold bool errstart_cold(int elevel, const char *domain);
+extern void errfinish(const char *filename, int lineno, const char *funcname);
+
+extern int errcode(int sqlerrcode);
+
+extern int errcode_for_file_access(void);
+extern int errcode_for_socket_access(void);
+
+extern int errmsg(const char *fmt,...) pg_attribute_printf(1, 2);
+extern int errmsg_internal(const char *fmt,...) pg_attribute_printf(1, 2);
+
+extern int errmsg_plural(const char *fmt_singular, const char *fmt_plural,
+ unsigned long n,...) pg_attribute_printf(1, 4) pg_attribute_printf(2, 4);
+
+extern int errdetail(const char *fmt,...) pg_attribute_printf(1, 2);
+extern int errdetail_internal(const char *fmt,...) pg_attribute_printf(1, 2);
+
+extern int errdetail_log(const char *fmt,...) pg_attribute_printf(1, 2);
+
+extern int errdetail_log_plural(const char *fmt_singular,
+ const char *fmt_plural,
+ unsigned long n,...) pg_attribute_printf(1, 4) pg_attribute_printf(2, 4);
+
+extern int errdetail_plural(const char *fmt_singular, const char *fmt_plural,
+ unsigned long n,...) pg_attribute_printf(1, 4) pg_attribute_printf(2, 4);
+
+extern int errhint(const char *fmt,...) pg_attribute_printf(1, 2);
+
+extern int errhint_plural(const char *fmt_singular, const char *fmt_plural,
+ unsigned long n,...) pg_attribute_printf(1, 4) pg_attribute_printf(2, 4);
+
+/*
+ * errcontext() is typically called in error context callback functions, not
+ * within an ereport() invocation. The callback function can be in a different
+ * module than the ereport() call, so the message domain passed in errstart()
+ * is not usually the correct domain for translating the context message.
+ * set_errcontext_domain() first sets the domain to be used, and
+ * errcontext_msg() passes the actual message.
+ */
+#define errcontext set_errcontext_domain(TEXTDOMAIN), errcontext_msg
+
+extern int set_errcontext_domain(const char *domain);
+
+extern int errcontext_msg(const char *fmt,...) pg_attribute_printf(1, 2);
+
+extern int errhidestmt(bool hide_stmt);
+extern int errhidecontext(bool hide_ctx);
+
+extern int errbacktrace(void);
+
+extern int errposition(int cursorpos);
+
+extern int internalerrposition(int cursorpos);
+extern int internalerrquery(const char *query);
+
+extern int err_generic_string(int field, const char *str);
+
+extern int geterrcode(void);
+extern int geterrposition(void);
+extern int getinternalerrposition(void);
+
+
+/*----------
+ * Old-style error reporting API: to be used in this way:
+ * elog(ERROR, "portal \"%s\" not found", stmt->portalname);
+ *----------
+ */
+#define elog(elevel, ...) \
+ ereport(elevel, errmsg_internal(__VA_ARGS__))
+
+
+/*----------
+ * Support for reporting "soft" errors that don't require a full transaction
+ * abort to clean up. This is to be used in this way:
+ * errsave(context,
+ * errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+ * errmsg("invalid input syntax for type %s: \"%s\"",
+ * "boolean", in_str),
+ * ... other errxxx() fields as needed ...);
+ *
+ * "context" is a node pointer or NULL, and the remaining auxiliary calls
+ * provide the same error details as in ereport(). If context is not a
+ * pointer to an ErrorSaveContext node, then errsave(context, ...)
+ * behaves identically to ereport(ERROR, ...). If context is a pointer
+ * to an ErrorSaveContext node, then the information provided by the
+ * auxiliary calls is stored in the context node and control returns
+ * normally. The caller of errsave() must then do any required cleanup
+ * and return control back to its caller. That caller must check the
+ * ErrorSaveContext node to see whether an error occurred before
+ * it can trust the function's result to be meaningful.
+ *
+ * errsave_domain() allows a message domain to be specified; it is
+ * precisely analogous to ereport_domain().
+ *----------
+ */
+#define errsave_domain(context, domain, ...) \
+ do { \
+ struct Node *context_ = (context); \
+ pg_prevent_errno_in_scope(); \
+ if (errsave_start(context_, domain)) \
+ __VA_ARGS__, errsave_finish(context_, __FILE__, __LINE__, __func__); \
+ } while(0)
+
+#define errsave(context, ...) \
+ errsave_domain(context, TEXTDOMAIN, __VA_ARGS__)
+
+/*
+ * "ereturn(context, dummy_value, ...);" is exactly the same as
+ * "errsave(context, ...); return dummy_value;". This saves a bit
+ * of typing in the common case where a function has no cleanup
+ * actions to take after reporting a soft error. "dummy_value"
+ * can be empty if the function returns void.
+ */
+#define ereturn_domain(context, dummy_value, domain, ...) \
+ do { \
+ errsave_domain(context, domain, __VA_ARGS__); \
+ return dummy_value; \
+ } while(0)
+
+#define ereturn(context, dummy_value, ...) \
+ ereturn_domain(context, dummy_value, TEXTDOMAIN, __VA_ARGS__)
+
+extern bool errsave_start(struct Node *context, const char *domain);
+extern void errsave_finish(struct Node *context,
+ const char *filename, int lineno,
+ const char *funcname);
+
+
+/* Support for constructing error strings separately from ereport() calls */
+
+extern void pre_format_elog_string(int errnumber, const char *domain);
+extern char *format_elog_string(const char *fmt,...) pg_attribute_printf(1, 2);
+
+
+/* Support for attaching context information to error reports */
+
+typedef struct ErrorContextCallback
+{
+ struct ErrorContextCallback *previous;
+ void (*callback) (void *arg);
+ void *arg;
+} ErrorContextCallback;
+
+extern PGDLLIMPORT ErrorContextCallback *error_context_stack;
+
+
+/*----------
+ * API for catching ereport(ERROR) exits. Use these macros like so:
+ *
+ * PG_TRY();
+ * {
+ * ... code that might throw ereport(ERROR) ...
+ * }
+ * PG_CATCH();
+ * {
+ * ... error recovery code ...
+ * }
+ * PG_END_TRY();
+ *
+ * (The braces are not actually necessary, but are recommended so that
+ * pgindent will indent the construct nicely.) The error recovery code
+ * can either do PG_RE_THROW to propagate the error outwards, or do a
+ * (sub)transaction abort. Failure to do so may leave the system in an
+ * inconsistent state for further processing.
+ *
+ * For the common case that the error recovery code and the cleanup in the
+ * normal code path are identical, the following can be used instead:
+ *
+ * PG_TRY();
+ * {
+ * ... code that might throw ereport(ERROR) ...
+ * }
+ * PG_FINALLY();
+ * {
+ * ... cleanup code ...
+ * }
+ * PG_END_TRY();
+ *
+ * The cleanup code will be run in either case, and any error will be rethrown
+ * afterwards.
+ *
+ * You cannot use both PG_CATCH() and PG_FINALLY() in the same
+ * PG_TRY()/PG_END_TRY() block.
+ *
+ * Note: while the system will correctly propagate any new ereport(ERROR)
+ * occurring in the recovery section, there is a small limit on the number
+ * of levels this will work for. It's best to keep the error recovery
+ * section simple enough that it can't generate any new errors, at least
+ * not before popping the error stack.
+ *
+ * Note: an ereport(FATAL) will not be caught by this construct; control will
+ * exit straight through proc_exit(). Therefore, do NOT put any cleanup
+ * of non-process-local resources into the error recovery section, at least
+ * not without taking thought for what will happen during ereport(FATAL).
+ * The PG_ENSURE_ERROR_CLEANUP macros provided by storage/ipc.h may be
+ * helpful in such cases.
+ *
+ * Note: if a local variable of the function containing PG_TRY is modified
+ * in the PG_TRY section and used in the PG_CATCH section, that variable
+ * must be declared "volatile" for POSIX compliance. This is not mere
+ * pedantry; we have seen bugs from compilers improperly optimizing code
+ * away when such a variable was not marked. Beware that gcc's -Wclobbered
+ * warnings are just about entirely useless for catching such oversights.
+ *
+ * Each of these macros accepts an optional argument which can be specified
+ * to apply a suffix to the variables declared within the macros. This suffix
+ * can be used to avoid the compiler emitting warnings about shadowed
+ * variables when compiling with -Wshadow in situations where nested PG_TRY()
+ * statements are required. The optional suffix may contain any character
+ * that's allowed in a variable name. The suffix, if specified, must be the
+ * same within each component macro of the given PG_TRY() statement.
+ *----------
+ */
+#define PG_TRY(...) \
+ do { \
+ sigjmp_buf *_save_exception_stack##__VA_ARGS__ = PG_exception_stack; \
+ ErrorContextCallback *_save_context_stack##__VA_ARGS__ = error_context_stack; \
+ sigjmp_buf _local_sigjmp_buf##__VA_ARGS__; \
+ bool _do_rethrow##__VA_ARGS__ = false; \
+ if (sigsetjmp(_local_sigjmp_buf##__VA_ARGS__, 0) == 0) \
+ { \
+ PG_exception_stack = &_local_sigjmp_buf##__VA_ARGS__
+
+#define PG_CATCH(...) \
+ } \
+ else \
+ { \
+ PG_exception_stack = _save_exception_stack##__VA_ARGS__; \
+ error_context_stack = _save_context_stack##__VA_ARGS__
+
+#define PG_FINALLY(...) \
+ } \
+ else \
+ _do_rethrow##__VA_ARGS__ = true; \
+ { \
+ PG_exception_stack = _save_exception_stack##__VA_ARGS__; \
+ error_context_stack = _save_context_stack##__VA_ARGS__
+
+#define PG_END_TRY(...) \
+ } \
+ if (_do_rethrow##__VA_ARGS__) \
+ PG_RE_THROW(); \
+ PG_exception_stack = _save_exception_stack##__VA_ARGS__; \
+ error_context_stack = _save_context_stack##__VA_ARGS__; \
+ } while (0)
+
+/*
+ * Some compilers understand pg_attribute_noreturn(); for other compilers,
+ * insert pg_unreachable() so that the compiler gets the point.
+ */
+#ifdef HAVE_PG_ATTRIBUTE_NORETURN
+#define PG_RE_THROW() \
+ pg_re_throw()
+#else
+#define PG_RE_THROW() \
+ (pg_re_throw(), pg_unreachable())
+#endif
+
+extern PGDLLIMPORT sigjmp_buf *PG_exception_stack;
+
+
+/* Stuff that error handlers might want to use */
+
+/*
+ * ErrorData holds the data accumulated during any one ereport() cycle.
+ * Any non-NULL pointers must point to palloc'd data.
+ * (The const pointers are an exception; we assume they point at non-freeable
+ * constant strings.)
+ */
+typedef struct ErrorData
+{
+ int elevel; /* error level */
+ bool output_to_server; /* will report to server log? */
+ bool output_to_client; /* will report to client? */
+ bool hide_stmt; /* true to prevent STATEMENT: inclusion */
+ bool hide_ctx; /* true to prevent CONTEXT: inclusion */
+ const char *filename; /* __FILE__ of ereport() call */
+ int lineno; /* __LINE__ of ereport() call */
+ const char *funcname; /* __func__ of ereport() call */
+ const char *domain; /* message domain */
+ const char *context_domain; /* message domain for context message */
+ int sqlerrcode; /* encoded ERRSTATE */
+ char *message; /* primary error message (translated) */
+ char *detail; /* detail error message */
+ char *detail_log; /* detail error message for server log only */
+ char *hint; /* hint message */
+ char *context; /* context message */
+ char *backtrace; /* backtrace */
+ const char *message_id; /* primary message's id (original string) */
+ char *schema_name; /* name of schema */
+ char *table_name; /* name of table */
+ char *column_name; /* name of column */
+ char *datatype_name; /* name of datatype */
+ char *constraint_name; /* name of constraint */
+ int cursorpos; /* cursor index into query string */
+ int internalpos; /* cursor index into internalquery */
+ char *internalquery; /* text of internally-generated query */
+ int saved_errno; /* errno at entry */
+
+ /* context containing associated non-constant strings */
+ struct MemoryContextData *assoc_context;
+} ErrorData;
+
+extern void EmitErrorReport(void);
+extern ErrorData *CopyErrorData(void);
+extern void FreeErrorData(ErrorData *edata);
+extern void FlushErrorState(void);
+extern void ReThrowError(ErrorData *edata) pg_attribute_noreturn();
+extern void ThrowErrorData(ErrorData *edata);
+extern void pg_re_throw(void) pg_attribute_noreturn();
+
+extern char *GetErrorContextStack(void);
+
+/* Hook for intercepting messages before they are sent to the server log */
+typedef void (*emit_log_hook_type) (ErrorData *edata);
+extern PGDLLIMPORT emit_log_hook_type emit_log_hook;
+
+
+/* GUC-configurable parameters */
+
+typedef enum
+{
+ PGERROR_TERSE, /* single-line error messages */
+ PGERROR_DEFAULT, /* recommended style */
+ PGERROR_VERBOSE /* all the facts, ma'am */
+} PGErrorVerbosity;
+
+extern PGDLLIMPORT int Log_error_verbosity;
+extern PGDLLIMPORT char *Log_line_prefix;
+extern PGDLLIMPORT int Log_destination;
+extern PGDLLIMPORT char *Log_destination_string;
+extern PGDLLIMPORT bool syslog_sequence_numbers;
+extern PGDLLIMPORT bool syslog_split_messages;
+
+/* Log destination bitmap */
+#define LOG_DESTINATION_STDERR 1
+#define LOG_DESTINATION_SYSLOG 2
+#define LOG_DESTINATION_EVENTLOG 4
+#define LOG_DESTINATION_CSVLOG 8
+#define LOG_DESTINATION_JSONLOG 16
+
+/* Other exported functions */
+extern void log_status_format(StringInfo buf, const char *format,
+ ErrorData *edata);
+extern void DebugFileOpen(void);
+extern char *unpack_sql_state(int sql_state);
+extern bool in_error_recursion_trouble(void);
+
+/* Common functions shared across destinations */
+extern void reset_formatted_start_time(void);
+extern char *get_formatted_start_time(void);
+extern char *get_formatted_log_time(void);
+extern const char *get_backend_type_for_log(void);
+extern bool check_log_of_query(ErrorData *edata);
+extern const char *error_severity(int elevel);
+extern void write_pipe_chunks(char *data, int len, int dest);
+
+/* Destination-specific functions */
+extern void write_csvlog(ErrorData *edata);
+extern void write_jsonlog(ErrorData *edata);
+
+/*
+ * Write errors to stderr (or by equal means when stderr is
+ * not available). Used before ereport/elog can be used
+ * safely (memory context, GUC load etc)
+ */
+extern void write_stderr(const char *fmt,...) pg_attribute_printf(1, 2);
+
+/*
+ * Write a message to STDERR using only async-signal-safe functions. This can
+ * be used to safely emit a message from a signal handler.
+ */
+extern void write_stderr_signal_safe(const char *fmt);
+
+#endif /* ELOG_H */
diff --git a/contrib/libs/libpq/src/include/utils/palloc.h b/contrib/libs/libpq/src/include/utils/palloc.h
new file mode 100644
index 0000000000..d1146c1235
--- /dev/null
+++ b/contrib/libs/libpq/src/include/utils/palloc.h
@@ -0,0 +1,165 @@
+/*-------------------------------------------------------------------------
+ *
+ * palloc.h
+ * POSTGRES memory allocator definitions.
+ *
+ * This file contains the basic memory allocation interface that is
+ * needed by almost every backend module. It is included directly by
+ * postgres.h, so the definitions here are automatically available
+ * everywhere. Keep it lean!
+ *
+ * Memory allocation occurs within "contexts". Every chunk obtained from
+ * palloc()/MemoryContextAlloc() is allocated within a specific context.
+ * The entire contents of a context can be freed easily and quickly by
+ * resetting or deleting the context --- this is both faster and less
+ * prone to memory-leakage bugs than releasing chunks individually.
+ * We organize contexts into context trees to allow fine-grain control
+ * over chunk lifetime while preserving the certainty that we will free
+ * everything that should be freed. See utils/mmgr/README for more info.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/palloc.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PALLOC_H
+#define PALLOC_H
+
+/*
+ * Type MemoryContextData is declared in nodes/memnodes.h. Most users
+ * of memory allocation should just treat it as an abstract type, so we
+ * do not provide the struct contents here.
+ */
+typedef struct MemoryContextData *MemoryContext;
+
+/*
+ * A memory context can have callback functions registered on it. Any such
+ * function will be called once just before the context is next reset or
+ * deleted. The MemoryContextCallback struct describing such a callback
+ * typically would be allocated within the context itself, thereby avoiding
+ * any need to manage it explicitly (the reset/delete action will free it).
+ */
+typedef void (*MemoryContextCallbackFunction) (void *arg);
+
+typedef struct MemoryContextCallback
+{
+ MemoryContextCallbackFunction func; /* function to call */
+ void *arg; /* argument to pass it */
+ struct MemoryContextCallback *next; /* next in list of callbacks */
+} MemoryContextCallback;
+
+/*
+ * CurrentMemoryContext is the default allocation context for palloc().
+ * Avoid accessing it directly! Instead, use MemoryContextSwitchTo()
+ * to change the setting.
+ */
+extern PGDLLIMPORT MemoryContext CurrentMemoryContext;
+
+/*
+ * Flags for MemoryContextAllocExtended.
+ */
+#define MCXT_ALLOC_HUGE 0x01 /* allow huge allocation (> 1 GB) */
+#define MCXT_ALLOC_NO_OOM 0x02 /* no failure if out-of-memory */
+#define MCXT_ALLOC_ZERO 0x04 /* zero allocated memory */
+
+/*
+ * Fundamental memory-allocation operations (more are in utils/memutils.h)
+ */
+extern void *MemoryContextAlloc(MemoryContext context, Size size);
+extern void *MemoryContextAllocZero(MemoryContext context, Size size);
+extern void *MemoryContextAllocZeroAligned(MemoryContext context, Size size);
+extern void *MemoryContextAllocExtended(MemoryContext context,
+ Size size, int flags);
+extern void *MemoryContextAllocAligned(MemoryContext context,
+ Size size, Size alignto, int flags);
+
+extern void *palloc(Size size);
+extern void *palloc0(Size size);
+extern void *palloc_extended(Size size, int flags);
+extern void *palloc_aligned(Size size, Size alignto, int flags);
+extern pg_nodiscard void *repalloc(void *pointer, Size size);
+extern pg_nodiscard void *repalloc_extended(void *pointer,
+ Size size, int flags);
+extern pg_nodiscard void *repalloc0(void *pointer, Size oldsize, Size size);
+extern void pfree(void *pointer);
+
+/*
+ * Variants with easier notation and more type safety
+ */
+
+/*
+ * Allocate space for one object of type "type"
+ */
+#define palloc_object(type) ((type *) palloc(sizeof(type)))
+#define palloc0_object(type) ((type *) palloc0(sizeof(type)))
+
+/*
+ * Allocate space for "count" objects of type "type"
+ */
+#define palloc_array(type, count) ((type *) palloc(sizeof(type) * (count)))
+#define palloc0_array(type, count) ((type *) palloc0(sizeof(type) * (count)))
+
+/*
+ * Change size of allocation pointed to by "pointer" to have space for "count"
+ * objects of type "type"
+ */
+#define repalloc_array(pointer, type, count) ((type *) repalloc(pointer, sizeof(type) * (count)))
+#define repalloc0_array(pointer, type, oldcount, count) ((type *) repalloc0(pointer, sizeof(type) * (oldcount), sizeof(type) * (count)))
+
+/*
+ * The result of palloc() is always word-aligned, so we can skip testing
+ * alignment of the pointer when deciding which MemSet variant to use.
+ * Note that this variant does not offer any advantage, and should not be
+ * used, unless its "sz" argument is a compile-time constant; therefore, the
+ * issue that it evaluates the argument multiple times isn't a problem in
+ * practice.
+ */
+#define palloc0fast(sz) \
+ ( MemSetTest(0, sz) ? \
+ MemoryContextAllocZeroAligned(CurrentMemoryContext, sz) : \
+ MemoryContextAllocZero(CurrentMemoryContext, sz) )
+
+/* Higher-limit allocators. */
+extern void *MemoryContextAllocHuge(MemoryContext context, Size size);
+extern pg_nodiscard void *repalloc_huge(void *pointer, Size size);
+
+/*
+ * Although this header file is nominally backend-only, certain frontend
+ * programs like pg_controldata include it via postgres.h. For some compilers
+ * it's necessary to hide the inline definition of MemoryContextSwitchTo in
+ * this scenario; hence the #ifndef FRONTEND.
+ */
+
+#ifndef FRONTEND
+static inline MemoryContext
+MemoryContextSwitchTo(MemoryContext context)
+{
+ MemoryContext old = CurrentMemoryContext;
+
+ CurrentMemoryContext = context;
+ return old;
+}
+#endif /* FRONTEND */
+
+/* Registration of memory context reset/delete callbacks */
+extern void MemoryContextRegisterResetCallback(MemoryContext context,
+ MemoryContextCallback *cb);
+
+/*
+ * These are like standard strdup() except the copied string is
+ * allocated in a context, not with malloc().
+ */
+extern char *MemoryContextStrdup(MemoryContext context, const char *string);
+extern char *pstrdup(const char *in);
+extern char *pnstrdup(const char *in, Size len);
+
+extern char *pchomp(const char *in);
+
+/* sprintf into a palloc'd buffer --- these are in psprintf.c */
+extern char *psprintf(const char *fmt,...) pg_attribute_printf(1, 2);
+extern size_t pvsnprintf(char *buf, size_t len, const char *fmt, va_list args) pg_attribute_printf(3, 0);
+
+#endif /* PALLOC_H */
diff --git a/contrib/libs/libpq/src/interfaces/libpq/README b/contrib/libs/libpq/src/interfaces/libpq/README
new file mode 100644
index 0000000000..0dcef75a83
--- /dev/null
+++ b/contrib/libs/libpq/src/interfaces/libpq/README
@@ -0,0 +1,3 @@
+src/interfaces/libpq/README
+
+This directory contains the C version of Libpq, the POSTGRES frontend library.
diff --git a/contrib/libs/libpq/src/interfaces/libpq/exports.txt b/contrib/libs/libpq/src/interfaces/libpq/exports.txt
new file mode 100644
index 0000000000..7ded77aff3
--- /dev/null
+++ b/contrib/libs/libpq/src/interfaces/libpq/exports.txt
@@ -0,0 +1,189 @@
+# src/interfaces/libpq/exports.txt
+# Functions to be exported by libpq DLLs
+PQconnectdb 1
+PQsetdbLogin 2
+PQconndefaults 3
+PQfinish 4
+PQreset 5
+PQrequestCancel 6
+PQdb 7
+PQuser 8
+PQpass 9
+PQhost 10
+PQport 11
+PQtty 12
+PQoptions 13
+PQstatus 14
+PQerrorMessage 15
+PQsocket 16
+PQbackendPID 17
+PQtrace 18
+PQuntrace 19
+PQsetNoticeProcessor 20
+PQexec 21
+PQnotifies 22
+PQsendQuery 23
+PQgetResult 24
+PQisBusy 25
+PQconsumeInput 26
+PQgetline 27
+PQputline 28
+PQgetlineAsync 29
+PQputnbytes 30
+PQendcopy 31
+PQfn 32
+PQresultStatus 33
+PQntuples 34
+PQnfields 35
+PQbinaryTuples 36
+PQfname 37
+PQfnumber 38
+PQftype 39
+PQfsize 40
+PQfmod 41
+PQcmdStatus 42
+PQoidStatus 43
+PQcmdTuples 44
+PQgetvalue 45
+PQgetlength 46
+PQgetisnull 47
+PQclear 48
+PQmakeEmptyPGresult 49
+PQprint 50
+PQdisplayTuples 51
+PQprintTuples 52
+lo_open 53
+lo_close 54
+lo_read 55
+lo_write 56
+lo_lseek 57
+lo_creat 58
+lo_tell 59
+lo_unlink 60
+lo_import 61
+lo_export 62
+pgresStatus 63
+PQmblen 64
+PQresultErrorMessage 65
+PQresStatus 66
+termPQExpBuffer 67
+appendPQExpBufferChar 68
+initPQExpBuffer 69
+resetPQExpBuffer 70
+PQoidValue 71
+PQclientEncoding 72
+PQenv2encoding 73
+appendBinaryPQExpBuffer 74
+appendPQExpBufferStr 75
+destroyPQExpBuffer 76
+createPQExpBuffer 77
+PQconninfoFree 78
+PQconnectPoll 79
+PQconnectStart 80
+PQflush 81
+PQisnonblocking 82
+PQresetPoll 83
+PQresetStart 84
+PQsetClientEncoding 85
+PQsetnonblocking 86
+PQfreeNotify 87
+PQescapeString 88
+PQescapeBytea 89
+printfPQExpBuffer 90
+appendPQExpBuffer 91
+pg_encoding_to_char 92
+pg_utf_mblen 93
+PQunescapeBytea 94
+PQfreemem 95
+PQtransactionStatus 96
+PQparameterStatus 97
+PQprotocolVersion 98
+PQsetErrorVerbosity 99
+PQsetNoticeReceiver 100
+PQexecParams 101
+PQsendQueryParams 102
+PQputCopyData 103
+PQputCopyEnd 104
+PQgetCopyData 105
+PQresultErrorField 106
+PQftable 107
+PQftablecol 108
+PQfformat 109
+PQexecPrepared 110
+PQsendQueryPrepared 111
+PQdsplen 112
+PQserverVersion 113
+PQgetssl 114
+pg_char_to_encoding 115
+pg_valid_server_encoding 116
+pqsignal 117
+PQprepare 118
+PQsendPrepare 119
+PQgetCancel 120
+PQfreeCancel 121
+PQcancel 122
+lo_create 123
+PQinitSSL 124
+PQregisterThreadLock 125
+PQescapeStringConn 126
+PQescapeByteaConn 127
+PQencryptPassword 128
+PQisthreadsafe 129
+enlargePQExpBuffer 130
+PQnparams 131
+PQparamtype 132
+PQdescribePrepared 133
+PQdescribePortal 134
+PQsendDescribePrepared 135
+PQsendDescribePortal 136
+lo_truncate 137
+PQconnectionUsedPassword 138
+pg_valid_server_encoding_id 139
+PQconnectionNeedsPassword 140
+lo_import_with_oid 141
+PQcopyResult 142
+PQsetResultAttrs 143
+PQsetvalue 144
+PQresultAlloc 145
+PQregisterEventProc 146
+PQinstanceData 147
+PQsetInstanceData 148
+PQresultInstanceData 149
+PQresultSetInstanceData 150
+PQfireResultCreateEvents 151
+PQconninfoParse 152
+PQinitOpenSSL 153
+PQescapeLiteral 154
+PQescapeIdentifier 155
+PQconnectdbParams 156
+PQconnectStartParams 157
+PQping 158
+PQpingParams 159
+PQlibVersion 160
+PQsetSingleRowMode 161
+lo_lseek64 162
+lo_tell64 163
+lo_truncate64 164
+PQconninfo 165
+PQsslInUse 166
+PQsslStruct 167
+PQsslAttributeNames 168
+PQsslAttribute 169
+PQsetErrorContextVisibility 170
+PQresultVerboseErrorMessage 171
+PQencryptPasswordConn 172
+PQresultMemorySize 173
+PQhostaddr 174
+PQgssEncInUse 175
+PQgetgssctx 176
+PQsetSSLKeyPassHook_OpenSSL 177
+PQgetSSLKeyPassHook_OpenSSL 178
+PQdefaultSSLKeyPassHook_OpenSSL 179
+PQenterPipelineMode 180
+PQexitPipelineMode 181
+PQpipelineSync 182
+PQpipelineStatus 183
+PQsetTraceFlags 184
+PQmblenBounded 185
+PQsendFlushRequest 186
+PQconnectionUsedGSSAPI 187
diff --git a/contrib/libs/libpq/src/interfaces/libpq/fe-auth-sasl.h b/contrib/libs/libpq/src/interfaces/libpq/fe-auth-sasl.h
new file mode 100644
index 0000000000..ddf6ea3f3f
--- /dev/null
+++ b/contrib/libs/libpq/src/interfaces/libpq/fe-auth-sasl.h
@@ -0,0 +1,131 @@
+/*-------------------------------------------------------------------------
+ *
+ * fe-auth-sasl.h
+ * Defines the SASL mechanism interface for libpq.
+ *
+ * Each SASL mechanism defines a frontend and a backend callback structure.
+ * This is not part of the public API for applications.
+ *
+ * See src/include/libpq/sasl.h for the backend counterpart.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/interfaces/libpq/fe-auth-sasl.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FE_AUTH_SASL_H
+#define FE_AUTH_SASL_H
+
+#include "libpq-fe.h"
+
+/*
+ * Frontend SASL mechanism callbacks.
+ *
+ * To implement a frontend mechanism, declare a pg_be_sasl_mech struct with
+ * appropriate callback implementations, then hook it into conn->sasl during
+ * pg_SASL_init()'s mechanism negotiation.
+ */
+typedef struct pg_fe_sasl_mech
+{
+ /*-------
+ * init()
+ *
+ * Initializes mechanism-specific state for a connection. This
+ * callback must return a pointer to its allocated state, which will
+ * be passed as-is as the first argument to the other callbacks.
+ * the free() callback is called to release any state resources.
+ *
+ * If state allocation fails, the implementation should return NULL to
+ * fail the authentication exchange.
+ *
+ * Input parameters:
+ *
+ * conn: The connection to the server
+ *
+ * password: The user's supplied password for the current connection
+ *
+ * mech: The mechanism name in use, for implementations that may
+ * advertise more than one name (such as *-PLUS variants).
+ *-------
+ */
+ void *(*init) (PGconn *conn, const char *password, const char *mech);
+
+ /*--------
+ * exchange()
+ *
+ * Produces a client response to a server challenge. As a special case
+ * for client-first SASL mechanisms, exchange() is called with a NULL
+ * server response once at the start of the authentication exchange to
+ * generate an initial response.
+ *
+ * Input parameters:
+ *
+ * state: The opaque mechanism state returned by init()
+ *
+ * input: The challenge data sent by the server, or NULL when
+ * generating a client-first initial response (that is, when
+ * the server expects the client to send a message to start
+ * the exchange). This is guaranteed to be null-terminated
+ * for safety, but SASL allows embedded nulls in challenges,
+ * so mechanisms must be careful to check inputlen.
+ *
+ * inputlen: The length of the challenge data sent by the server, or -1
+ * during client-first initial response generation.
+ *
+ * Output parameters, to be set by the callback function:
+ *
+ * output: A malloc'd buffer containing the client's response to
+ * the server (can be empty), or NULL if the exchange should
+ * be aborted. (*success should be set to false in the
+ * latter case.)
+ *
+ * outputlen: The length (0 or higher) of the client response buffer,
+ * ignored if output is NULL.
+ *
+ * done: Set to true if the SASL exchange should not continue,
+ * because the exchange is either complete or failed
+ *
+ * success: Set to true if the SASL exchange completed successfully.
+ * Ignored if *done is false.
+ *--------
+ */
+ void (*exchange) (void *state, char *input, int inputlen,
+ char **output, int *outputlen,
+ bool *done, bool *success);
+
+ /*--------
+ * channel_bound()
+ *
+ * Returns true if the connection has an established channel binding. A
+ * mechanism implementation must ensure that a SASL exchange has actually
+ * been completed, in addition to checking that channel binding is in use.
+ *
+ * Mechanisms that do not implement channel binding may simply return
+ * false.
+ *
+ * Input parameters:
+ *
+ * state: The opaque mechanism state returned by init()
+ *--------
+ */
+ bool (*channel_bound) (void *state);
+
+ /*--------
+ * free()
+ *
+ * Frees the state allocated by init(). This is called when the connection
+ * is dropped, not when the exchange is completed.
+ *
+ * Input parameters:
+ *
+ * state: The opaque mechanism state returned by init()
+ *--------
+ */
+ void (*free) (void *state);
+
+} pg_fe_sasl_mech;
+
+#endif /* FE_AUTH_SASL_H */
diff --git a/contrib/libs/libpq/src/interfaces/libpq/fe-auth-scram.c b/contrib/libs/libpq/src/interfaces/libpq/fe-auth-scram.c
new file mode 100644
index 0000000000..6b779ec7ff
--- /dev/null
+++ b/contrib/libs/libpq/src/interfaces/libpq/fe-auth-scram.c
@@ -0,0 +1,936 @@
+/*-------------------------------------------------------------------------
+ *
+ * fe-auth-scram.c
+ * The front-end (client) implementation of SCRAM authentication.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/interfaces/libpq/fe-auth-scram.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres_fe.h"
+
+#include "common/base64.h"
+#include "common/hmac.h"
+#include "common/saslprep.h"
+#include "common/scram-common.h"
+#include "fe-auth.h"
+
+
+/* The exported SCRAM callback mechanism. */
+static void *scram_init(PGconn *conn, const char *password,
+ const char *sasl_mechanism);
+static void scram_exchange(void *opaq, char *input, int inputlen,
+ char **output, int *outputlen,
+ bool *done, bool *success);
+static bool scram_channel_bound(void *opaq);
+static void scram_free(void *opaq);
+
+const pg_fe_sasl_mech pg_scram_mech = {
+ scram_init,
+ scram_exchange,
+ scram_channel_bound,
+ scram_free
+};
+
+/*
+ * Status of exchange messages used for SCRAM authentication via the
+ * SASL protocol.
+ */
+typedef enum
+{
+ FE_SCRAM_INIT,
+ FE_SCRAM_NONCE_SENT,
+ FE_SCRAM_PROOF_SENT,
+ FE_SCRAM_FINISHED
+} fe_scram_state_enum;
+
+typedef struct
+{
+ fe_scram_state_enum state;
+
+ /* These are supplied by the user */
+ PGconn *conn;
+ char *password;
+ char *sasl_mechanism;
+
+ /* State data depending on the hash type */
+ pg_cryptohash_type hash_type;
+ int key_length;
+
+ /* We construct these */
+ uint8 SaltedPassword[SCRAM_MAX_KEY_LEN];
+ char *client_nonce;
+ char *client_first_message_bare;
+ char *client_final_message_without_proof;
+
+ /* These come from the server-first message */
+ char *server_first_message;
+ char *salt;
+ int saltlen;
+ int iterations;
+ char *nonce;
+
+ /* These come from the server-final message */
+ char *server_final_message;
+ char ServerSignature[SCRAM_MAX_KEY_LEN];
+} fe_scram_state;
+
+static bool read_server_first_message(fe_scram_state *state, char *input);
+static bool read_server_final_message(fe_scram_state *state, char *input);
+static char *build_client_first_message(fe_scram_state *state);
+static char *build_client_final_message(fe_scram_state *state);
+static bool verify_server_signature(fe_scram_state *state, bool *match,
+ const char **errstr);
+static bool calculate_client_proof(fe_scram_state *state,
+ const char *client_final_message_without_proof,
+ uint8 *result, const char **errstr);
+
+/*
+ * Initialize SCRAM exchange status.
+ */
+static void *
+scram_init(PGconn *conn,
+ const char *password,
+ const char *sasl_mechanism)
+{
+ fe_scram_state *state;
+ char *prep_password;
+ pg_saslprep_rc rc;
+
+ Assert(sasl_mechanism != NULL);
+
+ state = (fe_scram_state *) malloc(sizeof(fe_scram_state));
+ if (!state)
+ return NULL;
+ memset(state, 0, sizeof(fe_scram_state));
+ state->conn = conn;
+ state->state = FE_SCRAM_INIT;
+ state->key_length = SCRAM_SHA_256_KEY_LEN;
+ state->hash_type = PG_SHA256;
+
+ state->sasl_mechanism = strdup(sasl_mechanism);
+ if (!state->sasl_mechanism)
+ {
+ free(state);
+ return NULL;
+ }
+
+ /* Normalize the password with SASLprep, if possible */
+ rc = pg_saslprep(password, &prep_password);
+ if (rc == SASLPREP_OOM)
+ {
+ free(state->sasl_mechanism);
+ free(state);
+ return NULL;
+ }
+ if (rc != SASLPREP_SUCCESS)
+ {
+ prep_password = strdup(password);
+ if (!prep_password)
+ {
+ free(state->sasl_mechanism);
+ free(state);
+ return NULL;
+ }
+ }
+ state->password = prep_password;
+
+ return state;
+}
+
+/*
+ * Return true if channel binding was employed and the SCRAM exchange
+ * completed. This should be used after a successful exchange to determine
+ * whether the server authenticated itself to the client.
+ *
+ * Note that the caller must also ensure that the exchange was actually
+ * successful.
+ */
+static bool
+scram_channel_bound(void *opaq)
+{
+ fe_scram_state *state = (fe_scram_state *) opaq;
+
+ /* no SCRAM exchange done */
+ if (state == NULL)
+ return false;
+
+ /* SCRAM exchange not completed */
+ if (state->state != FE_SCRAM_FINISHED)
+ return false;
+
+ /* channel binding mechanism not used */
+ if (strcmp(state->sasl_mechanism, SCRAM_SHA_256_PLUS_NAME) != 0)
+ return false;
+
+ /* all clear! */
+ return true;
+}
+
+/*
+ * Free SCRAM exchange status
+ */
+static void
+scram_free(void *opaq)
+{
+ fe_scram_state *state = (fe_scram_state *) opaq;
+
+ free(state->password);
+ free(state->sasl_mechanism);
+
+ /* client messages */
+ free(state->client_nonce);
+ free(state->client_first_message_bare);
+ free(state->client_final_message_without_proof);
+
+ /* first message from server */
+ free(state->server_first_message);
+ free(state->salt);
+ free(state->nonce);
+
+ /* final message from server */
+ free(state->server_final_message);
+
+ free(state);
+}
+
+/*
+ * Exchange a SCRAM message with backend.
+ */
+static void
+scram_exchange(void *opaq, char *input, int inputlen,
+ char **output, int *outputlen,
+ bool *done, bool *success)
+{
+ fe_scram_state *state = (fe_scram_state *) opaq;
+ PGconn *conn = state->conn;
+ const char *errstr = NULL;
+
+ *done = false;
+ *success = false;
+ *output = NULL;
+ *outputlen = 0;
+
+ /*
+ * Check that the input length agrees with the string length of the input.
+ * We can ignore inputlen after this.
+ */
+ if (state->state != FE_SCRAM_INIT)
+ {
+ if (inputlen == 0)
+ {
+ libpq_append_conn_error(conn, "malformed SCRAM message (empty message)");
+ goto error;
+ }
+ if (inputlen != strlen(input))
+ {
+ libpq_append_conn_error(conn, "malformed SCRAM message (length mismatch)");
+ goto error;
+ }
+ }
+
+ switch (state->state)
+ {
+ case FE_SCRAM_INIT:
+ /* Begin the SCRAM handshake, by sending client nonce */
+ *output = build_client_first_message(state);
+ if (*output == NULL)
+ goto error;
+
+ *outputlen = strlen(*output);
+ *done = false;
+ state->state = FE_SCRAM_NONCE_SENT;
+ break;
+
+ case FE_SCRAM_NONCE_SENT:
+ /* Receive salt and server nonce, send response. */
+ if (!read_server_first_message(state, input))
+ goto error;
+
+ *output = build_client_final_message(state);
+ if (*output == NULL)
+ goto error;
+
+ *outputlen = strlen(*output);
+ *done = false;
+ state->state = FE_SCRAM_PROOF_SENT;
+ break;
+
+ case FE_SCRAM_PROOF_SENT:
+ /* Receive server signature */
+ if (!read_server_final_message(state, input))
+ goto error;
+
+ /*
+ * Verify server signature, to make sure we're talking to the
+ * genuine server.
+ */
+ if (!verify_server_signature(state, success, &errstr))
+ {
+ libpq_append_conn_error(conn, "could not verify server signature: %s", errstr);
+ goto error;
+ }
+
+ if (!*success)
+ {
+ libpq_append_conn_error(conn, "incorrect server signature");
+ }
+ *done = true;
+ state->state = FE_SCRAM_FINISHED;
+ state->conn->client_finished_auth = true;
+ break;
+
+ default:
+ /* shouldn't happen */
+ libpq_append_conn_error(conn, "invalid SCRAM exchange state");
+ goto error;
+ }
+ return;
+
+error:
+ *done = true;
+ *success = false;
+}
+
+/*
+ * Read value for an attribute part of a SCRAM message.
+ *
+ * The buffer at **input is destructively modified, and *input is
+ * advanced over the "attr=value" string and any following comma.
+ *
+ * On failure, append an error message to *errorMessage and return NULL.
+ */
+static char *
+read_attr_value(char **input, char attr, PQExpBuffer errorMessage)
+{
+ char *begin = *input;
+ char *end;
+
+ if (*begin != attr)
+ {
+ libpq_append_error(errorMessage,
+ "malformed SCRAM message (attribute \"%c\" expected)",
+ attr);
+ return NULL;
+ }
+ begin++;
+
+ if (*begin != '=')
+ {
+ libpq_append_error(errorMessage,
+ "malformed SCRAM message (expected character \"=\" for attribute \"%c\")",
+ attr);
+ return NULL;
+ }
+ begin++;
+
+ end = begin;
+ while (*end && *end != ',')
+ end++;
+
+ if (*end)
+ {
+ *end = '\0';
+ *input = end + 1;
+ }
+ else
+ *input = end;
+
+ return begin;
+}
+
+/*
+ * Build the first exchange message sent by the client.
+ */
+static char *
+build_client_first_message(fe_scram_state *state)
+{
+ PGconn *conn = state->conn;
+ char raw_nonce[SCRAM_RAW_NONCE_LEN + 1];
+ char *result;
+ int channel_info_len;
+ int encoded_len;
+ PQExpBufferData buf;
+
+ /*
+ * Generate a "raw" nonce. This is converted to ASCII-printable form by
+ * base64-encoding it.
+ */
+ if (!pg_strong_random(raw_nonce, SCRAM_RAW_NONCE_LEN))
+ {
+ libpq_append_conn_error(conn, "could not generate nonce");
+ return NULL;
+ }
+
+ encoded_len = pg_b64_enc_len(SCRAM_RAW_NONCE_LEN);
+ /* don't forget the zero-terminator */
+ state->client_nonce = malloc(encoded_len + 1);
+ if (state->client_nonce == NULL)
+ {
+ libpq_append_conn_error(conn, "out of memory");
+ return NULL;
+ }
+ encoded_len = pg_b64_encode(raw_nonce, SCRAM_RAW_NONCE_LEN,
+ state->client_nonce, encoded_len);
+ if (encoded_len < 0)
+ {
+ libpq_append_conn_error(conn, "could not encode nonce");
+ return NULL;
+ }
+ state->client_nonce[encoded_len] = '\0';
+
+ /*
+ * Generate message. The username is left empty as the backend uses the
+ * value provided by the startup packet. Also, as this username is not
+ * prepared with SASLprep, the message parsing would fail if it includes
+ * '=' or ',' characters.
+ */
+
+ initPQExpBuffer(&buf);
+
+ /*
+ * First build the gs2-header with channel binding information.
+ */
+ if (strcmp(state->sasl_mechanism, SCRAM_SHA_256_PLUS_NAME) == 0)
+ {
+ Assert(conn->ssl_in_use);
+ appendPQExpBufferStr(&buf, "p=tls-server-end-point");
+ }
+#ifdef HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH
+ else if (conn->channel_binding[0] != 'd' && /* disable */
+ conn->ssl_in_use)
+ {
+ /*
+ * Client supports channel binding, but thinks the server does not.
+ */
+ appendPQExpBufferChar(&buf, 'y');
+ }
+#endif
+ else
+ {
+ /*
+ * Client does not support channel binding, or has disabled it.
+ */
+ appendPQExpBufferChar(&buf, 'n');
+ }
+
+ if (PQExpBufferDataBroken(buf))
+ goto oom_error;
+
+ channel_info_len = buf.len;
+
+ appendPQExpBuffer(&buf, ",,n=,r=%s", state->client_nonce);
+ if (PQExpBufferDataBroken(buf))
+ goto oom_error;
+
+ /*
+ * The first message content needs to be saved without channel binding
+ * information.
+ */
+ state->client_first_message_bare = strdup(buf.data + channel_info_len + 2);
+ if (!state->client_first_message_bare)
+ goto oom_error;
+
+ result = strdup(buf.data);
+ if (result == NULL)
+ goto oom_error;
+
+ termPQExpBuffer(&buf);
+ return result;
+
+oom_error:
+ termPQExpBuffer(&buf);
+ libpq_append_conn_error(conn, "out of memory");
+ return NULL;
+}
+
+/*
+ * Build the final exchange message sent from the client.
+ */
+static char *
+build_client_final_message(fe_scram_state *state)
+{
+ PQExpBufferData buf;
+ PGconn *conn = state->conn;
+ uint8 client_proof[SCRAM_MAX_KEY_LEN];
+ char *result;
+ int encoded_len;
+ const char *errstr = NULL;
+
+ initPQExpBuffer(&buf);
+
+ /*
+ * Construct client-final-message-without-proof. We need to remember it
+ * for verifying the server proof in the final step of authentication.
+ *
+ * The channel binding flag handling (p/y/n) must be consistent with
+ * build_client_first_message(), because the server will check that it's
+ * the same flag both times.
+ */
+ if (strcmp(state->sasl_mechanism, SCRAM_SHA_256_PLUS_NAME) == 0)
+ {
+#ifdef HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH
+ char *cbind_data = NULL;
+ size_t cbind_data_len = 0;
+ size_t cbind_header_len;
+ char *cbind_input;
+ size_t cbind_input_len;
+ int encoded_cbind_len;
+
+ /* Fetch hash data of server's SSL certificate */
+ cbind_data =
+ pgtls_get_peer_certificate_hash(state->conn,
+ &cbind_data_len);
+ if (cbind_data == NULL)
+ {
+ /* error message is already set on error */
+ termPQExpBuffer(&buf);
+ return NULL;
+ }
+
+ appendPQExpBufferStr(&buf, "c=");
+
+ /* p=type,, */
+ cbind_header_len = strlen("p=tls-server-end-point,,");
+ cbind_input_len = cbind_header_len + cbind_data_len;
+ cbind_input = malloc(cbind_input_len);
+ if (!cbind_input)
+ {
+ free(cbind_data);
+ goto oom_error;
+ }
+ memcpy(cbind_input, "p=tls-server-end-point,,", cbind_header_len);
+ memcpy(cbind_input + cbind_header_len, cbind_data, cbind_data_len);
+
+ encoded_cbind_len = pg_b64_enc_len(cbind_input_len);
+ if (!enlargePQExpBuffer(&buf, encoded_cbind_len))
+ {
+ free(cbind_data);
+ free(cbind_input);
+ goto oom_error;
+ }
+ encoded_cbind_len = pg_b64_encode(cbind_input, cbind_input_len,
+ buf.data + buf.len,
+ encoded_cbind_len);
+ if (encoded_cbind_len < 0)
+ {
+ free(cbind_data);
+ free(cbind_input);
+ termPQExpBuffer(&buf);
+ appendPQExpBufferStr(&conn->errorMessage,
+ "could not encode cbind data for channel binding\n");
+ return NULL;
+ }
+ buf.len += encoded_cbind_len;
+ buf.data[buf.len] = '\0';
+
+ free(cbind_data);
+ free(cbind_input);
+#else
+ /*
+ * Chose channel binding, but the SSL library doesn't support it.
+ * Shouldn't happen.
+ */
+ termPQExpBuffer(&buf);
+ appendPQExpBufferStr(&conn->errorMessage,
+ "channel binding not supported by this build\n");
+ return NULL;
+#endif /* HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH */
+ }
+#ifdef HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH
+ else if (conn->channel_binding[0] != 'd' && /* disable */
+ conn->ssl_in_use)
+ appendPQExpBufferStr(&buf, "c=eSws"); /* base64 of "y,," */
+#endif
+ else
+ appendPQExpBufferStr(&buf, "c=biws"); /* base64 of "n,," */
+
+ if (PQExpBufferDataBroken(buf))
+ goto oom_error;
+
+ appendPQExpBuffer(&buf, ",r=%s", state->nonce);
+ if (PQExpBufferDataBroken(buf))
+ goto oom_error;
+
+ state->client_final_message_without_proof = strdup(buf.data);
+ if (state->client_final_message_without_proof == NULL)
+ goto oom_error;
+
+ /* Append proof to it, to form client-final-message. */
+ if (!calculate_client_proof(state,
+ state->client_final_message_without_proof,
+ client_proof, &errstr))
+ {
+ termPQExpBuffer(&buf);
+ libpq_append_conn_error(conn, "could not calculate client proof: %s", errstr);
+ return NULL;
+ }
+
+ appendPQExpBufferStr(&buf, ",p=");
+ encoded_len = pg_b64_enc_len(state->key_length);
+ if (!enlargePQExpBuffer(&buf, encoded_len))
+ goto oom_error;
+ encoded_len = pg_b64_encode((char *) client_proof,
+ state->key_length,
+ buf.data + buf.len,
+ encoded_len);
+ if (encoded_len < 0)
+ {
+ termPQExpBuffer(&buf);
+ libpq_append_conn_error(conn, "could not encode client proof");
+ return NULL;
+ }
+ buf.len += encoded_len;
+ buf.data[buf.len] = '\0';
+
+ result = strdup(buf.data);
+ if (result == NULL)
+ goto oom_error;
+
+ termPQExpBuffer(&buf);
+ return result;
+
+oom_error:
+ termPQExpBuffer(&buf);
+ libpq_append_conn_error(conn, "out of memory");
+ return NULL;
+}
+
+/*
+ * Read the first exchange message coming from the server.
+ */
+static bool
+read_server_first_message(fe_scram_state *state, char *input)
+{
+ PGconn *conn = state->conn;
+ char *iterations_str;
+ char *endptr;
+ char *encoded_salt;
+ char *nonce;
+ int decoded_salt_len;
+
+ state->server_first_message = strdup(input);
+ if (state->server_first_message == NULL)
+ {
+ libpq_append_conn_error(conn, "out of memory");
+ return false;
+ }
+
+ /* parse the message */
+ nonce = read_attr_value(&input, 'r',
+ &conn->errorMessage);
+ if (nonce == NULL)
+ {
+ /* read_attr_value() has appended an error string */
+ return false;
+ }
+
+ /* Verify immediately that the server used our part of the nonce */
+ if (strlen(nonce) < strlen(state->client_nonce) ||
+ memcmp(nonce, state->client_nonce, strlen(state->client_nonce)) != 0)
+ {
+ libpq_append_conn_error(conn, "invalid SCRAM response (nonce mismatch)");
+ return false;
+ }
+
+ state->nonce = strdup(nonce);
+ if (state->nonce == NULL)
+ {
+ libpq_append_conn_error(conn, "out of memory");
+ return false;
+ }
+
+ encoded_salt = read_attr_value(&input, 's', &conn->errorMessage);
+ if (encoded_salt == NULL)
+ {
+ /* read_attr_value() has appended an error string */
+ return false;
+ }
+ decoded_salt_len = pg_b64_dec_len(strlen(encoded_salt));
+ state->salt = malloc(decoded_salt_len);
+ if (state->salt == NULL)
+ {
+ libpq_append_conn_error(conn, "out of memory");
+ return false;
+ }
+ state->saltlen = pg_b64_decode(encoded_salt,
+ strlen(encoded_salt),
+ state->salt,
+ decoded_salt_len);
+ if (state->saltlen < 0)
+ {
+ libpq_append_conn_error(conn, "malformed SCRAM message (invalid salt)");
+ return false;
+ }
+
+ iterations_str = read_attr_value(&input, 'i', &conn->errorMessage);
+ if (iterations_str == NULL)
+ {
+ /* read_attr_value() has appended an error string */
+ return false;
+ }
+ state->iterations = strtol(iterations_str, &endptr, 10);
+ if (*endptr != '\0' || state->iterations < 1)
+ {
+ libpq_append_conn_error(conn, "malformed SCRAM message (invalid iteration count)");
+ return false;
+ }
+
+ if (*input != '\0')
+ libpq_append_conn_error(conn, "malformed SCRAM message (garbage at end of server-first-message)");
+
+ return true;
+}
+
+/*
+ * Read the final exchange message coming from the server.
+ */
+static bool
+read_server_final_message(fe_scram_state *state, char *input)
+{
+ PGconn *conn = state->conn;
+ char *encoded_server_signature;
+ char *decoded_server_signature;
+ int server_signature_len;
+
+ state->server_final_message = strdup(input);
+ if (!state->server_final_message)
+ {
+ libpq_append_conn_error(conn, "out of memory");
+ return false;
+ }
+
+ /* Check for error result. */
+ if (*input == 'e')
+ {
+ char *errmsg = read_attr_value(&input, 'e',
+ &conn->errorMessage);
+
+ if (errmsg == NULL)
+ {
+ /* read_attr_value() has appended an error message */
+ return false;
+ }
+ libpq_append_conn_error(conn, "error received from server in SCRAM exchange: %s",
+ errmsg);
+ return false;
+ }
+
+ /* Parse the message. */
+ encoded_server_signature = read_attr_value(&input, 'v',
+ &conn->errorMessage);
+ if (encoded_server_signature == NULL)
+ {
+ /* read_attr_value() has appended an error message */
+ return false;
+ }
+
+ if (*input != '\0')
+ libpq_append_conn_error(conn, "malformed SCRAM message (garbage at end of server-final-message)");
+
+ server_signature_len = pg_b64_dec_len(strlen(encoded_server_signature));
+ decoded_server_signature = malloc(server_signature_len);
+ if (!decoded_server_signature)
+ {
+ libpq_append_conn_error(conn, "out of memory");
+ return false;
+ }
+
+ server_signature_len = pg_b64_decode(encoded_server_signature,
+ strlen(encoded_server_signature),
+ decoded_server_signature,
+ server_signature_len);
+ if (server_signature_len != state->key_length)
+ {
+ free(decoded_server_signature);
+ libpq_append_conn_error(conn, "malformed SCRAM message (invalid server signature)");
+ return false;
+ }
+ memcpy(state->ServerSignature, decoded_server_signature,
+ state->key_length);
+ free(decoded_server_signature);
+
+ return true;
+}
+
+/*
+ * Calculate the client proof, part of the final exchange message sent
+ * by the client. Returns true on success, false on failure with *errstr
+ * pointing to a message about the error details.
+ */
+static bool
+calculate_client_proof(fe_scram_state *state,
+ const char *client_final_message_without_proof,
+ uint8 *result, const char **errstr)
+{
+ uint8 StoredKey[SCRAM_MAX_KEY_LEN];
+ uint8 ClientKey[SCRAM_MAX_KEY_LEN];
+ uint8 ClientSignature[SCRAM_MAX_KEY_LEN];
+ int i;
+ pg_hmac_ctx *ctx;
+
+ ctx = pg_hmac_create(state->hash_type);
+ if (ctx == NULL)
+ {
+ *errstr = pg_hmac_error(NULL); /* returns OOM */
+ return false;
+ }
+
+ /*
+ * Calculate SaltedPassword, and store it in 'state' so that we can reuse
+ * it later in verify_server_signature.
+ */
+ if (scram_SaltedPassword(state->password, state->hash_type,
+ state->key_length, state->salt, state->saltlen,
+ state->iterations, state->SaltedPassword,
+ errstr) < 0 ||
+ scram_ClientKey(state->SaltedPassword, state->hash_type,
+ state->key_length, ClientKey, errstr) < 0 ||
+ scram_H(ClientKey, state->hash_type, state->key_length,
+ StoredKey, errstr) < 0)
+ {
+ /* errstr is already filled here */
+ pg_hmac_free(ctx);
+ return false;
+ }
+
+ if (pg_hmac_init(ctx, StoredKey, state->key_length) < 0 ||
+ pg_hmac_update(ctx,
+ (uint8 *) state->client_first_message_bare,
+ strlen(state->client_first_message_bare)) < 0 ||
+ pg_hmac_update(ctx, (uint8 *) ",", 1) < 0 ||
+ pg_hmac_update(ctx,
+ (uint8 *) state->server_first_message,
+ strlen(state->server_first_message)) < 0 ||
+ pg_hmac_update(ctx, (uint8 *) ",", 1) < 0 ||
+ pg_hmac_update(ctx,
+ (uint8 *) client_final_message_without_proof,
+ strlen(client_final_message_without_proof)) < 0 ||
+ pg_hmac_final(ctx, ClientSignature, state->key_length) < 0)
+ {
+ *errstr = pg_hmac_error(ctx);
+ pg_hmac_free(ctx);
+ return false;
+ }
+
+ for (i = 0; i < state->key_length; i++)
+ result[i] = ClientKey[i] ^ ClientSignature[i];
+
+ pg_hmac_free(ctx);
+ return true;
+}
+
+/*
+ * Validate the server signature, received as part of the final exchange
+ * message received from the server. *match tracks if the server signature
+ * matched or not. Returns true if the server signature got verified, and
+ * false for a processing error with *errstr pointing to a message about the
+ * error details.
+ */
+static bool
+verify_server_signature(fe_scram_state *state, bool *match,
+ const char **errstr)
+{
+ uint8 expected_ServerSignature[SCRAM_MAX_KEY_LEN];
+ uint8 ServerKey[SCRAM_MAX_KEY_LEN];
+ pg_hmac_ctx *ctx;
+
+ ctx = pg_hmac_create(state->hash_type);
+ if (ctx == NULL)
+ {
+ *errstr = pg_hmac_error(NULL); /* returns OOM */
+ return false;
+ }
+
+ if (scram_ServerKey(state->SaltedPassword, state->hash_type,
+ state->key_length, ServerKey, errstr) < 0)
+ {
+ /* errstr is filled already */
+ pg_hmac_free(ctx);
+ return false;
+ }
+
+ /* calculate ServerSignature */
+ if (pg_hmac_init(ctx, ServerKey, state->key_length) < 0 ||
+ pg_hmac_update(ctx,
+ (uint8 *) state->client_first_message_bare,
+ strlen(state->client_first_message_bare)) < 0 ||
+ pg_hmac_update(ctx, (uint8 *) ",", 1) < 0 ||
+ pg_hmac_update(ctx,
+ (uint8 *) state->server_first_message,
+ strlen(state->server_first_message)) < 0 ||
+ pg_hmac_update(ctx, (uint8 *) ",", 1) < 0 ||
+ pg_hmac_update(ctx,
+ (uint8 *) state->client_final_message_without_proof,
+ strlen(state->client_final_message_without_proof)) < 0 ||
+ pg_hmac_final(ctx, expected_ServerSignature,
+ state->key_length) < 0)
+ {
+ *errstr = pg_hmac_error(ctx);
+ pg_hmac_free(ctx);
+ return false;
+ }
+
+ pg_hmac_free(ctx);
+
+ /* signature processed, so now check after it */
+ if (memcmp(expected_ServerSignature, state->ServerSignature,
+ state->key_length) != 0)
+ *match = false;
+ else
+ *match = true;
+
+ return true;
+}
+
+/*
+ * Build a new SCRAM secret.
+ *
+ * On error, returns NULL and sets *errstr to point to a message about the
+ * error details.
+ */
+char *
+pg_fe_scram_build_secret(const char *password, int iterations, const char **errstr)
+{
+ char *prep_password;
+ pg_saslprep_rc rc;
+ char saltbuf[SCRAM_DEFAULT_SALT_LEN];
+ char *result;
+
+ /*
+ * Normalize the password with SASLprep. If that doesn't work, because
+ * the password isn't valid UTF-8 or contains prohibited characters, just
+ * proceed with the original password. (See comments at the top of
+ * auth-scram.c.)
+ */
+ rc = pg_saslprep(password, &prep_password);
+ if (rc == SASLPREP_OOM)
+ {
+ *errstr = libpq_gettext("out of memory");
+ return NULL;
+ }
+ if (rc == SASLPREP_SUCCESS)
+ password = (const char *) prep_password;
+
+ /* Generate a random salt */
+ if (!pg_strong_random(saltbuf, SCRAM_DEFAULT_SALT_LEN))
+ {
+ *errstr = libpq_gettext("could not generate random salt");
+ free(prep_password);
+ return NULL;
+ }
+
+ result = scram_build_secret(PG_SHA256, SCRAM_SHA_256_KEY_LEN, saltbuf,
+ SCRAM_DEFAULT_SALT_LEN,
+ iterations, password,
+ errstr);
+
+ free(prep_password);
+
+ return result;
+}
diff --git a/contrib/libs/libpq/src/interfaces/libpq/fe-auth.c b/contrib/libs/libpq/src/interfaces/libpq/fe-auth.c
new file mode 100644
index 0000000000..fce7f3da38
--- /dev/null
+++ b/contrib/libs/libpq/src/interfaces/libpq/fe-auth.c
@@ -0,0 +1,1385 @@
+/*-------------------------------------------------------------------------
+ *
+ * fe-auth.c
+ * The front-end (client) authorization routines
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/interfaces/libpq/fe-auth.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/*
+ * INTERFACE ROUTINES
+ * frontend (client) routines:
+ * pg_fe_sendauth send authentication information
+ * pg_fe_getauthname get user's name according to the client side
+ * of the authentication system
+ */
+
+#include "postgres_fe.h"
+
+#ifdef WIN32
+#include "win32.h"
+#else
+#include <unistd.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <sys/param.h> /* for MAXHOSTNAMELEN on most */
+#include <sys/socket.h>
+#ifdef HAVE_SYS_UCRED_H
+#include <sys/ucred.h>
+#endif
+#ifndef MAXHOSTNAMELEN
+#include <netdb.h> /* for MAXHOSTNAMELEN on some */
+#endif
+#endif
+
+#include "common/md5.h"
+#include "common/scram-common.h"
+#include "fe-auth.h"
+#include "fe-auth-sasl.h"
+#include "libpq-fe.h"
+
+#ifdef ENABLE_GSS
+/*
+ * GSSAPI authentication system.
+ */
+
+#error #include "fe-gssapi-common.h"
+
+/*
+ * Continue GSS authentication with next token as needed.
+ */
+static int
+pg_GSS_continue(PGconn *conn, int payloadlen)
+{
+ OM_uint32 maj_stat,
+ min_stat,
+ lmin_s,
+ gss_flags = GSS_C_MUTUAL_FLAG;
+ gss_buffer_desc ginbuf;
+ gss_buffer_desc goutbuf;
+
+ /*
+ * On first call, there's no input token. On subsequent calls, read the
+ * input token into a GSS buffer.
+ */
+ if (conn->gctx != GSS_C_NO_CONTEXT)
+ {
+ ginbuf.length = payloadlen;
+ ginbuf.value = malloc(payloadlen);
+ if (!ginbuf.value)
+ {
+ libpq_append_conn_error(conn, "out of memory allocating GSSAPI buffer (%d)",
+ payloadlen);
+ return STATUS_ERROR;
+ }
+ if (pqGetnchar(ginbuf.value, payloadlen, conn))
+ {
+ /*
+ * Shouldn't happen, because the caller should've ensured that the
+ * whole message is already in the input buffer.
+ */
+ free(ginbuf.value);
+ return STATUS_ERROR;
+ }
+ }
+ else
+ {
+ ginbuf.length = 0;
+ ginbuf.value = NULL;
+ }
+
+ /* Only try to acquire credentials if GSS delegation isn't disabled. */
+ if (!pg_GSS_have_cred_cache(&conn->gcred))
+ conn->gcred = GSS_C_NO_CREDENTIAL;
+
+ if (conn->gssdelegation && conn->gssdelegation[0] == '1')
+ gss_flags |= GSS_C_DELEG_FLAG;
+
+ maj_stat = gss_init_sec_context(&min_stat,
+ conn->gcred,
+ &conn->gctx,
+ conn->gtarg_nam,
+ GSS_C_NO_OID,
+ gss_flags,
+ 0,
+ GSS_C_NO_CHANNEL_BINDINGS,
+ (ginbuf.value == NULL) ? GSS_C_NO_BUFFER : &ginbuf,
+ NULL,
+ &goutbuf,
+ NULL,
+ NULL);
+
+ free(ginbuf.value);
+
+ if (goutbuf.length != 0)
+ {
+ /*
+ * GSS generated data to send to the server. We don't care if it's the
+ * first or subsequent packet, just send the same kind of password
+ * packet.
+ */
+ if (pqPacketSend(conn, 'p',
+ goutbuf.value, goutbuf.length) != STATUS_OK)
+ {
+ gss_release_buffer(&lmin_s, &goutbuf);
+ return STATUS_ERROR;
+ }
+ }
+ gss_release_buffer(&lmin_s, &goutbuf);
+
+ if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED)
+ {
+ pg_GSS_error(libpq_gettext("GSSAPI continuation error"),
+ conn,
+ maj_stat, min_stat);
+ gss_release_name(&lmin_s, &conn->gtarg_nam);
+ if (conn->gctx)
+ gss_delete_sec_context(&lmin_s, &conn->gctx, GSS_C_NO_BUFFER);
+ return STATUS_ERROR;
+ }
+
+ if (maj_stat == GSS_S_COMPLETE)
+ {
+ conn->client_finished_auth = true;
+ gss_release_name(&lmin_s, &conn->gtarg_nam);
+ conn->gssapi_used = true;
+ }
+
+ return STATUS_OK;
+}
+
+/*
+ * Send initial GSS authentication token
+ */
+static int
+pg_GSS_startup(PGconn *conn, int payloadlen)
+{
+ int ret;
+ char *host = conn->connhost[conn->whichhost].host;
+
+ if (!(host && host[0] != '\0'))
+ {
+ libpq_append_conn_error(conn, "host name must be specified");
+ return STATUS_ERROR;
+ }
+
+ if (conn->gctx)
+ {
+ libpq_append_conn_error(conn, "duplicate GSS authentication request");
+ return STATUS_ERROR;
+ }
+
+ ret = pg_GSS_load_servicename(conn);
+ if (ret != STATUS_OK)
+ return ret;
+
+ /*
+ * Initial packet is the same as a continuation packet with no initial
+ * context.
+ */
+ conn->gctx = GSS_C_NO_CONTEXT;
+
+ return pg_GSS_continue(conn, payloadlen);
+}
+#endif /* ENABLE_GSS */
+
+
+#ifdef ENABLE_SSPI
+/*
+ * SSPI authentication system (Windows only)
+ */
+
+static void
+pg_SSPI_error(PGconn *conn, const char *mprefix, SECURITY_STATUS r)
+{
+ char sysmsg[256];
+
+ if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS |
+ FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, r, 0,
+ sysmsg, sizeof(sysmsg), NULL) == 0)
+ appendPQExpBuffer(&conn->errorMessage, "%s: SSPI error %x\n",
+ mprefix, (unsigned int) r);
+ else
+ appendPQExpBuffer(&conn->errorMessage, "%s: %s (%x)\n",
+ mprefix, sysmsg, (unsigned int) r);
+}
+
+/*
+ * Continue SSPI authentication with next token as needed.
+ */
+static int
+pg_SSPI_continue(PGconn *conn, int payloadlen)
+{
+ SECURITY_STATUS r;
+ CtxtHandle newContext;
+ ULONG contextAttr;
+ SecBufferDesc inbuf;
+ SecBufferDesc outbuf;
+ SecBuffer OutBuffers[1];
+ SecBuffer InBuffers[1];
+ char *inputbuf = NULL;
+
+ if (conn->sspictx != NULL)
+ {
+ /*
+ * On runs other than the first we have some data to send. Put this
+ * data in a SecBuffer type structure.
+ */
+ inputbuf = malloc(payloadlen);
+ if (!inputbuf)
+ {
+ libpq_append_conn_error(conn, "out of memory allocating SSPI buffer (%d)",
+ payloadlen);
+ return STATUS_ERROR;
+ }
+ if (pqGetnchar(inputbuf, payloadlen, conn))
+ {
+ /*
+ * Shouldn't happen, because the caller should've ensured that the
+ * whole message is already in the input buffer.
+ */
+ free(inputbuf);
+ return STATUS_ERROR;
+ }
+
+ inbuf.ulVersion = SECBUFFER_VERSION;
+ inbuf.cBuffers = 1;
+ inbuf.pBuffers = InBuffers;
+ InBuffers[0].pvBuffer = inputbuf;
+ InBuffers[0].cbBuffer = payloadlen;
+ InBuffers[0].BufferType = SECBUFFER_TOKEN;
+ }
+
+ OutBuffers[0].pvBuffer = NULL;
+ OutBuffers[0].BufferType = SECBUFFER_TOKEN;
+ OutBuffers[0].cbBuffer = 0;
+ outbuf.cBuffers = 1;
+ outbuf.pBuffers = OutBuffers;
+ outbuf.ulVersion = SECBUFFER_VERSION;
+
+ r = InitializeSecurityContext(conn->sspicred,
+ conn->sspictx,
+ conn->sspitarget,
+ ISC_REQ_ALLOCATE_MEMORY,
+ 0,
+ SECURITY_NETWORK_DREP,
+ (conn->sspictx == NULL) ? NULL : &inbuf,
+ 0,
+ &newContext,
+ &outbuf,
+ &contextAttr,
+ NULL);
+
+ /* we don't need the input anymore */
+ free(inputbuf);
+
+ if (r != SEC_E_OK && r != SEC_I_CONTINUE_NEEDED)
+ {
+ pg_SSPI_error(conn, libpq_gettext("SSPI continuation error"), r);
+
+ return STATUS_ERROR;
+ }
+
+ if (conn->sspictx == NULL)
+ {
+ /* On first run, transfer retrieved context handle */
+ conn->sspictx = malloc(sizeof(CtxtHandle));
+ if (conn->sspictx == NULL)
+ {
+ libpq_append_conn_error(conn, "out of memory");
+ return STATUS_ERROR;
+ }
+ memcpy(conn->sspictx, &newContext, sizeof(CtxtHandle));
+ }
+
+ /*
+ * If SSPI returned any data to be sent to the server (as it normally
+ * would), send this data as a password packet.
+ */
+ if (outbuf.cBuffers > 0)
+ {
+ if (outbuf.cBuffers != 1)
+ {
+ /*
+ * This should never happen, at least not for Kerberos
+ * authentication. Keep check in case it shows up with other
+ * authentication methods later.
+ */
+ appendPQExpBufferStr(&conn->errorMessage,
+ "SSPI returned invalid number of output buffers\n");
+ return STATUS_ERROR;
+ }
+
+ /*
+ * If the negotiation is complete, there may be zero bytes to send.
+ * The server is at this point not expecting any more data, so don't
+ * send it.
+ */
+ if (outbuf.pBuffers[0].cbBuffer > 0)
+ {
+ if (pqPacketSend(conn, 'p',
+ outbuf.pBuffers[0].pvBuffer, outbuf.pBuffers[0].cbBuffer))
+ {
+ FreeContextBuffer(outbuf.pBuffers[0].pvBuffer);
+ return STATUS_ERROR;
+ }
+ }
+ FreeContextBuffer(outbuf.pBuffers[0].pvBuffer);
+ }
+
+ if (r == SEC_E_OK)
+ conn->client_finished_auth = true;
+
+ /* Cleanup is handled by the code in freePGconn() */
+ return STATUS_OK;
+}
+
+/*
+ * Send initial SSPI authentication token.
+ * If use_negotiate is 0, use kerberos authentication package which is
+ * compatible with Unix. If use_negotiate is 1, use the negotiate package
+ * which supports both kerberos and NTLM, but is not compatible with Unix.
+ */
+static int
+pg_SSPI_startup(PGconn *conn, int use_negotiate, int payloadlen)
+{
+ SECURITY_STATUS r;
+ TimeStamp expire;
+ char *host = conn->connhost[conn->whichhost].host;
+
+ if (conn->sspictx)
+ {
+ libpq_append_conn_error(conn, "duplicate SSPI authentication request");
+ return STATUS_ERROR;
+ }
+
+ /*
+ * Retrieve credentials handle
+ */
+ conn->sspicred = malloc(sizeof(CredHandle));
+ if (conn->sspicred == NULL)
+ {
+ libpq_append_conn_error(conn, "out of memory");
+ return STATUS_ERROR;
+ }
+
+ r = AcquireCredentialsHandle(NULL,
+ use_negotiate ? "negotiate" : "kerberos",
+ SECPKG_CRED_OUTBOUND,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ conn->sspicred,
+ &expire);
+ if (r != SEC_E_OK)
+ {
+ pg_SSPI_error(conn, libpq_gettext("could not acquire SSPI credentials"), r);
+ free(conn->sspicred);
+ conn->sspicred = NULL;
+ return STATUS_ERROR;
+ }
+
+ /*
+ * Compute target principal name. SSPI has a different format from GSSAPI,
+ * but not more complex. We can skip the @REALM part, because Windows will
+ * fill that in for us automatically.
+ */
+ if (!(host && host[0] != '\0'))
+ {
+ libpq_append_conn_error(conn, "host name must be specified");
+ return STATUS_ERROR;
+ }
+ conn->sspitarget = malloc(strlen(conn->krbsrvname) + strlen(host) + 2);
+ if (!conn->sspitarget)
+ {
+ libpq_append_conn_error(conn, "out of memory");
+ return STATUS_ERROR;
+ }
+ sprintf(conn->sspitarget, "%s/%s", conn->krbsrvname, host);
+
+ /*
+ * Indicate that we're in SSPI authentication mode to make sure that
+ * pg_SSPI_continue is called next time in the negotiation.
+ */
+ conn->usesspi = 1;
+
+ return pg_SSPI_continue(conn, payloadlen);
+}
+#endif /* ENABLE_SSPI */
+
+/*
+ * Initialize SASL authentication exchange.
+ */
+static int
+pg_SASL_init(PGconn *conn, int payloadlen)
+{
+ char *initialresponse = NULL;
+ int initialresponselen;
+ bool done;
+ bool success;
+ const char *selected_mechanism;
+ PQExpBufferData mechanism_buf;
+ char *password;
+
+ initPQExpBuffer(&mechanism_buf);
+
+ if (conn->channel_binding[0] == 'r' && /* require */
+ !conn->ssl_in_use)
+ {
+ libpq_append_conn_error(conn, "channel binding required, but SSL not in use");
+ goto error;
+ }
+
+ if (conn->sasl_state)
+ {
+ libpq_append_conn_error(conn, "duplicate SASL authentication request");
+ goto error;
+ }
+
+ /*
+ * Parse the list of SASL authentication mechanisms in the
+ * AuthenticationSASL message, and select the best mechanism that we
+ * support. SCRAM-SHA-256-PLUS and SCRAM-SHA-256 are the only ones
+ * supported at the moment, listed by order of decreasing importance.
+ */
+ selected_mechanism = NULL;
+ for (;;)
+ {
+ if (pqGets(&mechanism_buf, conn))
+ {
+ appendPQExpBufferStr(&conn->errorMessage,
+ "fe_sendauth: invalid authentication request from server: invalid list of authentication mechanisms\n");
+ goto error;
+ }
+ if (PQExpBufferDataBroken(mechanism_buf))
+ goto oom_error;
+
+ /* An empty string indicates end of list */
+ if (mechanism_buf.data[0] == '\0')
+ break;
+
+ /*
+ * Select the mechanism to use. Pick SCRAM-SHA-256-PLUS over anything
+ * else if a channel binding type is set and if the client supports it
+ * (and did not set channel_binding=disable). Pick SCRAM-SHA-256 if
+ * nothing else has already been picked. If we add more mechanisms, a
+ * more refined priority mechanism might become necessary.
+ */
+ if (strcmp(mechanism_buf.data, SCRAM_SHA_256_PLUS_NAME) == 0)
+ {
+ if (conn->ssl_in_use)
+ {
+ /* The server has offered SCRAM-SHA-256-PLUS. */
+
+#ifdef HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH
+ /*
+ * The client supports channel binding, which is chosen if
+ * channel_binding is not disabled.
+ */
+ if (conn->channel_binding[0] != 'd') /* disable */
+ {
+ selected_mechanism = SCRAM_SHA_256_PLUS_NAME;
+ conn->sasl = &pg_scram_mech;
+ }
+#else
+ /*
+ * The client does not support channel binding. If it is
+ * required, complain immediately instead of the error below
+ * which would be confusing as the server is publishing
+ * SCRAM-SHA-256-PLUS.
+ */
+ if (conn->channel_binding[0] == 'r') /* require */
+ {
+ libpq_append_conn_error(conn, "channel binding is required, but client does not support it");
+ goto error;
+ }
+#endif
+ }
+ else
+ {
+ /*
+ * The server offered SCRAM-SHA-256-PLUS, but the connection
+ * is not SSL-encrypted. That's not sane. Perhaps SSL was
+ * stripped by a proxy? There's no point in continuing,
+ * because the server will reject the connection anyway if we
+ * try authenticate without channel binding even though both
+ * the client and server supported it. The SCRAM exchange
+ * checks for that, to prevent downgrade attacks.
+ */
+ libpq_append_conn_error(conn, "server offered SCRAM-SHA-256-PLUS authentication over a non-SSL connection");
+ goto error;
+ }
+ }
+ else if (strcmp(mechanism_buf.data, SCRAM_SHA_256_NAME) == 0 &&
+ !selected_mechanism)
+ {
+ selected_mechanism = SCRAM_SHA_256_NAME;
+ conn->sasl = &pg_scram_mech;
+ }
+ }
+
+ if (!selected_mechanism)
+ {
+ libpq_append_conn_error(conn, "none of the server's SASL authentication mechanisms are supported");
+ goto error;
+ }
+
+ if (conn->channel_binding[0] == 'r' && /* require */
+ strcmp(selected_mechanism, SCRAM_SHA_256_PLUS_NAME) != 0)
+ {
+ libpq_append_conn_error(conn, "channel binding is required, but server did not offer an authentication method that supports channel binding");
+ goto error;
+ }
+
+ /*
+ * Now that the SASL mechanism has been chosen for the exchange,
+ * initialize its state information.
+ */
+
+ /*
+ * First, select the password to use for the exchange, complaining if
+ * there isn't one. Currently, all supported SASL mechanisms require a
+ * password, so we can just go ahead here without further distinction.
+ */
+ conn->password_needed = true;
+ password = conn->connhost[conn->whichhost].password;
+ if (password == NULL)
+ password = conn->pgpass;
+ if (password == NULL || password[0] == '\0')
+ {
+ appendPQExpBufferStr(&conn->errorMessage,
+ PQnoPasswordSupplied);
+ goto error;
+ }
+
+ Assert(conn->sasl);
+
+ /*
+ * Initialize the SASL state information with all the information gathered
+ * during the initial exchange.
+ *
+ * Note: Only tls-unique is supported for the moment.
+ */
+ conn->sasl_state = conn->sasl->init(conn,
+ password,
+ selected_mechanism);
+ if (!conn->sasl_state)
+ goto oom_error;
+
+ /* Get the mechanism-specific Initial Client Response, if any */
+ conn->sasl->exchange(conn->sasl_state,
+ NULL, -1,
+ &initialresponse, &initialresponselen,
+ &done, &success);
+
+ if (done && !success)
+ goto error;
+
+ /*
+ * Build a SASLInitialResponse message, and send it.
+ */
+ if (pqPutMsgStart('p', conn))
+ goto error;
+ if (pqPuts(selected_mechanism, conn))
+ goto error;
+ if (initialresponse)
+ {
+ if (pqPutInt(initialresponselen, 4, conn))
+ goto error;
+ if (pqPutnchar(initialresponse, initialresponselen, conn))
+ goto error;
+ }
+ if (pqPutMsgEnd(conn))
+ goto error;
+ if (pqFlush(conn))
+ goto error;
+
+ termPQExpBuffer(&mechanism_buf);
+ free(initialresponse);
+
+ return STATUS_OK;
+
+error:
+ termPQExpBuffer(&mechanism_buf);
+ free(initialresponse);
+ return STATUS_ERROR;
+
+oom_error:
+ termPQExpBuffer(&mechanism_buf);
+ free(initialresponse);
+ libpq_append_conn_error(conn, "out of memory");
+ return STATUS_ERROR;
+}
+
+/*
+ * Exchange a message for SASL communication protocol with the backend.
+ * This should be used after calling pg_SASL_init to set up the status of
+ * the protocol.
+ */
+static int
+pg_SASL_continue(PGconn *conn, int payloadlen, bool final)
+{
+ char *output;
+ int outputlen;
+ bool done;
+ bool success;
+ int res;
+ char *challenge;
+
+ /* Read the SASL challenge from the AuthenticationSASLContinue message. */
+ challenge = malloc(payloadlen + 1);
+ if (!challenge)
+ {
+ libpq_append_conn_error(conn, "out of memory allocating SASL buffer (%d)",
+ payloadlen);
+ return STATUS_ERROR;
+ }
+
+ if (pqGetnchar(challenge, payloadlen, conn))
+ {
+ free(challenge);
+ return STATUS_ERROR;
+ }
+ /* For safety and convenience, ensure the buffer is NULL-terminated. */
+ challenge[payloadlen] = '\0';
+
+ conn->sasl->exchange(conn->sasl_state,
+ challenge, payloadlen,
+ &output, &outputlen,
+ &done, &success);
+ free(challenge); /* don't need the input anymore */
+
+ if (final && !done)
+ {
+ if (outputlen != 0)
+ free(output);
+
+ libpq_append_conn_error(conn, "AuthenticationSASLFinal received from server, but SASL authentication was not completed");
+ return STATUS_ERROR;
+ }
+
+ /*
+ * If the exchange is not completed yet, we need to make sure that the
+ * SASL mechanism has generated a message to send back.
+ */
+ if (output == NULL && !done)
+ {
+ libpq_append_conn_error(conn, "no client response found after SASL exchange success");
+ return STATUS_ERROR;
+ }
+
+ /*
+ * SASL allows zero-length responses, so this check uses "output" and not
+ * "outputlen" to allow the case of an empty message.
+ */
+ if (output)
+ {
+ /*
+ * Send the SASL response to the server.
+ */
+ res = pqPacketSend(conn, 'p', output, outputlen);
+ free(output);
+
+ if (res != STATUS_OK)
+ return STATUS_ERROR;
+ }
+
+ if (done && !success)
+ return STATUS_ERROR;
+
+ return STATUS_OK;
+}
+
+static int
+pg_password_sendauth(PGconn *conn, const char *password, AuthRequest areq)
+{
+ int ret;
+ char *crypt_pwd = NULL;
+ const char *pwd_to_send;
+ char md5Salt[4];
+
+ /* Read the salt from the AuthenticationMD5Password message. */
+ if (areq == AUTH_REQ_MD5)
+ {
+ if (pqGetnchar(md5Salt, 4, conn))
+ return STATUS_ERROR; /* shouldn't happen */
+ }
+
+ /* Encrypt the password if needed. */
+
+ switch (areq)
+ {
+ case AUTH_REQ_MD5:
+ {
+ char *crypt_pwd2;
+ const char *errstr = NULL;
+
+ /* Allocate enough space for two MD5 hashes */
+ crypt_pwd = malloc(2 * (MD5_PASSWD_LEN + 1));
+ if (!crypt_pwd)
+ {
+ libpq_append_conn_error(conn, "out of memory");
+ return STATUS_ERROR;
+ }
+
+ crypt_pwd2 = crypt_pwd + MD5_PASSWD_LEN + 1;
+ if (!pg_md5_encrypt(password, conn->pguser,
+ strlen(conn->pguser), crypt_pwd2,
+ &errstr))
+ {
+ libpq_append_conn_error(conn, "could not encrypt password: %s", errstr);
+ free(crypt_pwd);
+ return STATUS_ERROR;
+ }
+ if (!pg_md5_encrypt(crypt_pwd2 + strlen("md5"), md5Salt,
+ 4, crypt_pwd, &errstr))
+ {
+ libpq_append_conn_error(conn, "could not encrypt password: %s", errstr);
+ free(crypt_pwd);
+ return STATUS_ERROR;
+ }
+
+ pwd_to_send = crypt_pwd;
+ break;
+ }
+ case AUTH_REQ_PASSWORD:
+ pwd_to_send = password;
+ break;
+ default:
+ return STATUS_ERROR;
+ }
+ ret = pqPacketSend(conn, 'p', pwd_to_send, strlen(pwd_to_send) + 1);
+ free(crypt_pwd);
+ return ret;
+}
+
+/*
+ * Translate a disallowed AuthRequest code into an error message.
+ */
+static const char *
+auth_method_description(AuthRequest areq)
+{
+ switch (areq)
+ {
+ case AUTH_REQ_PASSWORD:
+ return libpq_gettext("server requested a cleartext password");
+ case AUTH_REQ_MD5:
+ return libpq_gettext("server requested a hashed password");
+ case AUTH_REQ_GSS:
+ case AUTH_REQ_GSS_CONT:
+ return libpq_gettext("server requested GSSAPI authentication");
+ case AUTH_REQ_SSPI:
+ return libpq_gettext("server requested SSPI authentication");
+ case AUTH_REQ_SASL:
+ case AUTH_REQ_SASL_CONT:
+ case AUTH_REQ_SASL_FIN:
+ return libpq_gettext("server requested SASL authentication");
+ }
+
+ return libpq_gettext("server requested an unknown authentication type");
+}
+
+/*
+ * Convenience macro for checking the allowed_auth_methods bitmask. Caller
+ * must ensure that type is not greater than 31 (high bit of the bitmask).
+ */
+#define auth_method_allowed(conn, type) \
+ (((conn)->allowed_auth_methods & (1 << (type))) != 0)
+
+/*
+ * Verify that the authentication request is expected, given the connection
+ * parameters. This is especially important when the client wishes to
+ * authenticate the server before any sensitive information is exchanged.
+ */
+static bool
+check_expected_areq(AuthRequest areq, PGconn *conn)
+{
+ bool result = true;
+ const char *reason = NULL;
+
+ StaticAssertDecl((sizeof(conn->allowed_auth_methods) * CHAR_BIT) > AUTH_REQ_MAX,
+ "AUTH_REQ_MAX overflows the allowed_auth_methods bitmask");
+
+ if (conn->sslcertmode[0] == 'r' /* require */
+ && areq == AUTH_REQ_OK)
+ {
+ /*
+ * Trade off a little bit of complexity to try to get these error
+ * messages as precise as possible.
+ */
+ if (!conn->ssl_cert_requested)
+ {
+ libpq_append_conn_error(conn, "server did not request an SSL certificate");
+ return false;
+ }
+ else if (!conn->ssl_cert_sent)
+ {
+ libpq_append_conn_error(conn, "server accepted connection without a valid SSL certificate");
+ return false;
+ }
+ }
+
+ /*
+ * If the user required a specific auth method, or specified an allowed
+ * set, then reject all others here, and make sure the server actually
+ * completes an authentication exchange.
+ */
+ if (conn->require_auth)
+ {
+ switch (areq)
+ {
+ case AUTH_REQ_OK:
+
+ /*
+ * Check to make sure we've actually finished our exchange (or
+ * else that the user has allowed an authentication-less
+ * connection).
+ *
+ * If the user has allowed both SCRAM and unauthenticated
+ * (trust) connections, then this check will silently accept
+ * partial SCRAM exchanges, where a misbehaving server does
+ * not provide its verifier before sending an OK. This is
+ * consistent with historical behavior, but it may be a point
+ * to revisit in the future, since it could allow a server
+ * that doesn't know the user's password to silently harvest
+ * material for a brute force attack.
+ */
+ if (!conn->auth_required || conn->client_finished_auth)
+ break;
+
+ /*
+ * No explicit authentication request was made by the server
+ * -- or perhaps it was made and not completed, in the case of
+ * SCRAM -- but there is one special case to check. If the
+ * user allowed "gss", then a GSS-encrypted channel also
+ * satisfies the check.
+ */
+#ifdef ENABLE_GSS
+ if (auth_method_allowed(conn, AUTH_REQ_GSS) && conn->gssenc)
+ {
+ /*
+ * If implicit GSS auth has already been performed via GSS
+ * encryption, we don't need to have performed an
+ * AUTH_REQ_GSS exchange. This allows require_auth=gss to
+ * be combined with gssencmode, since there won't be an
+ * explicit authentication request in that case.
+ */
+ }
+ else
+#endif
+ {
+ reason = libpq_gettext("server did not complete authentication");
+ result = false;
+ }
+
+ break;
+
+ case AUTH_REQ_PASSWORD:
+ case AUTH_REQ_MD5:
+ case AUTH_REQ_GSS:
+ case AUTH_REQ_GSS_CONT:
+ case AUTH_REQ_SSPI:
+ case AUTH_REQ_SASL:
+ case AUTH_REQ_SASL_CONT:
+ case AUTH_REQ_SASL_FIN:
+
+ /*
+ * We don't handle these with the default case, to avoid
+ * bit-shifting past the end of the allowed_auth_methods mask
+ * if the server sends an unexpected AuthRequest.
+ */
+ result = auth_method_allowed(conn, areq);
+ break;
+
+ default:
+ result = false;
+ break;
+ }
+ }
+
+ if (!result)
+ {
+ if (!reason)
+ reason = auth_method_description(areq);
+
+ libpq_append_conn_error(conn, "authentication method requirement \"%s\" failed: %s",
+ conn->require_auth, reason);
+ return result;
+ }
+
+ /*
+ * When channel_binding=require, we must protect against two cases: (1) we
+ * must not respond to non-SASL authentication requests, which might leak
+ * information such as the client's password; and (2) even if we receive
+ * AUTH_REQ_OK, we still must ensure that channel binding has happened in
+ * order to authenticate the server.
+ */
+ if (conn->channel_binding[0] == 'r' /* require */ )
+ {
+ switch (areq)
+ {
+ case AUTH_REQ_SASL:
+ case AUTH_REQ_SASL_CONT:
+ case AUTH_REQ_SASL_FIN:
+ break;
+ case AUTH_REQ_OK:
+ if (!conn->sasl || !conn->sasl->channel_bound(conn->sasl_state))
+ {
+ libpq_append_conn_error(conn, "channel binding required, but server authenticated client without channel binding");
+ result = false;
+ }
+ break;
+ default:
+ libpq_append_conn_error(conn, "channel binding required but not supported by server's authentication request");
+ result = false;
+ break;
+ }
+ }
+
+ return result;
+}
+
+/*
+ * pg_fe_sendauth
+ * client demux routine for processing an authentication request
+ *
+ * The server has sent us an authentication challenge (or OK). Send an
+ * appropriate response. The caller has ensured that the whole message is
+ * now in the input buffer, and has already read the type and length of
+ * it. We are responsible for reading any remaining extra data, specific
+ * to the authentication method. 'payloadlen' is the remaining length in
+ * the message.
+ */
+int
+pg_fe_sendauth(AuthRequest areq, int payloadlen, PGconn *conn)
+{
+ int oldmsglen;
+
+ if (!check_expected_areq(areq, conn))
+ return STATUS_ERROR;
+
+ switch (areq)
+ {
+ case AUTH_REQ_OK:
+ break;
+
+ case AUTH_REQ_KRB4:
+ libpq_append_conn_error(conn, "Kerberos 4 authentication not supported");
+ return STATUS_ERROR;
+
+ case AUTH_REQ_KRB5:
+ libpq_append_conn_error(conn, "Kerberos 5 authentication not supported");
+ return STATUS_ERROR;
+
+#if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
+ case AUTH_REQ_GSS:
+#if !defined(ENABLE_SSPI)
+ /* no native SSPI, so use GSSAPI library for it */
+ case AUTH_REQ_SSPI:
+#endif
+ {
+ int r;
+
+ pglock_thread();
+
+ /*
+ * If we have both GSS and SSPI support compiled in, use SSPI
+ * support by default. This is overridable by a connection
+ * string parameter. Note that when using SSPI we still leave
+ * the negotiate parameter off, since we want SSPI to use the
+ * GSSAPI kerberos protocol. For actual SSPI negotiate
+ * protocol, we use AUTH_REQ_SSPI.
+ */
+#if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
+ if (conn->gsslib && (pg_strcasecmp(conn->gsslib, "gssapi") == 0))
+ r = pg_GSS_startup(conn, payloadlen);
+ else
+ r = pg_SSPI_startup(conn, 0, payloadlen);
+#elif defined(ENABLE_GSS) && !defined(ENABLE_SSPI)
+ r = pg_GSS_startup(conn, payloadlen);
+#elif !defined(ENABLE_GSS) && defined(ENABLE_SSPI)
+ r = pg_SSPI_startup(conn, 0, payloadlen);
+#endif
+ if (r != STATUS_OK)
+ {
+ /* Error message already filled in. */
+ pgunlock_thread();
+ return STATUS_ERROR;
+ }
+ pgunlock_thread();
+ }
+ break;
+
+ case AUTH_REQ_GSS_CONT:
+ {
+ int r;
+
+ pglock_thread();
+#if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
+ if (conn->usesspi)
+ r = pg_SSPI_continue(conn, payloadlen);
+ else
+ r = pg_GSS_continue(conn, payloadlen);
+#elif defined(ENABLE_GSS) && !defined(ENABLE_SSPI)
+ r = pg_GSS_continue(conn, payloadlen);
+#elif !defined(ENABLE_GSS) && defined(ENABLE_SSPI)
+ r = pg_SSPI_continue(conn, payloadlen);
+#endif
+ if (r != STATUS_OK)
+ {
+ /* Error message already filled in. */
+ pgunlock_thread();
+ return STATUS_ERROR;
+ }
+ pgunlock_thread();
+ }
+ break;
+#else /* defined(ENABLE_GSS) || defined(ENABLE_SSPI) */
+ /* No GSSAPI *or* SSPI support */
+ case AUTH_REQ_GSS:
+ case AUTH_REQ_GSS_CONT:
+ libpq_append_conn_error(conn, "GSSAPI authentication not supported");
+ return STATUS_ERROR;
+#endif /* defined(ENABLE_GSS) || defined(ENABLE_SSPI) */
+
+#ifdef ENABLE_SSPI
+ case AUTH_REQ_SSPI:
+
+ /*
+ * SSPI has its own startup message so libpq can decide which
+ * method to use. Indicate to pg_SSPI_startup that we want SSPI
+ * negotiation instead of Kerberos.
+ */
+ pglock_thread();
+ if (pg_SSPI_startup(conn, 1, payloadlen) != STATUS_OK)
+ {
+ /* Error message already filled in. */
+ pgunlock_thread();
+ return STATUS_ERROR;
+ }
+ pgunlock_thread();
+ break;
+#else
+
+ /*
+ * No SSPI support. However, if we have GSSAPI but not SSPI
+ * support, AUTH_REQ_SSPI will have been handled in the codepath
+ * for AUTH_REQ_GSS above, so don't duplicate the case label in
+ * that case.
+ */
+#if !defined(ENABLE_GSS)
+ case AUTH_REQ_SSPI:
+ libpq_append_conn_error(conn, "SSPI authentication not supported");
+ return STATUS_ERROR;
+#endif /* !define(ENABLE_GSS) */
+#endif /* ENABLE_SSPI */
+
+
+ case AUTH_REQ_CRYPT:
+ libpq_append_conn_error(conn, "Crypt authentication not supported");
+ return STATUS_ERROR;
+
+ case AUTH_REQ_MD5:
+ case AUTH_REQ_PASSWORD:
+ {
+ char *password;
+
+ conn->password_needed = true;
+ password = conn->connhost[conn->whichhost].password;
+ if (password == NULL)
+ password = conn->pgpass;
+ if (password == NULL || password[0] == '\0')
+ {
+ appendPQExpBufferStr(&conn->errorMessage,
+ PQnoPasswordSupplied);
+ return STATUS_ERROR;
+ }
+ if (pg_password_sendauth(conn, password, areq) != STATUS_OK)
+ {
+ appendPQExpBufferStr(&conn->errorMessage,
+ "fe_sendauth: error sending password authentication\n");
+ return STATUS_ERROR;
+ }
+
+ /* We expect no further authentication requests. */
+ conn->client_finished_auth = true;
+ break;
+ }
+
+ case AUTH_REQ_SASL:
+
+ /*
+ * The request contains the name (as assigned by IANA) of the
+ * authentication mechanism.
+ */
+ if (pg_SASL_init(conn, payloadlen) != STATUS_OK)
+ {
+ /* pg_SASL_init already set the error message */
+ return STATUS_ERROR;
+ }
+ break;
+
+ case AUTH_REQ_SASL_CONT:
+ case AUTH_REQ_SASL_FIN:
+ if (conn->sasl_state == NULL)
+ {
+ appendPQExpBufferStr(&conn->errorMessage,
+ "fe_sendauth: invalid authentication request from server: AUTH_REQ_SASL_CONT without AUTH_REQ_SASL\n");
+ return STATUS_ERROR;
+ }
+ oldmsglen = conn->errorMessage.len;
+ if (pg_SASL_continue(conn, payloadlen,
+ (areq == AUTH_REQ_SASL_FIN)) != STATUS_OK)
+ {
+ /* Use this message if pg_SASL_continue didn't supply one */
+ if (conn->errorMessage.len == oldmsglen)
+ appendPQExpBufferStr(&conn->errorMessage,
+ "fe_sendauth: error in SASL authentication\n");
+ return STATUS_ERROR;
+ }
+ break;
+
+ default:
+ libpq_append_conn_error(conn, "authentication method %u not supported", areq);
+ return STATUS_ERROR;
+ }
+
+ return STATUS_OK;
+}
+
+
+/*
+ * pg_fe_getusername
+ *
+ * Returns a pointer to malloc'd space containing the name of the
+ * specified user_id. If there is an error, return NULL, and append
+ * a suitable error message to *errorMessage if that's not NULL.
+ *
+ * Caution: on Windows, the user_id argument is ignored, and we always
+ * fetch the current user's name.
+ */
+char *
+pg_fe_getusername(uid_t user_id, PQExpBuffer errorMessage)
+{
+ char *result = NULL;
+ const char *name = NULL;
+
+#ifdef WIN32
+ /* Microsoft recommends buffer size of UNLEN+1, where UNLEN = 256 */
+ char username[256 + 1];
+ DWORD namesize = sizeof(username);
+#else
+ char pwdbuf[BUFSIZ];
+#endif
+
+ /*
+ * Some users are using configure --enable-thread-safety-force, so we
+ * might as well do the locking within our library to protect getpwuid().
+ * In fact, application developers can use getpwuid() in their application
+ * if they use the locking call we provide, or install their own locking
+ * function using PQregisterThreadLock().
+ */
+ pglock_thread();
+
+#ifdef WIN32
+ if (GetUserName(username, &namesize))
+ name = username;
+ else if (errorMessage)
+ libpq_append_error(errorMessage,
+ "user name lookup failure: error code %lu",
+ GetLastError());
+#else
+ if (pg_get_user_name(user_id, pwdbuf, sizeof(pwdbuf)))
+ name = pwdbuf;
+ else if (errorMessage)
+ appendPQExpBuffer(errorMessage, "%s\n", pwdbuf);
+#endif
+
+ if (name)
+ {
+ result = strdup(name);
+ if (result == NULL && errorMessage)
+ libpq_append_error(errorMessage, "out of memory");
+ }
+
+ pgunlock_thread();
+
+ return result;
+}
+
+/*
+ * pg_fe_getauthname
+ *
+ * Returns a pointer to malloc'd space containing whatever name the user
+ * has authenticated to the system. If there is an error, return NULL,
+ * and append a suitable error message to *errorMessage if that's not NULL.
+ */
+char *
+pg_fe_getauthname(PQExpBuffer errorMessage)
+{
+#ifdef WIN32
+ return pg_fe_getusername(0, errorMessage);
+#else
+ return pg_fe_getusername(geteuid(), errorMessage);
+#endif
+}
+
+
+/*
+ * PQencryptPassword -- exported routine to encrypt a password with MD5
+ *
+ * This function is equivalent to calling PQencryptPasswordConn with
+ * "md5" as the encryption method, except that this doesn't require
+ * a connection object. This function is deprecated, use
+ * PQencryptPasswordConn instead.
+ */
+char *
+PQencryptPassword(const char *passwd, const char *user)
+{
+ char *crypt_pwd;
+ const char *errstr = NULL;
+
+ crypt_pwd = malloc(MD5_PASSWD_LEN + 1);
+ if (!crypt_pwd)
+ return NULL;
+
+ if (!pg_md5_encrypt(passwd, user, strlen(user), crypt_pwd, &errstr))
+ {
+ free(crypt_pwd);
+ return NULL;
+ }
+
+ return crypt_pwd;
+}
+
+/*
+ * PQencryptPasswordConn -- exported routine to encrypt a password
+ *
+ * This is intended to be used by client applications that wish to send
+ * commands like ALTER USER joe PASSWORD 'pwd'. The password need not
+ * be sent in cleartext if it is encrypted on the client side. This is
+ * good because it ensures the cleartext password won't end up in logs,
+ * pg_stat displays, etc. We export the function so that clients won't
+ * be dependent on low-level details like whether the encryption is MD5
+ * or something else.
+ *
+ * Arguments are a connection object, the cleartext password, the SQL
+ * name of the user it is for, and a string indicating the algorithm to
+ * use for encrypting the password. If algorithm is NULL, this queries
+ * the server for the current 'password_encryption' value. If you wish
+ * to avoid that, e.g. to avoid blocking, you can execute
+ * 'show password_encryption' yourself before calling this function, and
+ * pass it as the algorithm.
+ *
+ * Return value is a malloc'd string. The client may assume the string
+ * doesn't contain any special characters that would require escaping.
+ * On error, an error message is stored in the connection object, and
+ * returns NULL.
+ */
+char *
+PQencryptPasswordConn(PGconn *conn, const char *passwd, const char *user,
+ const char *algorithm)
+{
+#define MAX_ALGORITHM_NAME_LEN 50
+ char algobuf[MAX_ALGORITHM_NAME_LEN + 1];
+ char *crypt_pwd = NULL;
+
+ if (!conn)
+ return NULL;
+
+ pqClearConnErrorState(conn);
+
+ /* If no algorithm was given, ask the server. */
+ if (algorithm == NULL)
+ {
+ PGresult *res;
+ char *val;
+
+ res = PQexec(conn, "show password_encryption");
+ if (res == NULL)
+ {
+ /* PQexec() should've set conn->errorMessage already */
+ return NULL;
+ }
+ if (PQresultStatus(res) != PGRES_TUPLES_OK)
+ {
+ /* PQexec() should've set conn->errorMessage already */
+ PQclear(res);
+ return NULL;
+ }
+ if (PQntuples(res) != 1 || PQnfields(res) != 1)
+ {
+ PQclear(res);
+ libpq_append_conn_error(conn, "unexpected shape of result set returned for SHOW");
+ return NULL;
+ }
+ val = PQgetvalue(res, 0, 0);
+
+ if (strlen(val) > MAX_ALGORITHM_NAME_LEN)
+ {
+ PQclear(res);
+ libpq_append_conn_error(conn, "password_encryption value too long");
+ return NULL;
+ }
+ strcpy(algobuf, val);
+ PQclear(res);
+
+ algorithm = algobuf;
+ }
+
+ /*
+ * Also accept "on" and "off" as aliases for "md5", because
+ * password_encryption was a boolean before PostgreSQL 10. We refuse to
+ * send the password in plaintext even if it was "off".
+ */
+ if (strcmp(algorithm, "on") == 0 ||
+ strcmp(algorithm, "off") == 0)
+ algorithm = "md5";
+
+ /*
+ * Ok, now we know what algorithm to use
+ */
+ if (strcmp(algorithm, "scram-sha-256") == 0)
+ {
+ const char *errstr = NULL;
+
+ crypt_pwd = pg_fe_scram_build_secret(passwd,
+ conn->scram_sha_256_iterations,
+ &errstr);
+ if (!crypt_pwd)
+ libpq_append_conn_error(conn, "could not encrypt password: %s", errstr);
+ }
+ else if (strcmp(algorithm, "md5") == 0)
+ {
+ crypt_pwd = malloc(MD5_PASSWD_LEN + 1);
+ if (crypt_pwd)
+ {
+ const char *errstr = NULL;
+
+ if (!pg_md5_encrypt(passwd, user, strlen(user), crypt_pwd, &errstr))
+ {
+ libpq_append_conn_error(conn, "could not encrypt password: %s", errstr);
+ free(crypt_pwd);
+ crypt_pwd = NULL;
+ }
+ }
+ else
+ libpq_append_conn_error(conn, "out of memory");
+ }
+ else
+ {
+ libpq_append_conn_error(conn, "unrecognized password encryption algorithm \"%s\"",
+ algorithm);
+ return NULL;
+ }
+
+ return crypt_pwd;
+}
diff --git a/contrib/libs/libpq/src/interfaces/libpq/fe-auth.h b/contrib/libs/libpq/src/interfaces/libpq/fe-auth.h
new file mode 100644
index 0000000000..124dd5d031
--- /dev/null
+++ b/contrib/libs/libpq/src/interfaces/libpq/fe-auth.h
@@ -0,0 +1,32 @@
+/*-------------------------------------------------------------------------
+ *
+ * fe-auth.h
+ *
+ * Definitions for network authentication routines
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/interfaces/libpq/fe-auth.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef FE_AUTH_H
+#define FE_AUTH_H
+
+#include "libpq-fe.h"
+#include "libpq-int.h"
+
+
+/* Prototypes for functions in fe-auth.c */
+extern int pg_fe_sendauth(AuthRequest areq, int payloadlen, PGconn *conn);
+extern char *pg_fe_getusername(uid_t user_id, PQExpBuffer errorMessage);
+extern char *pg_fe_getauthname(PQExpBuffer errorMessage);
+
+/* Mechanisms in fe-auth-scram.c */
+extern const pg_fe_sasl_mech pg_scram_mech;
+extern char *pg_fe_scram_build_secret(const char *password,
+ int iterations,
+ const char **errstr);
+
+#endif /* FE_AUTH_H */
diff --git a/contrib/libs/libpq/src/interfaces/libpq/fe-connect.c b/contrib/libs/libpq/src/interfaces/libpq/fe-connect.c
new file mode 100644
index 0000000000..a61eec7282
--- /dev/null
+++ b/contrib/libs/libpq/src/interfaces/libpq/fe-connect.c
@@ -0,0 +1,7831 @@
+/*-------------------------------------------------------------------------
+ *
+ * fe-connect.c
+ * functions related to setting up a connection to the backend
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/interfaces/libpq/fe-connect.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres_fe.h"
+
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <netdb.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "common/ip.h"
+#include "common/link-canary.h"
+#include "common/scram-common.h"
+#include "common/string.h"
+#include "fe-auth.h"
+#include "libpq-fe.h"
+#include "libpq-int.h"
+#include "mb/pg_wchar.h"
+#include "pg_config_paths.h"
+#include "port/pg_bswap.h"
+
+#ifdef WIN32
+#include "win32.h"
+#ifdef _WIN32_IE
+#undef _WIN32_IE
+#endif
+#define _WIN32_IE 0x0500
+#ifdef near
+#undef near
+#endif
+#define near
+#include <shlobj.h>
+#include <mstcpip.h>
+#else
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#endif
+
+#ifdef ENABLE_THREAD_SAFETY
+#ifdef WIN32
+#include "pthread-win32.h"
+#else
+#include <pthread.h>
+#endif
+#endif
+
+#ifdef USE_LDAP
+#ifdef WIN32
+#include <winldap.h>
+#else
+/* OpenLDAP deprecates RFC 1823, but we want standard conformance */
+#define LDAP_DEPRECATED 1
+#error #include <ldap.h>
+typedef struct timeval LDAP_TIMEVAL;
+#endif
+static int ldapServiceLookup(const char *purl, PQconninfoOption *options,
+ PQExpBuffer errorMessage);
+#endif
+
+#ifndef WIN32
+#define PGPASSFILE ".pgpass"
+#else
+#define PGPASSFILE "pgpass.conf"
+#endif
+
+/*
+ * Pre-9.0 servers will return this SQLSTATE if asked to set
+ * application_name in a startup packet. We hard-wire the value rather
+ * than looking into errcodes.h since it reflects historical behavior
+ * rather than that of the current code.
+ */
+#define ERRCODE_APPNAME_UNKNOWN "42704"
+
+/* This is part of the protocol so just define it */
+#define ERRCODE_INVALID_PASSWORD "28P01"
+/* This too */
+#define ERRCODE_CANNOT_CONNECT_NOW "57P03"
+
+/*
+ * Cope with the various platform-specific ways to spell TCP keepalive socket
+ * options. This doesn't cover Windows, which as usual does its own thing.
+ */
+#if defined(TCP_KEEPIDLE)
+/* TCP_KEEPIDLE is the name of this option on Linux and *BSD */
+#define PG_TCP_KEEPALIVE_IDLE TCP_KEEPIDLE
+#define PG_TCP_KEEPALIVE_IDLE_STR "TCP_KEEPIDLE"
+#elif defined(TCP_KEEPALIVE_THRESHOLD)
+/* TCP_KEEPALIVE_THRESHOLD is the name of this option on Solaris >= 11 */
+#define PG_TCP_KEEPALIVE_IDLE TCP_KEEPALIVE_THRESHOLD
+#define PG_TCP_KEEPALIVE_IDLE_STR "TCP_KEEPALIVE_THRESHOLD"
+#elif defined(TCP_KEEPALIVE) && defined(__darwin__)
+/* TCP_KEEPALIVE is the name of this option on macOS */
+/* Caution: Solaris has this symbol but it means something different */
+#define PG_TCP_KEEPALIVE_IDLE TCP_KEEPALIVE
+#define PG_TCP_KEEPALIVE_IDLE_STR "TCP_KEEPALIVE"
+#endif
+
+/*
+ * fall back options if they are not specified by arguments or defined
+ * by environment variables
+ */
+#define DefaultHost "localhost"
+#define DefaultOption ""
+#ifdef USE_SSL
+#define DefaultChannelBinding "prefer"
+#else
+#define DefaultChannelBinding "disable"
+#endif
+#define DefaultTargetSessionAttrs "any"
+#define DefaultLoadBalanceHosts "disable"
+#ifdef USE_SSL
+#define DefaultSSLMode "prefer"
+#define DefaultSSLCertMode "allow"
+#else
+#define DefaultSSLMode "disable"
+#define DefaultSSLCertMode "disable"
+#endif
+#ifdef ENABLE_GSS
+#error #include "fe-gssapi-common.h"
+#define DefaultGSSMode "prefer"
+#else
+#define DefaultGSSMode "disable"
+#endif
+
+/* ----------
+ * Definition of the conninfo parameters and their fallback resources.
+ *
+ * If Environment-Var and Compiled-in are specified as NULL, no
+ * fallback is available. If after all no value can be determined
+ * for an option, an error is returned.
+ *
+ * The value for the username is treated specially in conninfo_add_defaults.
+ * If the value is not obtained any other way, the username is determined
+ * by pg_fe_getauthname().
+ *
+ * The Label and Disp-Char entries are provided for applications that
+ * want to use PQconndefaults() to create a generic database connection
+ * dialog. Disp-Char is defined as follows:
+ * "" Normal input field
+ * "*" Password field - hide value
+ * "D" Debug option - don't show by default
+ *
+ * PQconninfoOptions[] is a constant static array that we use to initialize
+ * a dynamically allocated working copy. All the "val" fields in
+ * PQconninfoOptions[] *must* be NULL. In a working copy, non-null "val"
+ * fields point to malloc'd strings that should be freed when the working
+ * array is freed (see PQconninfoFree).
+ *
+ * The first part of each struct is identical to the one in libpq-fe.h,
+ * which is required since we memcpy() data between the two!
+ * ----------
+ */
+typedef struct _internalPQconninfoOption
+{
+ char *keyword; /* The keyword of the option */
+ char *envvar; /* Fallback environment variable name */
+ char *compiled; /* Fallback compiled in default value */
+ char *val; /* Option's current value, or NULL */
+ char *label; /* Label for field in connect dialog */
+ char *dispchar; /* Indicates how to display this field in a
+ * connect dialog. Values are: "" Display
+ * entered value as is "*" Password field -
+ * hide value "D" Debug option - don't show
+ * by default */
+ int dispsize; /* Field size in characters for dialog */
+ /* ---
+ * Anything above this comment must be synchronized with
+ * PQconninfoOption in libpq-fe.h, since we memcpy() data
+ * between them!
+ * ---
+ */
+ off_t connofs; /* Offset into PGconn struct, -1 if not there */
+} internalPQconninfoOption;
+
+static const internalPQconninfoOption PQconninfoOptions[] = {
+ {"service", "PGSERVICE", NULL, NULL,
+ "Database-Service", "", 20, -1},
+
+ {"user", "PGUSER", NULL, NULL,
+ "Database-User", "", 20,
+ offsetof(struct pg_conn, pguser)},
+
+ {"password", "PGPASSWORD", NULL, NULL,
+ "Database-Password", "*", 20,
+ offsetof(struct pg_conn, pgpass)},
+
+ {"passfile", "PGPASSFILE", NULL, NULL,
+ "Database-Password-File", "", 64,
+ offsetof(struct pg_conn, pgpassfile)},
+
+ {"channel_binding", "PGCHANNELBINDING", DefaultChannelBinding, NULL,
+ "Channel-Binding", "", 8, /* sizeof("require") == 8 */
+ offsetof(struct pg_conn, channel_binding)},
+
+ {"connect_timeout", "PGCONNECT_TIMEOUT", NULL, NULL,
+ "Connect-timeout", "", 10, /* strlen(INT32_MAX) == 10 */
+ offsetof(struct pg_conn, connect_timeout)},
+
+ {"dbname", "PGDATABASE", NULL, NULL,
+ "Database-Name", "", 20,
+ offsetof(struct pg_conn, dbName)},
+
+ {"host", "PGHOST", NULL, NULL,
+ "Database-Host", "", 40,
+ offsetof(struct pg_conn, pghost)},
+
+ {"hostaddr", "PGHOSTADDR", NULL, NULL,
+ "Database-Host-IP-Address", "", 45,
+ offsetof(struct pg_conn, pghostaddr)},
+
+ {"port", "PGPORT", DEF_PGPORT_STR, NULL,
+ "Database-Port", "", 6,
+ offsetof(struct pg_conn, pgport)},
+
+ {"client_encoding", "PGCLIENTENCODING", NULL, NULL,
+ "Client-Encoding", "", 10,
+ offsetof(struct pg_conn, client_encoding_initial)},
+
+ {"options", "PGOPTIONS", DefaultOption, NULL,
+ "Backend-Options", "", 40,
+ offsetof(struct pg_conn, pgoptions)},
+
+ {"application_name", "PGAPPNAME", NULL, NULL,
+ "Application-Name", "", 64,
+ offsetof(struct pg_conn, appname)},
+
+ {"fallback_application_name", NULL, NULL, NULL,
+ "Fallback-Application-Name", "", 64,
+ offsetof(struct pg_conn, fbappname)},
+
+ {"keepalives", NULL, NULL, NULL,
+ "TCP-Keepalives", "", 1, /* should be just '0' or '1' */
+ offsetof(struct pg_conn, keepalives)},
+
+ {"keepalives_idle", NULL, NULL, NULL,
+ "TCP-Keepalives-Idle", "", 10, /* strlen(INT32_MAX) == 10 */
+ offsetof(struct pg_conn, keepalives_idle)},
+
+ {"keepalives_interval", NULL, NULL, NULL,
+ "TCP-Keepalives-Interval", "", 10, /* strlen(INT32_MAX) == 10 */
+ offsetof(struct pg_conn, keepalives_interval)},
+
+ {"keepalives_count", NULL, NULL, NULL,
+ "TCP-Keepalives-Count", "", 10, /* strlen(INT32_MAX) == 10 */
+ offsetof(struct pg_conn, keepalives_count)},
+
+ {"tcp_user_timeout", NULL, NULL, NULL,
+ "TCP-User-Timeout", "", 10, /* strlen(INT32_MAX) == 10 */
+ offsetof(struct pg_conn, pgtcp_user_timeout)},
+
+ /*
+ * ssl options are allowed even without client SSL support because the
+ * client can still handle SSL modes "disable" and "allow". Other
+ * parameters have no effect on non-SSL connections, so there is no reason
+ * to exclude them since none of them are mandatory.
+ */
+ {"sslmode", "PGSSLMODE", DefaultSSLMode, NULL,
+ "SSL-Mode", "", 12, /* sizeof("verify-full") == 12 */
+ offsetof(struct pg_conn, sslmode)},
+
+ {"sslcompression", "PGSSLCOMPRESSION", "0", NULL,
+ "SSL-Compression", "", 1,
+ offsetof(struct pg_conn, sslcompression)},
+
+ {"sslcert", "PGSSLCERT", NULL, NULL,
+ "SSL-Client-Cert", "", 64,
+ offsetof(struct pg_conn, sslcert)},
+
+ {"sslkey", "PGSSLKEY", NULL, NULL,
+ "SSL-Client-Key", "", 64,
+ offsetof(struct pg_conn, sslkey)},
+
+ {"sslcertmode", "PGSSLCERTMODE", NULL, NULL,
+ "SSL-Client-Cert-Mode", "", 8, /* sizeof("disable") == 8 */
+ offsetof(struct pg_conn, sslcertmode)},
+
+ {"sslpassword", NULL, NULL, NULL,
+ "SSL-Client-Key-Password", "*", 20,
+ offsetof(struct pg_conn, sslpassword)},
+
+ {"sslrootcert", "PGSSLROOTCERT", NULL, NULL,
+ "SSL-Root-Certificate", "", 64,
+ offsetof(struct pg_conn, sslrootcert)},
+
+ {"sslcrl", "PGSSLCRL", NULL, NULL,
+ "SSL-Revocation-List", "", 64,
+ offsetof(struct pg_conn, sslcrl)},
+
+ {"sslcrldir", "PGSSLCRLDIR", NULL, NULL,
+ "SSL-Revocation-List-Dir", "", 64,
+ offsetof(struct pg_conn, sslcrldir)},
+
+ {"sslsni", "PGSSLSNI", "1", NULL,
+ "SSL-SNI", "", 1,
+ offsetof(struct pg_conn, sslsni)},
+
+ {"requirepeer", "PGREQUIREPEER", NULL, NULL,
+ "Require-Peer", "", 10,
+ offsetof(struct pg_conn, requirepeer)},
+
+ {"require_auth", "PGREQUIREAUTH", NULL, NULL,
+ "Require-Auth", "", 14, /* sizeof("scram-sha-256") == 14 */
+ offsetof(struct pg_conn, require_auth)},
+
+ {"ssl_min_protocol_version", "PGSSLMINPROTOCOLVERSION", "TLSv1.2", NULL,
+ "SSL-Minimum-Protocol-Version", "", 8, /* sizeof("TLSv1.x") == 8 */
+ offsetof(struct pg_conn, ssl_min_protocol_version)},
+
+ {"ssl_max_protocol_version", "PGSSLMAXPROTOCOLVERSION", NULL, NULL,
+ "SSL-Maximum-Protocol-Version", "", 8, /* sizeof("TLSv1.x") == 8 */
+ offsetof(struct pg_conn, ssl_max_protocol_version)},
+
+ /*
+ * As with SSL, all GSS options are exposed even in builds that don't have
+ * support.
+ */
+ {"gssencmode", "PGGSSENCMODE", DefaultGSSMode, NULL,
+ "GSSENC-Mode", "", 8, /* sizeof("disable") == 8 */
+ offsetof(struct pg_conn, gssencmode)},
+
+ /* Kerberos and GSSAPI authentication support specifying the service name */
+ {"krbsrvname", "PGKRBSRVNAME", PG_KRB_SRVNAM, NULL,
+ "Kerberos-service-name", "", 20,
+ offsetof(struct pg_conn, krbsrvname)},
+
+ {"gsslib", "PGGSSLIB", NULL, NULL,
+ "GSS-library", "", 7, /* sizeof("gssapi") == 7 */
+ offsetof(struct pg_conn, gsslib)},
+
+ {"gssdelegation", "PGGSSDELEGATION", "0", NULL,
+ "GSS-delegation", "", 1,
+ offsetof(struct pg_conn, gssdelegation)},
+
+ {"replication", NULL, NULL, NULL,
+ "Replication", "D", 5,
+ offsetof(struct pg_conn, replication)},
+
+ {"target_session_attrs", "PGTARGETSESSIONATTRS",
+ DefaultTargetSessionAttrs, NULL,
+ "Target-Session-Attrs", "", 15, /* sizeof("prefer-standby") = 15 */
+ offsetof(struct pg_conn, target_session_attrs)},
+
+ {"load_balance_hosts", "PGLOADBALANCEHOSTS",
+ DefaultLoadBalanceHosts, NULL,
+ "Load-Balance-Hosts", "", 8, /* sizeof("disable") = 8 */
+ offsetof(struct pg_conn, load_balance_hosts)},
+
+ /* Terminating entry --- MUST BE LAST */
+ {NULL, NULL, NULL, NULL,
+ NULL, NULL, 0}
+};
+
+static const PQEnvironmentOption EnvironmentOptions[] =
+{
+ /* common user-interface settings */
+ {
+ "PGDATESTYLE", "datestyle"
+ },
+ {
+ "PGTZ", "timezone"
+ },
+ /* internal performance-related settings */
+ {
+ "PGGEQO", "geqo"
+ },
+ {
+ NULL, NULL
+ }
+};
+
+/* The connection URI must start with either of the following designators: */
+static const char uri_designator[] = "postgresql://";
+static const char short_uri_designator[] = "postgres://";
+
+static bool connectOptions1(PGconn *conn, const char *conninfo);
+static bool connectOptions2(PGconn *conn);
+static int connectDBStart(PGconn *conn);
+static int connectDBComplete(PGconn *conn);
+static PGPing internal_ping(PGconn *conn);
+static PGconn *makeEmptyPGconn(void);
+static void pqFreeCommandQueue(PGcmdQueueEntry *queue);
+static bool fillPGconn(PGconn *conn, PQconninfoOption *connOptions);
+static void freePGconn(PGconn *conn);
+static void closePGconn(PGconn *conn);
+static void release_conn_addrinfo(PGconn *conn);
+static int store_conn_addrinfo(PGconn *conn, struct addrinfo *addrlist);
+static void sendTerminateConn(PGconn *conn);
+static PQconninfoOption *conninfo_init(PQExpBuffer errorMessage);
+static PQconninfoOption *parse_connection_string(const char *connstr,
+ PQExpBuffer errorMessage, bool use_defaults);
+static int uri_prefix_length(const char *connstr);
+static bool recognized_connection_string(const char *connstr);
+static PQconninfoOption *conninfo_parse(const char *conninfo,
+ PQExpBuffer errorMessage, bool use_defaults);
+static PQconninfoOption *conninfo_array_parse(const char *const *keywords,
+ const char *const *values, PQExpBuffer errorMessage,
+ bool use_defaults, int expand_dbname);
+static bool conninfo_add_defaults(PQconninfoOption *options,
+ PQExpBuffer errorMessage);
+static PQconninfoOption *conninfo_uri_parse(const char *uri,
+ PQExpBuffer errorMessage, bool use_defaults);
+static bool conninfo_uri_parse_options(PQconninfoOption *options,
+ const char *uri, PQExpBuffer errorMessage);
+static bool conninfo_uri_parse_params(char *params,
+ PQconninfoOption *connOptions,
+ PQExpBuffer errorMessage);
+static char *conninfo_uri_decode(const char *str, PQExpBuffer errorMessage);
+static bool get_hexdigit(char digit, int *value);
+static const char *conninfo_getval(PQconninfoOption *connOptions,
+ const char *keyword);
+static PQconninfoOption *conninfo_storeval(PQconninfoOption *connOptions,
+ const char *keyword, const char *value,
+ PQExpBuffer errorMessage, bool ignoreMissing, bool uri_decode);
+static PQconninfoOption *conninfo_find(PQconninfoOption *connOptions,
+ const char *keyword);
+static void defaultNoticeReceiver(void *arg, const PGresult *res);
+static void defaultNoticeProcessor(void *arg, const char *message);
+static int parseServiceInfo(PQconninfoOption *options,
+ PQExpBuffer errorMessage);
+static int parseServiceFile(const char *serviceFile,
+ const char *service,
+ PQconninfoOption *options,
+ PQExpBuffer errorMessage,
+ bool *group_found);
+static char *pwdfMatchesString(char *buf, const char *token);
+static char *passwordFromFile(const char *hostname, const char *port, const char *dbname,
+ const char *username, const char *pgpassfile);
+static void pgpassfileWarning(PGconn *conn);
+static void default_threadlock(int acquire);
+static bool sslVerifyProtocolVersion(const char *version);
+static bool sslVerifyProtocolRange(const char *min, const char *max);
+static bool parse_int_param(const char *value, int *result, PGconn *conn,
+ const char *context);
+
+
+/* global variable because fe-auth.c needs to access it */
+pgthreadlock_t pg_g_threadlock = default_threadlock;
+
+
+/*
+ * pqDropConnection
+ *
+ * Close any physical connection to the server, and reset associated
+ * state inside the connection object. We don't release state that
+ * would be needed to reconnect, though, nor local state that might still
+ * be useful later.
+ *
+ * We can always flush the output buffer, since there's no longer any hope
+ * of sending that data. However, unprocessed input data might still be
+ * valuable, so the caller must tell us whether to flush that or not.
+ */
+void
+pqDropConnection(PGconn *conn, bool flushInput)
+{
+ /* Drop any SSL state */
+ pqsecure_close(conn);
+
+ /* Close the socket itself */
+ if (conn->sock != PGINVALID_SOCKET)
+ closesocket(conn->sock);
+ conn->sock = PGINVALID_SOCKET;
+
+ /* Optionally discard any unread data */
+ if (flushInput)
+ conn->inStart = conn->inCursor = conn->inEnd = 0;
+
+ /* Always discard any unsent data */
+ conn->outCount = 0;
+
+ /* Likewise, discard any pending pipelined commands */
+ pqFreeCommandQueue(conn->cmd_queue_head);
+ conn->cmd_queue_head = conn->cmd_queue_tail = NULL;
+ pqFreeCommandQueue(conn->cmd_queue_recycle);
+ conn->cmd_queue_recycle = NULL;
+
+ /* Free authentication/encryption state */
+#ifdef ENABLE_GSS
+ {
+ OM_uint32 min_s;
+
+ if (conn->gcred != GSS_C_NO_CREDENTIAL)
+ {
+ gss_release_cred(&min_s, &conn->gcred);
+ conn->gcred = GSS_C_NO_CREDENTIAL;
+ }
+ if (conn->gctx)
+ gss_delete_sec_context(&min_s, &conn->gctx, GSS_C_NO_BUFFER);
+ if (conn->gtarg_nam)
+ gss_release_name(&min_s, &conn->gtarg_nam);
+ if (conn->gss_SendBuffer)
+ {
+ free(conn->gss_SendBuffer);
+ conn->gss_SendBuffer = NULL;
+ }
+ if (conn->gss_RecvBuffer)
+ {
+ free(conn->gss_RecvBuffer);
+ conn->gss_RecvBuffer = NULL;
+ }
+ if (conn->gss_ResultBuffer)
+ {
+ free(conn->gss_ResultBuffer);
+ conn->gss_ResultBuffer = NULL;
+ }
+ conn->gssenc = false;
+ }
+#endif
+#ifdef ENABLE_SSPI
+ if (conn->sspitarget)
+ {
+ free(conn->sspitarget);
+ conn->sspitarget = NULL;
+ }
+ if (conn->sspicred)
+ {
+ FreeCredentialsHandle(conn->sspicred);
+ free(conn->sspicred);
+ conn->sspicred = NULL;
+ }
+ if (conn->sspictx)
+ {
+ DeleteSecurityContext(conn->sspictx);
+ free(conn->sspictx);
+ conn->sspictx = NULL;
+ }
+ conn->usesspi = 0;
+#endif
+ if (conn->sasl_state)
+ {
+ conn->sasl->free(conn->sasl_state);
+ conn->sasl_state = NULL;
+ }
+}
+
+/*
+ * pqFreeCommandQueue
+ * Free all the entries of PGcmdQueueEntry queue passed.
+ */
+static void
+pqFreeCommandQueue(PGcmdQueueEntry *queue)
+{
+ while (queue != NULL)
+ {
+ PGcmdQueueEntry *cur = queue;
+
+ queue = cur->next;
+ free(cur->query);
+ free(cur);
+ }
+}
+
+/*
+ * pqDropServerData
+ *
+ * Clear all connection state data that was received from (or deduced about)
+ * the server. This is essential to do between connection attempts to
+ * different servers, else we may incorrectly hold over some data from the
+ * old server.
+ *
+ * It would be better to merge this into pqDropConnection, perhaps, but
+ * right now we cannot because that function is called immediately on
+ * detection of connection loss (cf. pqReadData, for instance). This data
+ * should be kept until we are actually starting a new connection.
+ */
+static void
+pqDropServerData(PGconn *conn)
+{
+ PGnotify *notify;
+ pgParameterStatus *pstatus;
+
+ /* Forget pending notifies */
+ notify = conn->notifyHead;
+ while (notify != NULL)
+ {
+ PGnotify *prev = notify;
+
+ notify = notify->next;
+ free(prev);
+ }
+ conn->notifyHead = conn->notifyTail = NULL;
+
+ /* Reset ParameterStatus data, as well as variables deduced from it */
+ pstatus = conn->pstatus;
+ while (pstatus != NULL)
+ {
+ pgParameterStatus *prev = pstatus;
+
+ pstatus = pstatus->next;
+ free(prev);
+ }
+ conn->pstatus = NULL;
+ conn->client_encoding = PG_SQL_ASCII;
+ conn->std_strings = false;
+ conn->default_transaction_read_only = PG_BOOL_UNKNOWN;
+ conn->in_hot_standby = PG_BOOL_UNKNOWN;
+ conn->scram_sha_256_iterations = SCRAM_SHA_256_DEFAULT_ITERATIONS;
+ conn->sversion = 0;
+
+ /* Drop large-object lookup data */
+ free(conn->lobjfuncs);
+ conn->lobjfuncs = NULL;
+
+ /* Reset assorted other per-connection state */
+ conn->last_sqlstate[0] = '\0';
+ conn->auth_req_received = false;
+ conn->client_finished_auth = false;
+ conn->password_needed = false;
+ conn->gssapi_used = false;
+ conn->write_failed = false;
+ free(conn->write_err_msg);
+ conn->write_err_msg = NULL;
+ conn->be_pid = 0;
+ conn->be_key = 0;
+}
+
+
+/*
+ * Connecting to a Database
+ *
+ * There are now six different ways a user of this API can connect to the
+ * database. Two are not recommended for use in new code, because of their
+ * lack of extensibility with respect to the passing of options to the
+ * backend. These are PQsetdb and PQsetdbLogin (the former now being a macro
+ * to the latter).
+ *
+ * If it is desired to connect in a synchronous (blocking) manner, use the
+ * function PQconnectdb or PQconnectdbParams. The former accepts a string of
+ * option = value pairs (or a URI) which must be parsed; the latter takes two
+ * NULL terminated arrays instead.
+ *
+ * To connect in an asynchronous (non-blocking) manner, use the functions
+ * PQconnectStart or PQconnectStartParams (which differ in the same way as
+ * PQconnectdb and PQconnectdbParams) and PQconnectPoll.
+ *
+ * Internally, the static functions connectDBStart, connectDBComplete
+ * are part of the connection procedure.
+ */
+
+/*
+ * PQconnectdbParams
+ *
+ * establishes a connection to a postgres backend through the postmaster
+ * using connection information in two arrays.
+ *
+ * The keywords array is defined as
+ *
+ * const char *params[] = {"option1", "option2", NULL}
+ *
+ * The values array is defined as
+ *
+ * const char *values[] = {"value1", "value2", NULL}
+ *
+ * Returns a PGconn* which is needed for all subsequent libpq calls, or NULL
+ * if a memory allocation failed.
+ * If the status field of the connection returned is CONNECTION_BAD,
+ * then some fields may be null'ed out instead of having valid values.
+ *
+ * You should call PQfinish (if conn is not NULL) regardless of whether this
+ * call succeeded.
+ */
+PGconn *
+PQconnectdbParams(const char *const *keywords,
+ const char *const *values,
+ int expand_dbname)
+{
+ PGconn *conn = PQconnectStartParams(keywords, values, expand_dbname);
+
+ if (conn && conn->status != CONNECTION_BAD)
+ (void) connectDBComplete(conn);
+
+ return conn;
+}
+
+/*
+ * PQpingParams
+ *
+ * check server status, accepting parameters identical to PQconnectdbParams
+ */
+PGPing
+PQpingParams(const char *const *keywords,
+ const char *const *values,
+ int expand_dbname)
+{
+ PGconn *conn = PQconnectStartParams(keywords, values, expand_dbname);
+ PGPing ret;
+
+ ret = internal_ping(conn);
+ PQfinish(conn);
+
+ return ret;
+}
+
+/*
+ * PQconnectdb
+ *
+ * establishes a connection to a postgres backend through the postmaster
+ * using connection information in a string.
+ *
+ * The conninfo string is either a whitespace-separated list of
+ *
+ * option = value
+ *
+ * definitions or a URI (refer to the documentation for details.) Value
+ * might be a single value containing no whitespaces or a single quoted
+ * string. If a single quote should appear anywhere in the value, it must be
+ * escaped with a backslash like \'
+ *
+ * Returns a PGconn* which is needed for all subsequent libpq calls, or NULL
+ * if a memory allocation failed.
+ * If the status field of the connection returned is CONNECTION_BAD,
+ * then some fields may be null'ed out instead of having valid values.
+ *
+ * You should call PQfinish (if conn is not NULL) regardless of whether this
+ * call succeeded.
+ */
+PGconn *
+PQconnectdb(const char *conninfo)
+{
+ PGconn *conn = PQconnectStart(conninfo);
+
+ if (conn && conn->status != CONNECTION_BAD)
+ (void) connectDBComplete(conn);
+
+ return conn;
+}
+
+/*
+ * PQping
+ *
+ * check server status, accepting parameters identical to PQconnectdb
+ */
+PGPing
+PQping(const char *conninfo)
+{
+ PGconn *conn = PQconnectStart(conninfo);
+ PGPing ret;
+
+ ret = internal_ping(conn);
+ PQfinish(conn);
+
+ return ret;
+}
+
+/*
+ * PQconnectStartParams
+ *
+ * Begins the establishment of a connection to a postgres backend through the
+ * postmaster using connection information in a struct.
+ *
+ * See comment for PQconnectdbParams for the definition of the string format.
+ *
+ * Returns a PGconn*. If NULL is returned, a malloc error has occurred, and
+ * you should not attempt to proceed with this connection. If the status
+ * field of the connection returned is CONNECTION_BAD, an error has
+ * occurred. In this case you should call PQfinish on the result, (perhaps
+ * inspecting the error message first). Other fields of the structure may not
+ * be valid if that occurs. If the status field is not CONNECTION_BAD, then
+ * this stage has succeeded - call PQconnectPoll, using select(2) to see when
+ * this is necessary.
+ *
+ * See PQconnectPoll for more info.
+ */
+PGconn *
+PQconnectStartParams(const char *const *keywords,
+ const char *const *values,
+ int expand_dbname)
+{
+ PGconn *conn;
+ PQconninfoOption *connOptions;
+
+ /*
+ * Allocate memory for the conn structure. Note that we also expect this
+ * to initialize conn->errorMessage to empty. All subsequent steps during
+ * connection initialization will only append to that buffer.
+ */
+ conn = makeEmptyPGconn();
+ if (conn == NULL)
+ return NULL;
+
+ /*
+ * Parse the conninfo arrays
+ */
+ connOptions = conninfo_array_parse(keywords, values,
+ &conn->errorMessage,
+ true, expand_dbname);
+ if (connOptions == NULL)
+ {
+ conn->status = CONNECTION_BAD;
+ /* errorMessage is already set */
+ return conn;
+ }
+
+ /*
+ * Move option values into conn structure
+ */
+ if (!fillPGconn(conn, connOptions))
+ {
+ PQconninfoFree(connOptions);
+ return conn;
+ }
+
+ /*
+ * Free the option info - all is in conn now
+ */
+ PQconninfoFree(connOptions);
+
+ /*
+ * Compute derived options
+ */
+ if (!connectOptions2(conn))
+ return conn;
+
+ /*
+ * Connect to the database
+ */
+ if (!connectDBStart(conn))
+ {
+ /* Just in case we failed to set it in connectDBStart */
+ conn->status = CONNECTION_BAD;
+ }
+
+ return conn;
+}
+
+/*
+ * PQconnectStart
+ *
+ * Begins the establishment of a connection to a postgres backend through the
+ * postmaster using connection information in a string.
+ *
+ * See comment for PQconnectdb for the definition of the string format.
+ *
+ * Returns a PGconn*. If NULL is returned, a malloc error has occurred, and
+ * you should not attempt to proceed with this connection. If the status
+ * field of the connection returned is CONNECTION_BAD, an error has
+ * occurred. In this case you should call PQfinish on the result, (perhaps
+ * inspecting the error message first). Other fields of the structure may not
+ * be valid if that occurs. If the status field is not CONNECTION_BAD, then
+ * this stage has succeeded - call PQconnectPoll, using select(2) to see when
+ * this is necessary.
+ *
+ * See PQconnectPoll for more info.
+ */
+PGconn *
+PQconnectStart(const char *conninfo)
+{
+ PGconn *conn;
+
+ /*
+ * Allocate memory for the conn structure. Note that we also expect this
+ * to initialize conn->errorMessage to empty. All subsequent steps during
+ * connection initialization will only append to that buffer.
+ */
+ conn = makeEmptyPGconn();
+ if (conn == NULL)
+ return NULL;
+
+ /*
+ * Parse the conninfo string
+ */
+ if (!connectOptions1(conn, conninfo))
+ return conn;
+
+ /*
+ * Compute derived options
+ */
+ if (!connectOptions2(conn))
+ return conn;
+
+ /*
+ * Connect to the database
+ */
+ if (!connectDBStart(conn))
+ {
+ /* Just in case we failed to set it in connectDBStart */
+ conn->status = CONNECTION_BAD;
+ }
+
+ return conn;
+}
+
+/*
+ * Move option values into conn structure
+ *
+ * Don't put anything cute here --- intelligence should be in
+ * connectOptions2 ...
+ *
+ * Returns true on success. On failure, returns false and sets error message.
+ */
+static bool
+fillPGconn(PGconn *conn, PQconninfoOption *connOptions)
+{
+ const internalPQconninfoOption *option;
+
+ for (option = PQconninfoOptions; option->keyword; option++)
+ {
+ if (option->connofs >= 0)
+ {
+ const char *tmp = conninfo_getval(connOptions, option->keyword);
+
+ if (tmp)
+ {
+ char **connmember = (char **) ((char *) conn + option->connofs);
+
+ free(*connmember);
+ *connmember = strdup(tmp);
+ if (*connmember == NULL)
+ {
+ libpq_append_conn_error(conn, "out of memory");
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+/*
+ * connectOptions1
+ *
+ * Internal subroutine to set up connection parameters given an already-
+ * created PGconn and a conninfo string. Derived settings should be
+ * processed by calling connectOptions2 next. (We split them because
+ * PQsetdbLogin overrides defaults in between.)
+ *
+ * Returns true if OK, false if trouble (in which case errorMessage is set
+ * and so is conn->status).
+ */
+static bool
+connectOptions1(PGconn *conn, const char *conninfo)
+{
+ PQconninfoOption *connOptions;
+
+ /*
+ * Parse the conninfo string
+ */
+ connOptions = parse_connection_string(conninfo, &conn->errorMessage, true);
+ if (connOptions == NULL)
+ {
+ conn->status = CONNECTION_BAD;
+ /* errorMessage is already set */
+ return false;
+ }
+
+ /*
+ * Move option values into conn structure
+ */
+ if (!fillPGconn(conn, connOptions))
+ {
+ conn->status = CONNECTION_BAD;
+ PQconninfoFree(connOptions);
+ return false;
+ }
+
+ /*
+ * Free the option info - all is in conn now
+ */
+ PQconninfoFree(connOptions);
+
+ return true;
+}
+
+/*
+ * Count the number of elements in a simple comma-separated list.
+ */
+static int
+count_comma_separated_elems(const char *input)
+{
+ int n;
+
+ n = 1;
+ for (; *input != '\0'; input++)
+ {
+ if (*input == ',')
+ n++;
+ }
+
+ return n;
+}
+
+/*
+ * Parse a simple comma-separated list.
+ *
+ * On each call, returns a malloc'd copy of the next element, and sets *more
+ * to indicate whether there are any more elements in the list after this,
+ * and updates *startptr to point to the next element, if any.
+ *
+ * On out of memory, returns NULL.
+ */
+static char *
+parse_comma_separated_list(char **startptr, bool *more)
+{
+ char *p;
+ char *s = *startptr;
+ char *e;
+ int len;
+
+ /*
+ * Search for the end of the current element; a comma or end-of-string
+ * acts as a terminator.
+ */
+ e = s;
+ while (*e != '\0' && *e != ',')
+ ++e;
+ *more = (*e == ',');
+
+ len = e - s;
+ p = (char *) malloc(sizeof(char) * (len + 1));
+ if (p)
+ {
+ memcpy(p, s, len);
+ p[len] = '\0';
+ }
+ *startptr = e + 1;
+
+ return p;
+}
+
+/*
+ * Initializes the prng_state field of the connection. We want something
+ * unpredictable, so if possible, use high-quality random bits for the
+ * seed. Otherwise, fall back to a seed based on the connection address,
+ * timestamp and PID.
+ */
+static void
+libpq_prng_init(PGconn *conn)
+{
+ uint64 rseed;
+ struct timeval tval = {0};
+
+ if (pg_prng_strong_seed(&conn->prng_state))
+ return;
+
+ gettimeofday(&tval, NULL);
+
+ rseed = ((uintptr_t) conn) ^
+ ((uint64) getpid()) ^
+ ((uint64) tval.tv_usec) ^
+ ((uint64) tval.tv_sec);
+
+ pg_prng_seed(&conn->prng_state, rseed);
+}
+
+/*
+ * connectOptions2
+ *
+ * Compute derived connection options after absorbing all user-supplied info.
+ *
+ * Returns true if OK, false if trouble (in which case errorMessage is set
+ * and so is conn->status).
+ */
+static bool
+connectOptions2(PGconn *conn)
+{
+ int i;
+
+ /*
+ * Allocate memory for details about each host to which we might possibly
+ * try to connect. For that, count the number of elements in the hostaddr
+ * or host options. If neither is given, assume one host.
+ */
+ conn->whichhost = 0;
+ if (conn->pghostaddr && conn->pghostaddr[0] != '\0')
+ conn->nconnhost = count_comma_separated_elems(conn->pghostaddr);
+ else if (conn->pghost && conn->pghost[0] != '\0')
+ conn->nconnhost = count_comma_separated_elems(conn->pghost);
+ else
+ conn->nconnhost = 1;
+ conn->connhost = (pg_conn_host *)
+ calloc(conn->nconnhost, sizeof(pg_conn_host));
+ if (conn->connhost == NULL)
+ goto oom_error;
+
+ /*
+ * We now have one pg_conn_host structure per possible host. Fill in the
+ * host and hostaddr fields for each, by splitting the parameter strings.
+ */
+ if (conn->pghostaddr != NULL && conn->pghostaddr[0] != '\0')
+ {
+ char *s = conn->pghostaddr;
+ bool more = true;
+
+ for (i = 0; i < conn->nconnhost && more; i++)
+ {
+ conn->connhost[i].hostaddr = parse_comma_separated_list(&s, &more);
+ if (conn->connhost[i].hostaddr == NULL)
+ goto oom_error;
+ }
+
+ /*
+ * If hostaddr was given, the array was allocated according to the
+ * number of elements in the hostaddr list, so it really should be the
+ * right size.
+ */
+ Assert(!more);
+ Assert(i == conn->nconnhost);
+ }
+
+ if (conn->pghost != NULL && conn->pghost[0] != '\0')
+ {
+ char *s = conn->pghost;
+ bool more = true;
+
+ for (i = 0; i < conn->nconnhost && more; i++)
+ {
+ conn->connhost[i].host = parse_comma_separated_list(&s, &more);
+ if (conn->connhost[i].host == NULL)
+ goto oom_error;
+ }
+
+ /* Check for wrong number of host items. */
+ if (more || i != conn->nconnhost)
+ {
+ conn->status = CONNECTION_BAD;
+ libpq_append_conn_error(conn, "could not match %d host names to %d hostaddr values",
+ count_comma_separated_elems(conn->pghost), conn->nconnhost);
+ return false;
+ }
+ }
+
+ /*
+ * Now, for each host slot, identify the type of address spec, and fill in
+ * the default address if nothing was given.
+ */
+ for (i = 0; i < conn->nconnhost; i++)
+ {
+ pg_conn_host *ch = &conn->connhost[i];
+
+ if (ch->hostaddr != NULL && ch->hostaddr[0] != '\0')
+ ch->type = CHT_HOST_ADDRESS;
+ else if (ch->host != NULL && ch->host[0] != '\0')
+ {
+ ch->type = CHT_HOST_NAME;
+ if (is_unixsock_path(ch->host))
+ ch->type = CHT_UNIX_SOCKET;
+ }
+ else
+ {
+ free(ch->host);
+
+ /*
+ * This bit selects the default host location. If you change
+ * this, see also pg_regress.
+ */
+ if (DEFAULT_PGSOCKET_DIR[0])
+ {
+ ch->host = strdup(DEFAULT_PGSOCKET_DIR);
+ ch->type = CHT_UNIX_SOCKET;
+ }
+ else
+ {
+ ch->host = strdup(DefaultHost);
+ ch->type = CHT_HOST_NAME;
+ }
+ if (ch->host == NULL)
+ goto oom_error;
+ }
+ }
+
+ /*
+ * Next, work out the port number corresponding to each host name.
+ *
+ * Note: unlike the above for host names, this could leave the port fields
+ * as null or empty strings. We will substitute DEF_PGPORT whenever we
+ * read such a port field.
+ */
+ if (conn->pgport != NULL && conn->pgport[0] != '\0')
+ {
+ char *s = conn->pgport;
+ bool more = true;
+
+ for (i = 0; i < conn->nconnhost && more; i++)
+ {
+ conn->connhost[i].port = parse_comma_separated_list(&s, &more);
+ if (conn->connhost[i].port == NULL)
+ goto oom_error;
+ }
+
+ /*
+ * If exactly one port was given, use it for every host. Otherwise,
+ * there must be exactly as many ports as there were hosts.
+ */
+ if (i == 1 && !more)
+ {
+ for (i = 1; i < conn->nconnhost; i++)
+ {
+ conn->connhost[i].port = strdup(conn->connhost[0].port);
+ if (conn->connhost[i].port == NULL)
+ goto oom_error;
+ }
+ }
+ else if (more || i != conn->nconnhost)
+ {
+ conn->status = CONNECTION_BAD;
+ libpq_append_conn_error(conn, "could not match %d port numbers to %d hosts",
+ count_comma_separated_elems(conn->pgport), conn->nconnhost);
+ return false;
+ }
+ }
+
+ /*
+ * If user name was not given, fetch it. (Most likely, the fetch will
+ * fail, since the only way we get here is if pg_fe_getauthname() failed
+ * during conninfo_add_defaults(). But now we want an error message.)
+ */
+ if (conn->pguser == NULL || conn->pguser[0] == '\0')
+ {
+ free(conn->pguser);
+ conn->pguser = pg_fe_getauthname(&conn->errorMessage);
+ if (!conn->pguser)
+ {
+ conn->status = CONNECTION_BAD;
+ return false;
+ }
+ }
+
+ /*
+ * If database name was not given, default it to equal user name
+ */
+ if (conn->dbName == NULL || conn->dbName[0] == '\0')
+ {
+ free(conn->dbName);
+ conn->dbName = strdup(conn->pguser);
+ if (!conn->dbName)
+ goto oom_error;
+ }
+
+ /*
+ * If password was not given, try to look it up in password file. Note
+ * that the result might be different for each host/port pair.
+ */
+ if (conn->pgpass == NULL || conn->pgpass[0] == '\0')
+ {
+ /* If password file wasn't specified, use ~/PGPASSFILE */
+ if (conn->pgpassfile == NULL || conn->pgpassfile[0] == '\0')
+ {
+ char homedir[MAXPGPATH];
+
+ if (pqGetHomeDirectory(homedir, sizeof(homedir)))
+ {
+ free(conn->pgpassfile);
+ conn->pgpassfile = malloc(MAXPGPATH);
+ if (!conn->pgpassfile)
+ goto oom_error;
+ snprintf(conn->pgpassfile, MAXPGPATH, "%s/%s",
+ homedir, PGPASSFILE);
+ }
+ }
+
+ if (conn->pgpassfile != NULL && conn->pgpassfile[0] != '\0')
+ {
+ for (i = 0; i < conn->nconnhost; i++)
+ {
+ /*
+ * Try to get a password for this host from file. We use host
+ * for the hostname search key if given, else hostaddr (at
+ * least one of them is guaranteed nonempty by now).
+ */
+ const char *pwhost = conn->connhost[i].host;
+
+ if (pwhost == NULL || pwhost[0] == '\0')
+ pwhost = conn->connhost[i].hostaddr;
+
+ conn->connhost[i].password =
+ passwordFromFile(pwhost,
+ conn->connhost[i].port,
+ conn->dbName,
+ conn->pguser,
+ conn->pgpassfile);
+ }
+ }
+ }
+
+ /*
+ * parse and validate require_auth option
+ */
+ if (conn->require_auth && conn->require_auth[0])
+ {
+ char *s = conn->require_auth;
+ bool first,
+ more;
+ bool negated = false;
+
+ /*
+ * By default, start from an empty set of allowed options and add to
+ * it.
+ */
+ conn->auth_required = true;
+ conn->allowed_auth_methods = 0;
+
+ for (first = true, more = true; more; first = false)
+ {
+ char *method,
+ *part;
+ uint32 bits;
+
+ part = parse_comma_separated_list(&s, &more);
+ if (part == NULL)
+ goto oom_error;
+
+ /*
+ * Check for negation, e.g. '!password'. If one element is
+ * negated, they all have to be.
+ */
+ method = part;
+ if (*method == '!')
+ {
+ if (first)
+ {
+ /*
+ * Switch to a permissive set of allowed options, and
+ * subtract from it.
+ */
+ conn->auth_required = false;
+ conn->allowed_auth_methods = -1;
+ }
+ else if (!negated)
+ {
+ conn->status = CONNECTION_BAD;
+ libpq_append_conn_error(conn, "negative require_auth method \"%s\" cannot be mixed with non-negative methods",
+ method);
+
+ free(part);
+ return false;
+ }
+
+ negated = true;
+ method++;
+ }
+ else if (negated)
+ {
+ conn->status = CONNECTION_BAD;
+ libpq_append_conn_error(conn, "require_auth method \"%s\" cannot be mixed with negative methods",
+ method);
+
+ free(part);
+ return false;
+ }
+
+ if (strcmp(method, "password") == 0)
+ {
+ bits = (1 << AUTH_REQ_PASSWORD);
+ }
+ else if (strcmp(method, "md5") == 0)
+ {
+ bits = (1 << AUTH_REQ_MD5);
+ }
+ else if (strcmp(method, "gss") == 0)
+ {
+ bits = (1 << AUTH_REQ_GSS);
+ bits |= (1 << AUTH_REQ_GSS_CONT);
+ }
+ else if (strcmp(method, "sspi") == 0)
+ {
+ bits = (1 << AUTH_REQ_SSPI);
+ bits |= (1 << AUTH_REQ_GSS_CONT);
+ }
+ else if (strcmp(method, "scram-sha-256") == 0)
+ {
+ /* This currently assumes that SCRAM is the only SASL method. */
+ bits = (1 << AUTH_REQ_SASL);
+ bits |= (1 << AUTH_REQ_SASL_CONT);
+ bits |= (1 << AUTH_REQ_SASL_FIN);
+ }
+ else if (strcmp(method, "none") == 0)
+ {
+ /*
+ * Special case: let the user explicitly allow (or disallow)
+ * connections where the server does not send an explicit
+ * authentication challenge, such as "trust" and "cert" auth.
+ */
+ if (negated) /* "!none" */
+ {
+ if (conn->auth_required)
+ goto duplicate;
+
+ conn->auth_required = true;
+ }
+ else /* "none" */
+ {
+ if (!conn->auth_required)
+ goto duplicate;
+
+ conn->auth_required = false;
+ }
+
+ free(part);
+ continue; /* avoid the bitmask manipulation below */
+ }
+ else
+ {
+ conn->status = CONNECTION_BAD;
+ libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
+ "require_auth", method);
+
+ free(part);
+ return false;
+ }
+
+ /* Update the bitmask. */
+ if (negated)
+ {
+ if ((conn->allowed_auth_methods & bits) == 0)
+ goto duplicate;
+
+ conn->allowed_auth_methods &= ~bits;
+ }
+ else
+ {
+ if ((conn->allowed_auth_methods & bits) == bits)
+ goto duplicate;
+
+ conn->allowed_auth_methods |= bits;
+ }
+
+ free(part);
+ continue;
+
+ duplicate:
+
+ /*
+ * A duplicated method probably indicates a typo in a setting
+ * where typos are extremely risky.
+ */
+ conn->status = CONNECTION_BAD;
+ libpq_append_conn_error(conn, "require_auth method \"%s\" is specified more than once",
+ part);
+
+ free(part);
+ return false;
+ }
+ }
+
+ /*
+ * validate channel_binding option
+ */
+ if (conn->channel_binding)
+ {
+ if (strcmp(conn->channel_binding, "disable") != 0
+ && strcmp(conn->channel_binding, "prefer") != 0
+ && strcmp(conn->channel_binding, "require") != 0)
+ {
+ conn->status = CONNECTION_BAD;
+ libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
+ "channel_binding", conn->channel_binding);
+ return false;
+ }
+ }
+ else
+ {
+ conn->channel_binding = strdup(DefaultChannelBinding);
+ if (!conn->channel_binding)
+ goto oom_error;
+ }
+
+#ifndef USE_SSL
+
+ /*
+ * sslrootcert=system is not supported. Since setting this changes the
+ * default sslmode, check this _before_ we validate sslmode, to avoid
+ * confusing the user with errors for an option they may not have set.
+ */
+ if (conn->sslrootcert
+ && strcmp(conn->sslrootcert, "system") == 0)
+ {
+ conn->status = CONNECTION_BAD;
+ libpq_append_conn_error(conn, "%s value \"%s\" invalid when SSL support is not compiled in",
+ "sslrootcert", conn->sslrootcert);
+ return false;
+ }
+#endif
+
+ /*
+ * validate sslmode option
+ */
+ if (conn->sslmode)
+ {
+ if (strcmp(conn->sslmode, "disable") != 0
+ && strcmp(conn->sslmode, "allow") != 0
+ && strcmp(conn->sslmode, "prefer") != 0
+ && strcmp(conn->sslmode, "require") != 0
+ && strcmp(conn->sslmode, "verify-ca") != 0
+ && strcmp(conn->sslmode, "verify-full") != 0)
+ {
+ conn->status = CONNECTION_BAD;
+ libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
+ "sslmode", conn->sslmode);
+ return false;
+ }
+
+#ifndef USE_SSL
+ switch (conn->sslmode[0])
+ {
+ case 'a': /* "allow" */
+ case 'p': /* "prefer" */
+
+ /*
+ * warn user that an SSL connection will never be negotiated
+ * since SSL was not compiled in?
+ */
+ break;
+
+ case 'r': /* "require" */
+ case 'v': /* "verify-ca" or "verify-full" */
+ conn->status = CONNECTION_BAD;
+ libpq_append_conn_error(conn, "%s value \"%s\" invalid when SSL support is not compiled in",
+ "sslmode", conn->sslmode);
+ return false;
+ }
+#endif
+ }
+ else
+ {
+ conn->sslmode = strdup(DefaultSSLMode);
+ if (!conn->sslmode)
+ goto oom_error;
+ }
+
+#ifdef USE_SSL
+
+ /*
+ * If sslrootcert=system, make sure our chosen sslmode is compatible.
+ */
+ if (conn->sslrootcert
+ && strcmp(conn->sslrootcert, "system") == 0
+ && strcmp(conn->sslmode, "verify-full") != 0)
+ {
+ conn->status = CONNECTION_BAD;
+ libpq_append_conn_error(conn, "weak sslmode \"%s\" may not be used with sslrootcert=system (use \"verify-full\")",
+ conn->sslmode);
+ return false;
+ }
+#endif
+
+ /*
+ * Validate TLS protocol versions for ssl_min_protocol_version and
+ * ssl_max_protocol_version.
+ */
+ if (!sslVerifyProtocolVersion(conn->ssl_min_protocol_version))
+ {
+ conn->status = CONNECTION_BAD;
+ libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
+ "ssl_min_protocol_version",
+ conn->ssl_min_protocol_version);
+ return false;
+ }
+ if (!sslVerifyProtocolVersion(conn->ssl_max_protocol_version))
+ {
+ conn->status = CONNECTION_BAD;
+ libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
+ "ssl_max_protocol_version",
+ conn->ssl_max_protocol_version);
+ return false;
+ }
+
+ /*
+ * Check if the range of SSL protocols defined is correct. This is done
+ * at this early step because this is independent of the SSL
+ * implementation used, and this avoids unnecessary cycles with an
+ * already-built SSL context when the connection is being established, as
+ * it would be doomed anyway.
+ */
+ if (!sslVerifyProtocolRange(conn->ssl_min_protocol_version,
+ conn->ssl_max_protocol_version))
+ {
+ conn->status = CONNECTION_BAD;
+ libpq_append_conn_error(conn, "invalid SSL protocol version range");
+ return false;
+ }
+
+ /*
+ * validate sslcertmode option
+ */
+ if (conn->sslcertmode)
+ {
+ if (strcmp(conn->sslcertmode, "disable") != 0 &&
+ strcmp(conn->sslcertmode, "allow") != 0 &&
+ strcmp(conn->sslcertmode, "require") != 0)
+ {
+ conn->status = CONNECTION_BAD;
+ libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
+ "sslcertmode", conn->sslcertmode);
+ return false;
+ }
+#ifndef USE_SSL
+ if (strcmp(conn->sslcertmode, "require") == 0)
+ {
+ conn->status = CONNECTION_BAD;
+ libpq_append_conn_error(conn, "%s value \"%s\" invalid when SSL support is not compiled in",
+ "sslcertmode", conn->sslcertmode);
+ return false;
+ }
+#endif
+#ifndef HAVE_SSL_CTX_SET_CERT_CB
+
+ /*
+ * Without a certificate callback, the current implementation can't
+ * figure out if a certificate was actually requested, so "require" is
+ * useless.
+ */
+ if (strcmp(conn->sslcertmode, "require") == 0)
+ {
+ conn->status = CONNECTION_BAD;
+ libpq_append_conn_error(conn, "%s value \"%s\" is not supported (check OpenSSL version)",
+ "sslcertmode", conn->sslcertmode);
+ return false;
+ }
+#endif
+ }
+ else
+ {
+ conn->sslcertmode = strdup(DefaultSSLCertMode);
+ if (!conn->sslcertmode)
+ goto oom_error;
+ }
+
+ /*
+ * validate gssencmode option
+ */
+ if (conn->gssencmode)
+ {
+ if (strcmp(conn->gssencmode, "disable") != 0 &&
+ strcmp(conn->gssencmode, "prefer") != 0 &&
+ strcmp(conn->gssencmode, "require") != 0)
+ {
+ conn->status = CONNECTION_BAD;
+ libpq_append_conn_error(conn, "invalid %s value: \"%s\"", "gssencmode", conn->gssencmode);
+ return false;
+ }
+#ifndef ENABLE_GSS
+ if (strcmp(conn->gssencmode, "require") == 0)
+ {
+ conn->status = CONNECTION_BAD;
+ libpq_append_conn_error(conn, "gssencmode value \"%s\" invalid when GSSAPI support is not compiled in",
+ conn->gssencmode);
+ return false;
+ }
+#endif
+ }
+ else
+ {
+ conn->gssencmode = strdup(DefaultGSSMode);
+ if (!conn->gssencmode)
+ goto oom_error;
+ }
+
+ /*
+ * validate target_session_attrs option, and set target_server_type
+ */
+ if (conn->target_session_attrs)
+ {
+ if (strcmp(conn->target_session_attrs, "any") == 0)
+ conn->target_server_type = SERVER_TYPE_ANY;
+ else if (strcmp(conn->target_session_attrs, "read-write") == 0)
+ conn->target_server_type = SERVER_TYPE_READ_WRITE;
+ else if (strcmp(conn->target_session_attrs, "read-only") == 0)
+ conn->target_server_type = SERVER_TYPE_READ_ONLY;
+ else if (strcmp(conn->target_session_attrs, "primary") == 0)
+ conn->target_server_type = SERVER_TYPE_PRIMARY;
+ else if (strcmp(conn->target_session_attrs, "standby") == 0)
+ conn->target_server_type = SERVER_TYPE_STANDBY;
+ else if (strcmp(conn->target_session_attrs, "prefer-standby") == 0)
+ conn->target_server_type = SERVER_TYPE_PREFER_STANDBY;
+ else
+ {
+ conn->status = CONNECTION_BAD;
+ libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
+ "target_session_attrs",
+ conn->target_session_attrs);
+ return false;
+ }
+ }
+ else
+ conn->target_server_type = SERVER_TYPE_ANY;
+
+ /*
+ * validate load_balance_hosts option, and set load_balance_type
+ */
+ if (conn->load_balance_hosts)
+ {
+ if (strcmp(conn->load_balance_hosts, "disable") == 0)
+ conn->load_balance_type = LOAD_BALANCE_DISABLE;
+ else if (strcmp(conn->load_balance_hosts, "random") == 0)
+ conn->load_balance_type = LOAD_BALANCE_RANDOM;
+ else
+ {
+ conn->status = CONNECTION_BAD;
+ libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
+ "load_balance_hosts",
+ conn->load_balance_hosts);
+ return false;
+ }
+ }
+ else
+ conn->load_balance_type = LOAD_BALANCE_DISABLE;
+
+ if (conn->load_balance_type == LOAD_BALANCE_RANDOM)
+ {
+ libpq_prng_init(conn);
+
+ /*
+ * This is the "inside-out" variant of the Fisher-Yates shuffle
+ * algorithm. Notionally, we append each new value to the array and
+ * then swap it with a randomly-chosen array element (possibly
+ * including itself, else we fail to generate permutations with the
+ * last integer last). The swap step can be optimized by combining it
+ * with the insertion.
+ */
+ for (i = 1; i < conn->nconnhost; i++)
+ {
+ int j = pg_prng_uint64_range(&conn->prng_state, 0, i);
+ pg_conn_host temp = conn->connhost[j];
+
+ conn->connhost[j] = conn->connhost[i];
+ conn->connhost[i] = temp;
+ }
+ }
+
+ /*
+ * Resolve special "auto" client_encoding from the locale
+ */
+ if (conn->client_encoding_initial &&
+ strcmp(conn->client_encoding_initial, "auto") == 0)
+ {
+ free(conn->client_encoding_initial);
+ conn->client_encoding_initial = strdup(pg_encoding_to_char(pg_get_encoding_from_locale(NULL, true)));
+ if (!conn->client_encoding_initial)
+ goto oom_error;
+ }
+
+ /*
+ * Only if we get this far is it appropriate to try to connect. (We need a
+ * state flag, rather than just the boolean result of this function, in
+ * case someone tries to PQreset() the PGconn.)
+ */
+ conn->options_valid = true;
+
+ return true;
+
+oom_error:
+ conn->status = CONNECTION_BAD;
+ libpq_append_conn_error(conn, "out of memory");
+ return false;
+}
+
+/*
+ * PQconndefaults
+ *
+ * Construct a default connection options array, which identifies all the
+ * available options and shows any default values that are available from the
+ * environment etc. On error (eg out of memory), NULL is returned.
+ *
+ * Using this function, an application may determine all possible options
+ * and their current default values.
+ *
+ * NOTE: as of PostgreSQL 7.0, the returned array is dynamically allocated
+ * and should be freed when no longer needed via PQconninfoFree(). (In prior
+ * versions, the returned array was static, but that's not thread-safe.)
+ * Pre-7.0 applications that use this function will see a small memory leak
+ * until they are updated to call PQconninfoFree.
+ */
+PQconninfoOption *
+PQconndefaults(void)
+{
+ PQExpBufferData errorBuf;
+ PQconninfoOption *connOptions;
+
+ /* We don't actually report any errors here, but callees want a buffer */
+ initPQExpBuffer(&errorBuf);
+ if (PQExpBufferDataBroken(errorBuf))
+ return NULL; /* out of memory already :-( */
+
+ connOptions = conninfo_init(&errorBuf);
+ if (connOptions != NULL)
+ {
+ /* pass NULL errorBuf to ignore errors */
+ if (!conninfo_add_defaults(connOptions, NULL))
+ {
+ PQconninfoFree(connOptions);
+ connOptions = NULL;
+ }
+ }
+
+ termPQExpBuffer(&errorBuf);
+ return connOptions;
+}
+
+/* ----------------
+ * PQsetdbLogin
+ *
+ * establishes a connection to a postgres backend through the postmaster
+ * at the specified host and port.
+ *
+ * returns a PGconn* which is needed for all subsequent libpq calls
+ *
+ * if the status field of the connection returned is CONNECTION_BAD,
+ * then only the errorMessage is likely to be useful.
+ * ----------------
+ */
+PGconn *
+PQsetdbLogin(const char *pghost, const char *pgport, const char *pgoptions,
+ const char *pgtty, const char *dbName, const char *login,
+ const char *pwd)
+{
+ PGconn *conn;
+
+ /*
+ * Allocate memory for the conn structure. Note that we also expect this
+ * to initialize conn->errorMessage to empty. All subsequent steps during
+ * connection initialization will only append to that buffer.
+ */
+ conn = makeEmptyPGconn();
+ if (conn == NULL)
+ return NULL;
+
+ /*
+ * If the dbName parameter contains what looks like a connection string,
+ * parse it into conn struct using connectOptions1.
+ */
+ if (dbName && recognized_connection_string(dbName))
+ {
+ if (!connectOptions1(conn, dbName))
+ return conn;
+ }
+ else
+ {
+ /*
+ * Old-style path: first, parse an empty conninfo string in order to
+ * set up the same defaults that PQconnectdb() would use.
+ */
+ if (!connectOptions1(conn, ""))
+ return conn;
+
+ /* Insert dbName parameter value into struct */
+ if (dbName && dbName[0] != '\0')
+ {
+ free(conn->dbName);
+ conn->dbName = strdup(dbName);
+ if (!conn->dbName)
+ goto oom_error;
+ }
+ }
+
+ /*
+ * Insert remaining parameters into struct, overriding defaults (as well
+ * as any conflicting data from dbName taken as a conninfo).
+ */
+ if (pghost && pghost[0] != '\0')
+ {
+ free(conn->pghost);
+ conn->pghost = strdup(pghost);
+ if (!conn->pghost)
+ goto oom_error;
+ }
+
+ if (pgport && pgport[0] != '\0')
+ {
+ free(conn->pgport);
+ conn->pgport = strdup(pgport);
+ if (!conn->pgport)
+ goto oom_error;
+ }
+
+ if (pgoptions && pgoptions[0] != '\0')
+ {
+ free(conn->pgoptions);
+ conn->pgoptions = strdup(pgoptions);
+ if (!conn->pgoptions)
+ goto oom_error;
+ }
+
+ if (login && login[0] != '\0')
+ {
+ free(conn->pguser);
+ conn->pguser = strdup(login);
+ if (!conn->pguser)
+ goto oom_error;
+ }
+
+ if (pwd && pwd[0] != '\0')
+ {
+ free(conn->pgpass);
+ conn->pgpass = strdup(pwd);
+ if (!conn->pgpass)
+ goto oom_error;
+ }
+
+ /*
+ * Compute derived options
+ */
+ if (!connectOptions2(conn))
+ return conn;
+
+ /*
+ * Connect to the database
+ */
+ if (connectDBStart(conn))
+ (void) connectDBComplete(conn);
+
+ return conn;
+
+oom_error:
+ conn->status = CONNECTION_BAD;
+ libpq_append_conn_error(conn, "out of memory");
+ return conn;
+}
+
+
+/* ----------
+ * connectNoDelay -
+ * Sets the TCP_NODELAY socket option.
+ * Returns 1 if successful, 0 if not.
+ * ----------
+ */
+static int
+connectNoDelay(PGconn *conn)
+{
+#ifdef TCP_NODELAY
+ int on = 1;
+
+ if (setsockopt(conn->sock, IPPROTO_TCP, TCP_NODELAY,
+ (char *) &on,
+ sizeof(on)) < 0)
+ {
+ char sebuf[PG_STRERROR_R_BUFLEN];
+
+ libpq_append_conn_error(conn, "could not set socket to TCP no delay mode: %s",
+ SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
+ return 0;
+ }
+#endif
+
+ return 1;
+}
+
+/* ----------
+ * Write currently connected IP address into host_addr (of len host_addr_len).
+ * If unable to, set it to the empty string.
+ * ----------
+ */
+static void
+getHostaddr(PGconn *conn, char *host_addr, int host_addr_len)
+{
+ struct sockaddr_storage *addr = &conn->raddr.addr;
+
+ if (addr->ss_family == AF_INET)
+ {
+ if (pg_inet_net_ntop(AF_INET,
+ &((struct sockaddr_in *) addr)->sin_addr.s_addr,
+ 32,
+ host_addr, host_addr_len) == NULL)
+ host_addr[0] = '\0';
+ }
+ else if (addr->ss_family == AF_INET6)
+ {
+ if (pg_inet_net_ntop(AF_INET6,
+ &((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr,
+ 128,
+ host_addr, host_addr_len) == NULL)
+ host_addr[0] = '\0';
+ }
+ else
+ host_addr[0] = '\0';
+}
+
+/*
+ * emitHostIdentityInfo -
+ * Speculatively append "connection to server so-and-so failed: " to
+ * conn->errorMessage once we've identified the current connection target
+ * address. This ensures that any subsequent error message will be properly
+ * attributed to the server we couldn't connect to. conn->raddr must be
+ * valid, and the result of getHostaddr() must be supplied.
+ */
+static void
+emitHostIdentityInfo(PGconn *conn, const char *host_addr)
+{
+ if (conn->raddr.addr.ss_family == AF_UNIX)
+ {
+ char service[NI_MAXHOST];
+
+ pg_getnameinfo_all(&conn->raddr.addr, conn->raddr.salen,
+ NULL, 0,
+ service, sizeof(service),
+ NI_NUMERICSERV);
+ appendPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("connection to server on socket \"%s\" failed: "),
+ service);
+ }
+ else
+ {
+ const char *displayed_host;
+ const char *displayed_port;
+
+ /* To which host and port were we actually connecting? */
+ if (conn->connhost[conn->whichhost].type == CHT_HOST_ADDRESS)
+ displayed_host = conn->connhost[conn->whichhost].hostaddr;
+ else
+ displayed_host = conn->connhost[conn->whichhost].host;
+ displayed_port = conn->connhost[conn->whichhost].port;
+ if (displayed_port == NULL || displayed_port[0] == '\0')
+ displayed_port = DEF_PGPORT_STR;
+
+ /*
+ * If the user did not supply an IP address using 'hostaddr', and
+ * 'host' was missing or does not match our lookup, display the
+ * looked-up IP address.
+ */
+ if (conn->connhost[conn->whichhost].type != CHT_HOST_ADDRESS &&
+ host_addr[0] &&
+ strcmp(displayed_host, host_addr) != 0)
+ appendPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("connection to server at \"%s\" (%s), port %s failed: "),
+ displayed_host, host_addr,
+ displayed_port);
+ else
+ appendPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("connection to server at \"%s\", port %s failed: "),
+ displayed_host,
+ displayed_port);
+ }
+}
+
+/* ----------
+ * connectFailureMessage -
+ * create a friendly error message on connection failure,
+ * using the given errno value. Use this for error cases that
+ * imply that there's no server there.
+ * ----------
+ */
+static void
+connectFailureMessage(PGconn *conn, int errorno)
+{
+ char sebuf[PG_STRERROR_R_BUFLEN];
+
+ appendPQExpBuffer(&conn->errorMessage,
+ "%s\n",
+ SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)));
+
+ if (conn->raddr.addr.ss_family == AF_UNIX)
+ libpq_append_conn_error(conn, "\tIs the server running locally and accepting connections on that socket?");
+ else
+ libpq_append_conn_error(conn, "\tIs the server running on that host and accepting TCP/IP connections?");
+}
+
+/*
+ * Should we use keepalives? Returns 1 if yes, 0 if no, and -1 if
+ * conn->keepalives is set to a value which is not parseable as an
+ * integer.
+ */
+static int
+useKeepalives(PGconn *conn)
+{
+ char *ep;
+ int val;
+
+ if (conn->keepalives == NULL)
+ return 1;
+ val = strtol(conn->keepalives, &ep, 10);
+ if (*ep)
+ return -1;
+ return val != 0 ? 1 : 0;
+}
+
+/*
+ * Parse and try to interpret "value" as an integer value, and if successful,
+ * store it in *result, complaining if there is any trailing garbage or an
+ * overflow. This allows any number of leading and trailing whitespaces.
+ */
+static bool
+parse_int_param(const char *value, int *result, PGconn *conn,
+ const char *context)
+{
+ char *end;
+ long numval;
+
+ Assert(value != NULL);
+
+ *result = 0;
+
+ /* strtol(3) skips leading whitespaces */
+ errno = 0;
+ numval = strtol(value, &end, 10);
+
+ /*
+ * If no progress was done during the parsing or an error happened, fail.
+ * This tests properly for overflows of the result.
+ */
+ if (value == end || errno != 0 || numval != (int) numval)
+ goto error;
+
+ /*
+ * Skip any trailing whitespace; if anything but whitespace remains before
+ * the terminating character, fail
+ */
+ while (*end != '\0' && isspace((unsigned char) *end))
+ end++;
+
+ if (*end != '\0')
+ goto error;
+
+ *result = numval;
+ return true;
+
+error:
+ libpq_append_conn_error(conn, "invalid integer value \"%s\" for connection option \"%s\"",
+ value, context);
+ return false;
+}
+
+#ifndef WIN32
+/*
+ * Set the keepalive idle timer.
+ */
+static int
+setKeepalivesIdle(PGconn *conn)
+{
+ int idle;
+
+ if (conn->keepalives_idle == NULL)
+ return 1;
+
+ if (!parse_int_param(conn->keepalives_idle, &idle, conn,
+ "keepalives_idle"))
+ return 0;
+ if (idle < 0)
+ idle = 0;
+
+#ifdef PG_TCP_KEEPALIVE_IDLE
+ if (setsockopt(conn->sock, IPPROTO_TCP, PG_TCP_KEEPALIVE_IDLE,
+ (char *) &idle, sizeof(idle)) < 0)
+ {
+ char sebuf[PG_STRERROR_R_BUFLEN];
+
+ libpq_append_conn_error(conn, "%s(%s) failed: %s",
+ "setsockopt",
+ PG_TCP_KEEPALIVE_IDLE_STR,
+ SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
+ return 0;
+ }
+#endif
+
+ return 1;
+}
+
+/*
+ * Set the keepalive interval.
+ */
+static int
+setKeepalivesInterval(PGconn *conn)
+{
+ int interval;
+
+ if (conn->keepalives_interval == NULL)
+ return 1;
+
+ if (!parse_int_param(conn->keepalives_interval, &interval, conn,
+ "keepalives_interval"))
+ return 0;
+ if (interval < 0)
+ interval = 0;
+
+#ifdef TCP_KEEPINTVL
+ if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPINTVL,
+ (char *) &interval, sizeof(interval)) < 0)
+ {
+ char sebuf[PG_STRERROR_R_BUFLEN];
+
+ libpq_append_conn_error(conn, "%s(%s) failed: %s",
+ "setsockopt",
+ "TCP_KEEPINTVL",
+ SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
+ return 0;
+ }
+#endif
+
+ return 1;
+}
+
+/*
+ * Set the count of lost keepalive packets that will trigger a connection
+ * break.
+ */
+static int
+setKeepalivesCount(PGconn *conn)
+{
+ int count;
+
+ if (conn->keepalives_count == NULL)
+ return 1;
+
+ if (!parse_int_param(conn->keepalives_count, &count, conn,
+ "keepalives_count"))
+ return 0;
+ if (count < 0)
+ count = 0;
+
+#ifdef TCP_KEEPCNT
+ if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPCNT,
+ (char *) &count, sizeof(count)) < 0)
+ {
+ char sebuf[PG_STRERROR_R_BUFLEN];
+
+ libpq_append_conn_error(conn, "%s(%s) failed: %s",
+ "setsockopt",
+ "TCP_KEEPCNT",
+ SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
+ return 0;
+ }
+#endif
+
+ return 1;
+}
+#else /* WIN32 */
+#ifdef SIO_KEEPALIVE_VALS
+/*
+ * Enable keepalives and set the keepalive values on Win32,
+ * where they are always set in one batch.
+ *
+ * CAUTION: This needs to be signal safe, since it's used by PQcancel.
+ */
+static int
+setKeepalivesWin32(pgsocket sock, int idle, int interval)
+{
+ struct tcp_keepalive ka;
+ DWORD retsize;
+
+ if (idle <= 0)
+ idle = 2 * 60 * 60; /* 2 hours = default */
+ if (interval <= 0)
+ interval = 1; /* 1 second = default */
+
+ ka.onoff = 1;
+ ka.keepalivetime = idle * 1000;
+ ka.keepaliveinterval = interval * 1000;
+
+ if (WSAIoctl(sock,
+ SIO_KEEPALIVE_VALS,
+ (LPVOID) &ka,
+ sizeof(ka),
+ NULL,
+ 0,
+ &retsize,
+ NULL,
+ NULL)
+ != 0)
+ return 0;
+ return 1;
+}
+
+static int
+prepKeepalivesWin32(PGconn *conn)
+{
+ int idle = -1;
+ int interval = -1;
+
+ if (conn->keepalives_idle &&
+ !parse_int_param(conn->keepalives_idle, &idle, conn,
+ "keepalives_idle"))
+ return 0;
+ if (conn->keepalives_interval &&
+ !parse_int_param(conn->keepalives_interval, &interval, conn,
+ "keepalives_interval"))
+ return 0;
+
+ if (!setKeepalivesWin32(conn->sock, idle, interval))
+ {
+ libpq_append_conn_error(conn, "%s(%s) failed: error code %d",
+ "WSAIoctl", "SIO_KEEPALIVE_VALS",
+ WSAGetLastError());
+ return 0;
+ }
+ return 1;
+}
+#endif /* SIO_KEEPALIVE_VALS */
+#endif /* WIN32 */
+
+/*
+ * Set the TCP user timeout.
+ */
+static int
+setTCPUserTimeout(PGconn *conn)
+{
+ int timeout;
+
+ if (conn->pgtcp_user_timeout == NULL)
+ return 1;
+
+ if (!parse_int_param(conn->pgtcp_user_timeout, &timeout, conn,
+ "tcp_user_timeout"))
+ return 0;
+
+ if (timeout < 0)
+ timeout = 0;
+
+// Compilation must fail on linux if TCP_USER_TIMEOUT is not defined
+#ifdef __linux__
+ if (setsockopt(conn->sock, IPPROTO_TCP, TCP_USER_TIMEOUT,
+ (char *) &timeout, sizeof(timeout)) < 0)
+ {
+ char sebuf[256];
+
+ libpq_append_conn_error(conn, "%s(%s) failed: %s",
+ "setsockopt",
+ "TCP_USER_TIMEOUT",
+ SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
+ return 0;
+ }
+#endif
+
+ return 1;
+}
+
+/* ----------
+ * connectDBStart -
+ * Begin the process of making a connection to the backend.
+ *
+ * Returns 1 if successful, 0 if not.
+ * ----------
+ */
+static int
+connectDBStart(PGconn *conn)
+{
+ if (!conn)
+ return 0;
+
+ if (!conn->options_valid)
+ goto connect_errReturn;
+
+ /*
+ * Check for bad linking to backend-internal versions of src/common
+ * functions (see comments in link-canary.c for the reason we need this).
+ * Nobody but developers should see this message, so we don't bother
+ * translating it.
+ */
+ if (!pg_link_canary_is_frontend())
+ {
+ appendPQExpBufferStr(&conn->errorMessage,
+ "libpq is incorrectly linked to backend functions\n");
+ goto connect_errReturn;
+ }
+
+ /* Ensure our buffers are empty */
+ conn->inStart = conn->inCursor = conn->inEnd = 0;
+ conn->outCount = 0;
+
+ /*
+ * Set up to try to connect to the first host. (Setting whichhost = -1 is
+ * a bit of a cheat, but PQconnectPoll will advance it to 0 before
+ * anything else looks at it.)
+ */
+ conn->whichhost = -1;
+ conn->try_next_addr = false;
+ conn->try_next_host = true;
+ conn->status = CONNECTION_NEEDED;
+
+ /* Also reset the target_server_type state if needed */
+ if (conn->target_server_type == SERVER_TYPE_PREFER_STANDBY_PASS2)
+ conn->target_server_type = SERVER_TYPE_PREFER_STANDBY;
+
+ /*
+ * The code for processing CONNECTION_NEEDED state is in PQconnectPoll(),
+ * so that it can easily be re-executed if needed again during the
+ * asynchronous startup process. However, we must run it once here,
+ * because callers expect a success return from this routine to mean that
+ * we are in PGRES_POLLING_WRITING connection state.
+ */
+ if (PQconnectPoll(conn) == PGRES_POLLING_WRITING)
+ return 1;
+
+connect_errReturn:
+
+ /*
+ * If we managed to open a socket, close it immediately rather than
+ * waiting till PQfinish. (The application cannot have gotten the socket
+ * from PQsocket yet, so this doesn't risk breaking anything.)
+ */
+ pqDropConnection(conn, true);
+ conn->status = CONNECTION_BAD;
+ return 0;
+}
+
+
+/*
+ * connectDBComplete
+ *
+ * Block and complete a connection.
+ *
+ * Returns 1 on success, 0 on failure.
+ */
+static int
+connectDBComplete(PGconn *conn)
+{
+ PostgresPollingStatusType flag = PGRES_POLLING_WRITING;
+ time_t finish_time = ((time_t) -1);
+ int timeout = 0;
+ int last_whichhost = -2; /* certainly different from whichhost */
+ int last_whichaddr = -2; /* certainly different from whichaddr */
+
+ if (conn == NULL || conn->status == CONNECTION_BAD)
+ return 0;
+
+ /*
+ * Set up a time limit, if connect_timeout isn't zero.
+ */
+ if (conn->connect_timeout != NULL)
+ {
+ if (!parse_int_param(conn->connect_timeout, &timeout, conn,
+ "connect_timeout"))
+ {
+ /* mark the connection as bad to report the parsing failure */
+ conn->status = CONNECTION_BAD;
+ return 0;
+ }
+
+ if (timeout > 0)
+ {
+ /*
+ * Rounding could cause connection to fail unexpectedly quickly;
+ * to prevent possibly waiting hardly-at-all, insist on at least
+ * two seconds.
+ */
+ if (timeout < 2)
+ timeout = 2;
+ }
+ else /* negative means 0 */
+ timeout = 0;
+ }
+
+ for (;;)
+ {
+ int ret = 0;
+
+ /*
+ * (Re)start the connect_timeout timer if it's active and we are
+ * considering a different host than we were last time through. If
+ * we've already succeeded, though, needn't recalculate.
+ */
+ if (flag != PGRES_POLLING_OK &&
+ timeout > 0 &&
+ (conn->whichhost != last_whichhost ||
+ conn->whichaddr != last_whichaddr))
+ {
+ finish_time = time(NULL) + timeout;
+ last_whichhost = conn->whichhost;
+ last_whichaddr = conn->whichaddr;
+ }
+
+ /*
+ * Wait, if necessary. Note that the initial state (just after
+ * PQconnectStart) is to wait for the socket to select for writing.
+ */
+ switch (flag)
+ {
+ case PGRES_POLLING_OK:
+ return 1; /* success! */
+
+ case PGRES_POLLING_READING:
+ ret = pqWaitTimed(1, 0, conn, finish_time);
+ if (ret == -1)
+ {
+ /* hard failure, eg select() problem, aborts everything */
+ conn->status = CONNECTION_BAD;
+ return 0;
+ }
+ break;
+
+ case PGRES_POLLING_WRITING:
+ ret = pqWaitTimed(0, 1, conn, finish_time);
+ if (ret == -1)
+ {
+ /* hard failure, eg select() problem, aborts everything */
+ conn->status = CONNECTION_BAD;
+ return 0;
+ }
+ break;
+
+ default:
+ /* Just in case we failed to set it in PQconnectPoll */
+ conn->status = CONNECTION_BAD;
+ return 0;
+ }
+
+ if (ret == 1) /* connect_timeout elapsed */
+ {
+ /*
+ * Give up on current server/address, try the next one.
+ */
+ conn->try_next_addr = true;
+ conn->status = CONNECTION_NEEDED;
+ }
+
+ /*
+ * Now try to advance the state machine.
+ */
+ flag = PQconnectPoll(conn);
+ }
+}
+
+/* ----------------
+ * PQconnectPoll
+ *
+ * Poll an asynchronous connection.
+ *
+ * Returns a PostgresPollingStatusType.
+ * Before calling this function, use select(2) to determine when data
+ * has arrived..
+ *
+ * You must call PQfinish whether or not this fails.
+ *
+ * This function and PQconnectStart are intended to allow connections to be
+ * made without blocking the execution of your program on remote I/O. However,
+ * there are a number of caveats:
+ *
+ * o If you call PQtrace, ensure that the stream object into which you trace
+ * will not block.
+ * o If you do not supply an IP address for the remote host (i.e. you
+ * supply a host name instead) then PQconnectStart will block on
+ * getaddrinfo. You will be fine if using Unix sockets (i.e. by
+ * supplying neither a host name nor a host address).
+ * o If your backend wants to use Kerberos authentication then you must
+ * supply both a host name and a host address, otherwise this function
+ * may block on gethostname.
+ *
+ * ----------------
+ */
+PostgresPollingStatusType
+PQconnectPoll(PGconn *conn)
+{
+ bool reset_connection_state_machine = false;
+ bool need_new_connection = false;
+ PGresult *res;
+ char sebuf[PG_STRERROR_R_BUFLEN];
+ int optval;
+
+ if (conn == NULL)
+ return PGRES_POLLING_FAILED;
+
+ /* Get the new data */
+ switch (conn->status)
+ {
+ /*
+ * We really shouldn't have been polled in these two cases, but we
+ * can handle it.
+ */
+ case CONNECTION_BAD:
+ return PGRES_POLLING_FAILED;
+ case CONNECTION_OK:
+ return PGRES_POLLING_OK;
+
+ /* These are reading states */
+ case CONNECTION_AWAITING_RESPONSE:
+ case CONNECTION_AUTH_OK:
+ case CONNECTION_CHECK_WRITABLE:
+ case CONNECTION_CONSUME:
+ case CONNECTION_CHECK_STANDBY:
+ {
+ /* Load waiting data */
+ int n = pqReadData(conn);
+
+ if (n < 0)
+ goto error_return;
+ if (n == 0)
+ return PGRES_POLLING_READING;
+
+ break;
+ }
+
+ /* These are writing states, so we just proceed. */
+ case CONNECTION_STARTED:
+ case CONNECTION_MADE:
+ break;
+
+ /* Special cases: proceed without waiting. */
+ case CONNECTION_SSL_STARTUP:
+ case CONNECTION_NEEDED:
+ case CONNECTION_GSS_STARTUP:
+ case CONNECTION_CHECK_TARGET:
+ break;
+
+ default:
+ libpq_append_conn_error(conn, "invalid connection state, probably indicative of memory corruption");
+ goto error_return;
+ }
+
+
+keep_going: /* We will come back to here until there is
+ * nothing left to do. */
+
+ /* Time to advance to next address, or next host if no more addresses? */
+ if (conn->try_next_addr)
+ {
+ if (conn->whichaddr < conn->naddr)
+ {
+ conn->whichaddr++;
+ reset_connection_state_machine = true;
+ }
+ else
+ conn->try_next_host = true;
+ conn->try_next_addr = false;
+ }
+
+ /* Time to advance to next connhost[] entry? */
+ if (conn->try_next_host)
+ {
+ pg_conn_host *ch;
+ struct addrinfo hint;
+ struct addrinfo *addrlist;
+ int thisport;
+ int ret;
+ char portstr[MAXPGPATH];
+
+ if (conn->whichhost + 1 < conn->nconnhost)
+ conn->whichhost++;
+ else
+ {
+ /*
+ * Oops, no more hosts.
+ *
+ * If we are trying to connect in "prefer-standby" mode, then drop
+ * the standby requirement and start over.
+ *
+ * Otherwise, an appropriate error message is already set up, so
+ * we just need to set the right status.
+ */
+ if (conn->target_server_type == SERVER_TYPE_PREFER_STANDBY &&
+ conn->nconnhost > 0)
+ {
+ conn->target_server_type = SERVER_TYPE_PREFER_STANDBY_PASS2;
+ conn->whichhost = 0;
+ }
+ else
+ goto error_return;
+ }
+
+ /* Drop any address info for previous host */
+ release_conn_addrinfo(conn);
+
+ /*
+ * Look up info for the new host. On failure, log the problem in
+ * conn->errorMessage, then loop around to try the next host. (Note
+ * we don't clear try_next_host until we've succeeded.)
+ */
+ ch = &conn->connhost[conn->whichhost];
+
+ /* Initialize hint structure */
+ MemSet(&hint, 0, sizeof(hint));
+ hint.ai_socktype = SOCK_STREAM;
+ hint.ai_family = AF_UNSPEC;
+
+ /* Figure out the port number we're going to use. */
+ if (ch->port == NULL || ch->port[0] == '\0')
+ thisport = DEF_PGPORT;
+ else
+ {
+ if (!parse_int_param(ch->port, &thisport, conn, "port"))
+ goto error_return;
+
+ if (thisport < 1 || thisport > 65535)
+ {
+ libpq_append_conn_error(conn, "invalid port number: \"%s\"", ch->port);
+ goto keep_going;
+ }
+ }
+ snprintf(portstr, sizeof(portstr), "%d", thisport);
+
+ /* Use pg_getaddrinfo_all() to resolve the address */
+ switch (ch->type)
+ {
+ case CHT_HOST_NAME:
+ ret = pg_getaddrinfo_all(ch->host, portstr, &hint,
+ &addrlist);
+ if (ret || !addrlist)
+ {
+ libpq_append_conn_error(conn, "could not translate host name \"%s\" to address: %s",
+ ch->host, gai_strerror(ret));
+ goto keep_going;
+ }
+ break;
+
+ case CHT_HOST_ADDRESS:
+ hint.ai_flags = AI_NUMERICHOST;
+ ret = pg_getaddrinfo_all(ch->hostaddr, portstr, &hint,
+ &addrlist);
+ if (ret || !addrlist)
+ {
+ libpq_append_conn_error(conn, "could not parse network address \"%s\": %s",
+ ch->hostaddr, gai_strerror(ret));
+ goto keep_going;
+ }
+ break;
+
+ case CHT_UNIX_SOCKET:
+ hint.ai_family = AF_UNIX;
+ UNIXSOCK_PATH(portstr, thisport, ch->host);
+ if (strlen(portstr) >= UNIXSOCK_PATH_BUFLEN)
+ {
+ libpq_append_conn_error(conn, "Unix-domain socket path \"%s\" is too long (maximum %d bytes)",
+ portstr,
+ (int) (UNIXSOCK_PATH_BUFLEN - 1));
+ goto keep_going;
+ }
+
+ /*
+ * NULL hostname tells pg_getaddrinfo_all to parse the service
+ * name as a Unix-domain socket path.
+ */
+ ret = pg_getaddrinfo_all(NULL, portstr, &hint,
+ &addrlist);
+ if (ret || !addrlist)
+ {
+ libpq_append_conn_error(conn, "could not translate Unix-domain socket path \"%s\" to address: %s",
+ portstr, gai_strerror(ret));
+ goto keep_going;
+ }
+ break;
+ }
+
+ /*
+ * Store a copy of the addrlist in private memory so we can perform
+ * randomization for load balancing.
+ */
+ ret = store_conn_addrinfo(conn, addrlist);
+ pg_freeaddrinfo_all(hint.ai_family, addrlist);
+ if (ret)
+ goto error_return; /* message already logged */
+
+ /*
+ * If random load balancing is enabled we shuffle the addresses.
+ */
+ if (conn->load_balance_type == LOAD_BALANCE_RANDOM)
+ {
+ /*
+ * This is the "inside-out" variant of the Fisher-Yates shuffle
+ * algorithm. Notionally, we append each new value to the array
+ * and then swap it with a randomly-chosen array element (possibly
+ * including itself, else we fail to generate permutations with
+ * the last integer last). The swap step can be optimized by
+ * combining it with the insertion.
+ *
+ * We don't need to initialize conn->prng_state here, because that
+ * already happened in connectOptions2.
+ */
+ for (int i = 1; i < conn->naddr; i++)
+ {
+ int j = pg_prng_uint64_range(&conn->prng_state, 0, i);
+ AddrInfo temp = conn->addr[j];
+
+ conn->addr[j] = conn->addr[i];
+ conn->addr[i] = temp;
+ }
+ }
+
+ reset_connection_state_machine = true;
+ conn->try_next_host = false;
+ }
+
+ /* Reset connection state machine? */
+ if (reset_connection_state_machine)
+ {
+ /*
+ * (Re) initialize our connection control variables for a set of
+ * connection attempts to a single server address. These variables
+ * must persist across individual connection attempts, but we must
+ * reset them when we start to consider a new server.
+ */
+ conn->pversion = PG_PROTOCOL(3, 0);
+ conn->send_appname = true;
+#ifdef USE_SSL
+ /* initialize these values based on SSL mode */
+ conn->allow_ssl_try = (conn->sslmode[0] != 'd'); /* "disable" */
+ conn->wait_ssl_try = (conn->sslmode[0] == 'a'); /* "allow" */
+#endif
+#ifdef ENABLE_GSS
+ conn->try_gss = (conn->gssencmode[0] != 'd'); /* "disable" */
+#endif
+
+ reset_connection_state_machine = false;
+ need_new_connection = true;
+ }
+
+ /* Force a new connection (perhaps to the same server as before)? */
+ if (need_new_connection)
+ {
+ /* Drop any existing connection */
+ pqDropConnection(conn, true);
+
+ /* Reset all state obtained from old server */
+ pqDropServerData(conn);
+
+ /* Drop any PGresult we might have, too */
+ conn->asyncStatus = PGASYNC_IDLE;
+ conn->xactStatus = PQTRANS_IDLE;
+ conn->pipelineStatus = PQ_PIPELINE_OFF;
+ pqClearAsyncResult(conn);
+
+ /* Reset conn->status to put the state machine in the right state */
+ conn->status = CONNECTION_NEEDED;
+
+ need_new_connection = false;
+ }
+
+ /* Now try to advance the state machine for this connection */
+ switch (conn->status)
+ {
+ case CONNECTION_NEEDED:
+ {
+ /*
+ * Try to initiate a connection to one of the addresses
+ * returned by pg_getaddrinfo_all(). conn->whichaddr is the
+ * next one to try.
+ *
+ * The extra level of braces here is historical. It's not
+ * worth reindenting this whole switch case to remove 'em.
+ */
+ {
+ char host_addr[NI_MAXHOST];
+ int sock_type;
+ AddrInfo *addr_cur;
+
+ /*
+ * Advance to next possible host, if we've tried all of
+ * the addresses for the current host.
+ */
+ if (conn->whichaddr == conn->naddr)
+ {
+ conn->try_next_host = true;
+ goto keep_going;
+ }
+ addr_cur = &conn->addr[conn->whichaddr];
+
+ /* Remember current address for possible use later */
+ memcpy(&conn->raddr, &addr_cur->addr, sizeof(SockAddr));
+
+ /*
+ * Set connip, too. Note we purposely ignore strdup
+ * failure; not a big problem if it fails.
+ */
+ if (conn->connip != NULL)
+ {
+ free(conn->connip);
+ conn->connip = NULL;
+ }
+ getHostaddr(conn, host_addr, NI_MAXHOST);
+ if (host_addr[0])
+ conn->connip = strdup(host_addr);
+
+ /* Try to create the socket */
+ sock_type = SOCK_STREAM;
+#ifdef SOCK_CLOEXEC
+
+ /*
+ * Atomically mark close-on-exec, if possible on this
+ * platform, so that there isn't a window where a
+ * subprogram executed by another thread inherits the
+ * socket. See fallback code below.
+ */
+ sock_type |= SOCK_CLOEXEC;
+#endif
+#ifdef SOCK_NONBLOCK
+
+ /*
+ * We might as well skip a system call for nonblocking
+ * mode too, if we can.
+ */
+ sock_type |= SOCK_NONBLOCK;
+#endif
+ conn->sock = socket(addr_cur->family, sock_type, 0);
+ if (conn->sock == PGINVALID_SOCKET)
+ {
+ int errorno = SOCK_ERRNO;
+
+ /*
+ * Silently ignore socket() failure if we have more
+ * addresses to try; this reduces useless chatter in
+ * cases where the address list includes both IPv4 and
+ * IPv6 but kernel only accepts one family.
+ */
+ if (conn->whichaddr < conn->naddr ||
+ conn->whichhost + 1 < conn->nconnhost)
+ {
+ conn->try_next_addr = true;
+ goto keep_going;
+ }
+ emitHostIdentityInfo(conn, host_addr);
+ libpq_append_conn_error(conn, "could not create socket: %s",
+ SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)));
+ goto error_return;
+ }
+
+ /*
+ * Once we've identified a target address, all errors
+ * except the preceding socket()-failure case should be
+ * prefixed with host-identity information. (If the
+ * connection succeeds, the contents of conn->errorMessage
+ * won't matter, so this is harmless.)
+ */
+ emitHostIdentityInfo(conn, host_addr);
+
+ /*
+ * Select socket options: no delay of outgoing data for
+ * TCP sockets, nonblock mode, close-on-exec. Try the
+ * next address if any of this fails.
+ */
+ if (addr_cur->family != AF_UNIX)
+ {
+ if (!connectNoDelay(conn))
+ {
+ /* error message already created */
+ conn->try_next_addr = true;
+ goto keep_going;
+ }
+ }
+#ifndef SOCK_NONBLOCK
+ if (!pg_set_noblock(conn->sock))
+ {
+ libpq_append_conn_error(conn, "could not set socket to nonblocking mode: %s",
+ SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
+ conn->try_next_addr = true;
+ goto keep_going;
+ }
+#endif
+
+#ifndef SOCK_CLOEXEC
+#ifdef F_SETFD
+ if (fcntl(conn->sock, F_SETFD, FD_CLOEXEC) == -1)
+ {
+ libpq_append_conn_error(conn, "could not set socket to close-on-exec mode: %s",
+ SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
+ conn->try_next_addr = true;
+ goto keep_going;
+ }
+#endif /* F_SETFD */
+#endif
+
+ if (addr_cur->family != AF_UNIX)
+ {
+#ifndef WIN32
+ int on = 1;
+#endif
+ int usekeepalives = useKeepalives(conn);
+ int err = 0;
+
+ if (usekeepalives < 0)
+ {
+ libpq_append_conn_error(conn, "keepalives parameter must be an integer");
+ err = 1;
+ }
+ else if (usekeepalives == 0)
+ {
+ /* Do nothing */
+ }
+#ifndef WIN32
+ else if (setsockopt(conn->sock,
+ SOL_SOCKET, SO_KEEPALIVE,
+ (char *) &on, sizeof(on)) < 0)
+ {
+ libpq_append_conn_error(conn, "%s(%s) failed: %s",
+ "setsockopt",
+ "SO_KEEPALIVE",
+ SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
+ err = 1;
+ }
+ else if (!setKeepalivesIdle(conn)
+ || !setKeepalivesInterval(conn)
+ || !setKeepalivesCount(conn))
+ err = 1;
+#else /* WIN32 */
+#ifdef SIO_KEEPALIVE_VALS
+ else if (!prepKeepalivesWin32(conn))
+ err = 1;
+#endif /* SIO_KEEPALIVE_VALS */
+#endif /* WIN32 */
+ else if (!setTCPUserTimeout(conn))
+ err = 1;
+
+ if (err)
+ {
+ conn->try_next_addr = true;
+ goto keep_going;
+ }
+ }
+
+ /*----------
+ * We have three methods of blocking SIGPIPE during
+ * send() calls to this socket:
+ *
+ * - setsockopt(sock, SO_NOSIGPIPE)
+ * - send(sock, ..., MSG_NOSIGNAL)
+ * - setting the signal mask to SIG_IGN during send()
+ *
+ * The third method requires three syscalls per send,
+ * so we prefer either of the first two, but they are
+ * less portable. The state is tracked in the following
+ * members of PGconn:
+ *
+ * conn->sigpipe_so - we have set up SO_NOSIGPIPE
+ * conn->sigpipe_flag - we're specifying MSG_NOSIGNAL
+ *
+ * If we can use SO_NOSIGPIPE, then set sigpipe_so here
+ * and we're done. Otherwise, set sigpipe_flag so that
+ * we will try MSG_NOSIGNAL on sends. If we get an error
+ * with MSG_NOSIGNAL, we'll clear that flag and revert to
+ * signal masking.
+ *----------
+ */
+ conn->sigpipe_so = false;
+#ifdef MSG_NOSIGNAL
+ conn->sigpipe_flag = true;
+#else
+ conn->sigpipe_flag = false;
+#endif /* MSG_NOSIGNAL */
+
+#ifdef SO_NOSIGPIPE
+ optval = 1;
+ if (setsockopt(conn->sock, SOL_SOCKET, SO_NOSIGPIPE,
+ (char *) &optval, sizeof(optval)) == 0)
+ {
+ conn->sigpipe_so = true;
+ conn->sigpipe_flag = false;
+ }
+#endif /* SO_NOSIGPIPE */
+
+ /*
+ * Start/make connection. This should not block, since we
+ * are in nonblock mode. If it does, well, too bad.
+ */
+ if (connect(conn->sock, (struct sockaddr *) &addr_cur->addr.addr,
+ addr_cur->addr.salen) < 0)
+ {
+ if (SOCK_ERRNO == EINPROGRESS ||
+#ifdef WIN32
+ SOCK_ERRNO == EWOULDBLOCK ||
+#endif
+ SOCK_ERRNO == EINTR)
+ {
+ /*
+ * This is fine - we're in non-blocking mode, and
+ * the connection is in progress. Tell caller to
+ * wait for write-ready on socket.
+ */
+ conn->status = CONNECTION_STARTED;
+ return PGRES_POLLING_WRITING;
+ }
+ /* otherwise, trouble */
+ }
+ else
+ {
+ /*
+ * Hm, we're connected already --- seems the "nonblock
+ * connection" wasn't. Advance the state machine and
+ * go do the next stuff.
+ */
+ conn->status = CONNECTION_STARTED;
+ goto keep_going;
+ }
+
+ /*
+ * This connection failed. Add the error report to
+ * conn->errorMessage, then try the next address if any.
+ */
+ connectFailureMessage(conn, SOCK_ERRNO);
+ conn->try_next_addr = true;
+ goto keep_going;
+ }
+ }
+
+ case CONNECTION_STARTED:
+ {
+ socklen_t optlen = sizeof(optval);
+
+ /*
+ * Write ready, since we've made it here, so the connection
+ * has been made ... or has failed.
+ */
+
+ /*
+ * Now check (using getsockopt) that there is not an error
+ * state waiting for us on the socket.
+ */
+
+ if (getsockopt(conn->sock, SOL_SOCKET, SO_ERROR,
+ (char *) &optval, &optlen) == -1)
+ {
+ libpq_append_conn_error(conn, "could not get socket error status: %s",
+ SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
+ goto error_return;
+ }
+ else if (optval != 0)
+ {
+ /*
+ * When using a nonblocking connect, we will typically see
+ * connect failures at this point, so provide a friendly
+ * error message.
+ */
+ connectFailureMessage(conn, optval);
+
+ /*
+ * Try the next address if any, just as in the case where
+ * connect() returned failure immediately.
+ */
+ conn->try_next_addr = true;
+ goto keep_going;
+ }
+
+ /* Fill in the client address */
+ conn->laddr.salen = sizeof(conn->laddr.addr);
+ if (getsockname(conn->sock,
+ (struct sockaddr *) &conn->laddr.addr,
+ &conn->laddr.salen) < 0)
+ {
+ libpq_append_conn_error(conn, "could not get client address from socket: %s",
+ SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
+ goto error_return;
+ }
+
+ /*
+ * Make sure we can write before advancing to next step.
+ */
+ conn->status = CONNECTION_MADE;
+ return PGRES_POLLING_WRITING;
+ }
+
+ case CONNECTION_MADE:
+ {
+ char *startpacket;
+ int packetlen;
+
+ /*
+ * Implement requirepeer check, if requested and it's a
+ * Unix-domain socket.
+ */
+ if (conn->requirepeer && conn->requirepeer[0] &&
+ conn->raddr.addr.ss_family == AF_UNIX)
+ {
+#ifndef WIN32
+ char *remote_username;
+#endif
+ uid_t uid;
+ gid_t gid;
+
+ errno = 0;
+ if (getpeereid(conn->sock, &uid, &gid) != 0)
+ {
+ /*
+ * Provide special error message if getpeereid is a
+ * stub
+ */
+ if (errno == ENOSYS)
+ libpq_append_conn_error(conn, "requirepeer parameter is not supported on this platform");
+ else
+ libpq_append_conn_error(conn, "could not get peer credentials: %s",
+ strerror_r(errno, sebuf, sizeof(sebuf)));
+ goto error_return;
+ }
+
+#ifndef WIN32
+ remote_username = pg_fe_getusername(uid,
+ &conn->errorMessage);
+ if (remote_username == NULL)
+ goto error_return; /* message already logged */
+
+ if (strcmp(remote_username, conn->requirepeer) != 0)
+ {
+ libpq_append_conn_error(conn, "requirepeer specifies \"%s\", but actual peer user name is \"%s\"",
+ conn->requirepeer, remote_username);
+ free(remote_username);
+ goto error_return;
+ }
+ free(remote_username);
+#else /* WIN32 */
+ /* should have failed with ENOSYS above */
+ Assert(false);
+#endif /* WIN32 */
+ }
+
+ if (conn->raddr.addr.ss_family == AF_UNIX)
+ {
+ /* Don't request SSL or GSSAPI over Unix sockets */
+#ifdef USE_SSL
+ conn->allow_ssl_try = false;
+#endif
+#ifdef ENABLE_GSS
+ conn->try_gss = false;
+#endif
+ }
+
+#ifdef ENABLE_GSS
+
+ /*
+ * If GSSAPI encryption is enabled, then call
+ * pg_GSS_have_cred_cache() which will return true if we can
+ * acquire credentials (and give us a handle to use in
+ * conn->gcred), and then send a packet to the server asking
+ * for GSSAPI Encryption (and skip past SSL negotiation and
+ * regular startup below).
+ */
+ if (conn->try_gss && !conn->gctx)
+ conn->try_gss = pg_GSS_have_cred_cache(&conn->gcred);
+ if (conn->try_gss && !conn->gctx)
+ {
+ ProtocolVersion pv = pg_hton32(NEGOTIATE_GSS_CODE);
+
+ if (pqPacketSend(conn, 0, &pv, sizeof(pv)) != STATUS_OK)
+ {
+ libpq_append_conn_error(conn, "could not send GSSAPI negotiation packet: %s",
+ SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
+ goto error_return;
+ }
+
+ /* Ok, wait for response */
+ conn->status = CONNECTION_GSS_STARTUP;
+ return PGRES_POLLING_READING;
+ }
+ else if (!conn->gctx && conn->gssencmode[0] == 'r')
+ {
+ libpq_append_conn_error(conn,
+ "GSSAPI encryption required but was impossible (possibly no credential cache, no server support, or using a local socket)");
+ goto error_return;
+ }
+#endif
+
+#ifdef USE_SSL
+
+ /*
+ * Enable the libcrypto callbacks before checking if SSL needs
+ * to be done. This is done before sending the startup packet
+ * as depending on the type of authentication done, like MD5
+ * or SCRAM that use cryptohashes, the callbacks would be
+ * required even without a SSL connection
+ */
+ if (pqsecure_initialize(conn, false, true) < 0)
+ goto error_return;
+
+ /*
+ * If SSL is enabled and we haven't already got encryption of
+ * some sort running, request SSL instead of sending the
+ * startup message.
+ */
+ if (conn->allow_ssl_try && !conn->wait_ssl_try &&
+ !conn->ssl_in_use
+#ifdef ENABLE_GSS
+ && !conn->gssenc
+#endif
+ )
+ {
+ ProtocolVersion pv;
+
+ /*
+ * Send the SSL request packet.
+ *
+ * Theoretically, this could block, but it really
+ * shouldn't since we only got here if the socket is
+ * write-ready.
+ */
+ pv = pg_hton32(NEGOTIATE_SSL_CODE);
+ if (pqPacketSend(conn, 0, &pv, sizeof(pv)) != STATUS_OK)
+ {
+ libpq_append_conn_error(conn, "could not send SSL negotiation packet: %s",
+ SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
+ goto error_return;
+ }
+ /* Ok, wait for response */
+ conn->status = CONNECTION_SSL_STARTUP;
+ return PGRES_POLLING_READING;
+ }
+#endif /* USE_SSL */
+
+ /*
+ * Build the startup packet.
+ */
+ startpacket = pqBuildStartupPacket3(conn, &packetlen,
+ EnvironmentOptions);
+ if (!startpacket)
+ {
+ libpq_append_conn_error(conn, "out of memory");
+ goto error_return;
+ }
+
+ /*
+ * Send the startup packet.
+ *
+ * Theoretically, this could block, but it really shouldn't
+ * since we only got here if the socket is write-ready.
+ */
+ if (pqPacketSend(conn, 0, startpacket, packetlen) != STATUS_OK)
+ {
+ libpq_append_conn_error(conn, "could not send startup packet: %s",
+ SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
+ free(startpacket);
+ goto error_return;
+ }
+
+ free(startpacket);
+
+ conn->status = CONNECTION_AWAITING_RESPONSE;
+ return PGRES_POLLING_READING;
+ }
+
+ /*
+ * Handle SSL negotiation: wait for postmaster messages and
+ * respond as necessary.
+ */
+ case CONNECTION_SSL_STARTUP:
+ {
+#ifdef USE_SSL
+ PostgresPollingStatusType pollres;
+
+ /*
+ * On first time through, get the postmaster's response to our
+ * SSL negotiation packet.
+ */
+ if (!conn->ssl_in_use)
+ {
+ /*
+ * We use pqReadData here since it has the logic to
+ * distinguish no-data-yet from connection closure. Since
+ * conn->ssl isn't set, a plain recv() will occur.
+ */
+ char SSLok;
+ int rdresult;
+
+ rdresult = pqReadData(conn);
+ if (rdresult < 0)
+ {
+ /* errorMessage is already filled in */
+ goto error_return;
+ }
+ if (rdresult == 0)
+ {
+ /* caller failed to wait for data */
+ return PGRES_POLLING_READING;
+ }
+ if (pqGetc(&SSLok, conn) < 0)
+ {
+ /* should not happen really */
+ return PGRES_POLLING_READING;
+ }
+ if (SSLok == 'S')
+ {
+ /* mark byte consumed */
+ conn->inStart = conn->inCursor;
+
+ /*
+ * Set up global SSL state if required. The crypto
+ * state has already been set if libpq took care of
+ * doing that, so there is no need to make that happen
+ * again.
+ */
+ if (pqsecure_initialize(conn, true, false) != 0)
+ goto error_return;
+ }
+ else if (SSLok == 'N')
+ {
+ /* mark byte consumed */
+ conn->inStart = conn->inCursor;
+ /* OK to do without SSL? */
+ if (conn->sslmode[0] == 'r' || /* "require" */
+ conn->sslmode[0] == 'v') /* "verify-ca" or
+ * "verify-full" */
+ {
+ /* Require SSL, but server does not want it */
+ libpq_append_conn_error(conn, "server does not support SSL, but SSL was required");
+ goto error_return;
+ }
+ /* Otherwise, proceed with normal startup */
+ conn->allow_ssl_try = false;
+ /* We can proceed using this connection */
+ conn->status = CONNECTION_MADE;
+ return PGRES_POLLING_WRITING;
+ }
+ else if (SSLok == 'E')
+ {
+ /*
+ * Server failure of some sort, such as failure to
+ * fork a backend process. We need to process and
+ * report the error message, which might be formatted
+ * according to either protocol 2 or protocol 3.
+ * Rather than duplicate the code for that, we flip
+ * into AWAITING_RESPONSE state and let the code there
+ * deal with it. Note we have *not* consumed the "E"
+ * byte here.
+ */
+ conn->status = CONNECTION_AWAITING_RESPONSE;
+ goto keep_going;
+ }
+ else
+ {
+ libpq_append_conn_error(conn, "received invalid response to SSL negotiation: %c",
+ SSLok);
+ goto error_return;
+ }
+ }
+
+ /*
+ * Begin or continue the SSL negotiation process.
+ */
+ pollres = pqsecure_open_client(conn);
+ if (pollres == PGRES_POLLING_OK)
+ {
+ /*
+ * At this point we should have no data already buffered.
+ * If we do, it was received before we performed the SSL
+ * handshake, so it wasn't encrypted and indeed may have
+ * been injected by a man-in-the-middle.
+ */
+ if (conn->inCursor != conn->inEnd)
+ {
+ libpq_append_conn_error(conn, "received unencrypted data after SSL response");
+ goto error_return;
+ }
+
+ /* SSL handshake done, ready to send startup packet */
+ conn->status = CONNECTION_MADE;
+ return PGRES_POLLING_WRITING;
+ }
+ if (pollres == PGRES_POLLING_FAILED)
+ {
+ /*
+ * Failed ... if sslmode is "prefer" then do a non-SSL
+ * retry
+ */
+ if (conn->sslmode[0] == 'p' /* "prefer" */
+ && conn->allow_ssl_try /* redundant? */
+ && !conn->wait_ssl_try) /* redundant? */
+ {
+ /* only retry once */
+ conn->allow_ssl_try = false;
+ need_new_connection = true;
+ goto keep_going;
+ }
+ /* Else it's a hard failure */
+ goto error_return;
+ }
+ /* Else, return POLLING_READING or POLLING_WRITING status */
+ return pollres;
+#else /* !USE_SSL */
+ /* can't get here */
+ goto error_return;
+#endif /* USE_SSL */
+ }
+
+ case CONNECTION_GSS_STARTUP:
+ {
+#ifdef ENABLE_GSS
+ PostgresPollingStatusType pollres;
+
+ /*
+ * If we haven't yet, get the postmaster's response to our
+ * negotiation packet
+ */
+ if (conn->try_gss && !conn->gctx)
+ {
+ char gss_ok;
+ int rdresult = pqReadData(conn);
+
+ if (rdresult < 0)
+ /* pqReadData fills in error message */
+ goto error_return;
+ else if (rdresult == 0)
+ /* caller failed to wait for data */
+ return PGRES_POLLING_READING;
+ if (pqGetc(&gss_ok, conn) < 0)
+ /* shouldn't happen... */
+ return PGRES_POLLING_READING;
+
+ if (gss_ok == 'E')
+ {
+ /*
+ * Server failure of some sort. Assume it's a
+ * protocol version support failure, and let's see if
+ * we can't recover (if it's not, we'll get a better
+ * error message on retry). Server gets fussy if we
+ * don't hang up the socket, though.
+ */
+ conn->try_gss = false;
+ need_new_connection = true;
+ goto keep_going;
+ }
+
+ /* mark byte consumed */
+ conn->inStart = conn->inCursor;
+
+ if (gss_ok == 'N')
+ {
+ /* Server doesn't want GSSAPI; fall back if we can */
+ if (conn->gssencmode[0] == 'r')
+ {
+ libpq_append_conn_error(conn, "server doesn't support GSSAPI encryption, but it was required");
+ goto error_return;
+ }
+
+ conn->try_gss = false;
+ /* We can proceed using this connection */
+ conn->status = CONNECTION_MADE;
+ return PGRES_POLLING_WRITING;
+ }
+ else if (gss_ok != 'G')
+ {
+ libpq_append_conn_error(conn, "received invalid response to GSSAPI negotiation: %c",
+ gss_ok);
+ goto error_return;
+ }
+ }
+
+ /* Begin or continue GSSAPI negotiation */
+ pollres = pqsecure_open_gss(conn);
+ if (pollres == PGRES_POLLING_OK)
+ {
+ /*
+ * At this point we should have no data already buffered.
+ * If we do, it was received before we performed the GSS
+ * handshake, so it wasn't encrypted and indeed may have
+ * been injected by a man-in-the-middle.
+ */
+ if (conn->inCursor != conn->inEnd)
+ {
+ libpq_append_conn_error(conn, "received unencrypted data after GSSAPI encryption response");
+ goto error_return;
+ }
+
+ /* All set for startup packet */
+ conn->status = CONNECTION_MADE;
+ return PGRES_POLLING_WRITING;
+ }
+ else if (pollres == PGRES_POLLING_FAILED)
+ {
+ if (conn->gssencmode[0] == 'p')
+ {
+ /*
+ * We failed, but we can retry on "prefer". Have to
+ * drop the current connection to do so, though.
+ */
+ conn->try_gss = false;
+ need_new_connection = true;
+ goto keep_going;
+ }
+ /* Else it's a hard failure */
+ goto error_return;
+ }
+ /* Else, return POLLING_READING or POLLING_WRITING status */
+ return pollres;
+#else /* !ENABLE_GSS */
+ /* unreachable */
+ goto error_return;
+#endif /* ENABLE_GSS */
+ }
+
+ /*
+ * Handle authentication exchange: wait for postmaster messages
+ * and respond as necessary.
+ */
+ case CONNECTION_AWAITING_RESPONSE:
+ {
+ char beresp;
+ int msgLength;
+ int avail;
+ AuthRequest areq;
+ int res;
+
+ /*
+ * Scan the message from current point (note that if we find
+ * the message is incomplete, we will return without advancing
+ * inStart, and resume here next time).
+ */
+ conn->inCursor = conn->inStart;
+
+ /* Read type byte */
+ if (pqGetc(&beresp, conn))
+ {
+ /* We'll come back when there is more data */
+ return PGRES_POLLING_READING;
+ }
+
+ /*
+ * Validate message type: we expect only an authentication
+ * request, NegotiateProtocolVersion, or an error here.
+ * Anything else probably means it's not Postgres on the other
+ * end at all.
+ */
+ if (!(beresp == 'R' || beresp == 'v' || beresp == 'E'))
+ {
+ libpq_append_conn_error(conn, "expected authentication request from server, but received %c",
+ beresp);
+ goto error_return;
+ }
+
+ /* Read message length word */
+ if (pqGetInt(&msgLength, 4, conn))
+ {
+ /* We'll come back when there is more data */
+ return PGRES_POLLING_READING;
+ }
+
+ /*
+ * Try to validate message length before using it.
+ *
+ * Authentication requests can't be very large, although GSS
+ * auth requests may not be that small. Same for
+ * NegotiateProtocolVersion.
+ *
+ * Errors can be a little larger, but not huge. If we see a
+ * large apparent length in an error, it means we're really
+ * talking to a pre-3.0-protocol server; cope. (Before
+ * version 14, the server also used the old protocol for
+ * errors that happened before processing the startup packet.)
+ */
+ if (beresp == 'R' && (msgLength < 8 || msgLength > 2000))
+ {
+ libpq_append_conn_error(conn, "received invalid authentication request");
+ goto error_return;
+ }
+ if (beresp == 'v' && (msgLength < 8 || msgLength > 2000))
+ {
+ libpq_append_conn_error(conn, "received invalid protocol negotiation message");
+ goto error_return;
+ }
+
+#define MAX_ERRLEN 30000
+ if (beresp == 'E' && (msgLength < 8 || msgLength > MAX_ERRLEN))
+ {
+ /* Handle error from a pre-3.0 server */
+ conn->inCursor = conn->inStart + 1; /* reread data */
+ if (pqGets_append(&conn->errorMessage, conn))
+ {
+ /*
+ * We may not have authenticated the server yet, so
+ * don't let the buffer grow forever.
+ */
+ avail = conn->inEnd - conn->inCursor;
+ if (avail > MAX_ERRLEN)
+ {
+ libpq_append_conn_error(conn, "received invalid error message");
+ goto error_return;
+ }
+
+ /* We'll come back when there is more data */
+ return PGRES_POLLING_READING;
+ }
+ /* OK, we read the message; mark data consumed */
+ conn->inStart = conn->inCursor;
+
+ /*
+ * Before 7.2, the postmaster didn't always end its
+ * messages with a newline, so add one if needed to
+ * conform to libpq conventions.
+ */
+ if (conn->errorMessage.len == 0 ||
+ conn->errorMessage.data[conn->errorMessage.len - 1] != '\n')
+ {
+ appendPQExpBufferChar(&conn->errorMessage, '\n');
+ }
+
+ goto error_return;
+ }
+#undef MAX_ERRLEN
+
+ /*
+ * Can't process if message body isn't all here yet.
+ *
+ * After this check passes, any further EOF during parsing
+ * implies that the server sent a bad/truncated message.
+ * Reading more bytes won't help in that case, so don't return
+ * PGRES_POLLING_READING after this point.
+ */
+ msgLength -= 4;
+ avail = conn->inEnd - conn->inCursor;
+ if (avail < msgLength)
+ {
+ /*
+ * Before returning, try to enlarge the input buffer if
+ * needed to hold the whole message; see notes in
+ * pqParseInput3.
+ */
+ if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength,
+ conn))
+ goto error_return;
+ /* We'll come back when there is more data */
+ return PGRES_POLLING_READING;
+ }
+
+ /* Handle errors. */
+ if (beresp == 'E')
+ {
+ if (pqGetErrorNotice3(conn, true))
+ {
+ libpq_append_conn_error(conn, "received invalid error message");
+ goto error_return;
+ }
+ /* OK, we read the message; mark data consumed */
+ conn->inStart = conn->inCursor;
+
+ /*
+ * If error is "cannot connect now", try the next host if
+ * any (but we don't want to consider additional addresses
+ * for this host, nor is there much point in changing SSL
+ * or GSS mode). This is helpful when dealing with
+ * standby servers that might not be in hot-standby state.
+ */
+ if (strcmp(conn->last_sqlstate,
+ ERRCODE_CANNOT_CONNECT_NOW) == 0)
+ {
+ conn->try_next_host = true;
+ goto keep_going;
+ }
+
+ /* Check to see if we should mention pgpassfile */
+ pgpassfileWarning(conn);
+
+#ifdef ENABLE_GSS
+
+ /*
+ * If gssencmode is "prefer" and we're using GSSAPI, retry
+ * without it.
+ */
+ if (conn->gssenc && conn->gssencmode[0] == 'p')
+ {
+ /* only retry once */
+ conn->try_gss = false;
+ need_new_connection = true;
+ goto keep_going;
+ }
+#endif
+
+#ifdef USE_SSL
+
+ /*
+ * if sslmode is "allow" and we haven't tried an SSL
+ * connection already, then retry with an SSL connection
+ */
+ if (conn->sslmode[0] == 'a' /* "allow" */
+ && !conn->ssl_in_use
+ && conn->allow_ssl_try
+ && conn->wait_ssl_try)
+ {
+ /* only retry once */
+ conn->wait_ssl_try = false;
+ need_new_connection = true;
+ goto keep_going;
+ }
+
+ /*
+ * if sslmode is "prefer" and we're in an SSL connection,
+ * then do a non-SSL retry
+ */
+ if (conn->sslmode[0] == 'p' /* "prefer" */
+ && conn->ssl_in_use
+ && conn->allow_ssl_try /* redundant? */
+ && !conn->wait_ssl_try) /* redundant? */
+ {
+ /* only retry once */
+ conn->allow_ssl_try = false;
+ need_new_connection = true;
+ goto keep_going;
+ }
+#endif
+
+ goto error_return;
+ }
+ else if (beresp == 'v')
+ {
+ if (pqGetNegotiateProtocolVersion3(conn))
+ {
+ libpq_append_conn_error(conn, "received invalid protocol negotiation message");
+ goto error_return;
+ }
+ /* OK, we read the message; mark data consumed */
+ conn->inStart = conn->inCursor;
+ goto error_return;
+ }
+
+ /* It is an authentication request. */
+ conn->auth_req_received = true;
+
+ /* Get the type of request. */
+ if (pqGetInt((int *) &areq, 4, conn))
+ {
+ /* can't happen because we checked the length already */
+ libpq_append_conn_error(conn, "received invalid authentication request");
+ goto error_return;
+ }
+ msgLength -= 4;
+
+ /*
+ * Process the rest of the authentication request message, and
+ * respond to it if necessary.
+ *
+ * Note that conn->pghost must be non-NULL if we are going to
+ * avoid the Kerberos code doing a hostname look-up.
+ */
+ res = pg_fe_sendauth(areq, msgLength, conn);
+
+ /* OK, we have processed the message; mark data consumed */
+ conn->inStart = conn->inCursor;
+
+ if (res != STATUS_OK)
+ goto error_return;
+
+ /*
+ * Just make sure that any data sent by pg_fe_sendauth is
+ * flushed out. Although this theoretically could block, it
+ * really shouldn't since we don't send large auth responses.
+ */
+ if (pqFlush(conn))
+ goto error_return;
+
+ if (areq == AUTH_REQ_OK)
+ {
+ /* We are done with authentication exchange */
+ conn->status = CONNECTION_AUTH_OK;
+
+ /*
+ * Set asyncStatus so that PQgetResult will think that
+ * what comes back next is the result of a query. See
+ * below.
+ */
+ conn->asyncStatus = PGASYNC_BUSY;
+ }
+
+ /* Look to see if we have more data yet. */
+ goto keep_going;
+ }
+
+ case CONNECTION_AUTH_OK:
+ {
+ /*
+ * Now we expect to hear from the backend. A ReadyForQuery
+ * message indicates that startup is successful, but we might
+ * also get an Error message indicating failure. (Notice
+ * messages indicating nonfatal warnings are also allowed by
+ * the protocol, as are ParameterStatus and BackendKeyData
+ * messages.) Easiest way to handle this is to let
+ * PQgetResult() read the messages. We just have to fake it
+ * out about the state of the connection, by setting
+ * asyncStatus = PGASYNC_BUSY (done above).
+ */
+
+ if (PQisBusy(conn))
+ return PGRES_POLLING_READING;
+
+ res = PQgetResult(conn);
+
+ /*
+ * NULL return indicating we have gone to IDLE state is
+ * expected
+ */
+ if (res)
+ {
+ if (res->resultStatus != PGRES_FATAL_ERROR)
+ libpq_append_conn_error(conn, "unexpected message from server during startup");
+ else if (conn->send_appname &&
+ (conn->appname || conn->fbappname))
+ {
+ /*
+ * If we tried to send application_name, check to see
+ * if the error is about that --- pre-9.0 servers will
+ * reject it at this stage of the process. If so,
+ * close the connection and retry without sending
+ * application_name. We could possibly get a false
+ * SQLSTATE match here and retry uselessly, but there
+ * seems no great harm in that; we'll just get the
+ * same error again if it's unrelated.
+ */
+ const char *sqlstate;
+
+ sqlstate = PQresultErrorField(res, PG_DIAG_SQLSTATE);
+ if (sqlstate &&
+ strcmp(sqlstate, ERRCODE_APPNAME_UNKNOWN) == 0)
+ {
+ PQclear(res);
+ conn->send_appname = false;
+ need_new_connection = true;
+ goto keep_going;
+ }
+ }
+
+ /*
+ * if the resultStatus is FATAL, then conn->errorMessage
+ * already has a copy of the error; needn't copy it back.
+ * But add a newline if it's not there already, since
+ * postmaster error messages may not have one.
+ */
+ if (conn->errorMessage.len <= 0 ||
+ conn->errorMessage.data[conn->errorMessage.len - 1] != '\n')
+ appendPQExpBufferChar(&conn->errorMessage, '\n');
+ PQclear(res);
+ goto error_return;
+ }
+
+ /* Almost there now ... */
+ conn->status = CONNECTION_CHECK_TARGET;
+ goto keep_going;
+ }
+
+ case CONNECTION_CHECK_TARGET:
+ {
+ /*
+ * If a read-write, read-only, primary, or standby connection
+ * is required, see if we have one.
+ */
+ if (conn->target_server_type == SERVER_TYPE_READ_WRITE ||
+ conn->target_server_type == SERVER_TYPE_READ_ONLY)
+ {
+ bool read_only_server;
+
+ /*
+ * If the server didn't report
+ * "default_transaction_read_only" or "in_hot_standby" at
+ * startup, we must determine its state by sending the
+ * query "SHOW transaction_read_only". This GUC exists in
+ * all server versions that support 3.0 protocol.
+ */
+ if (conn->default_transaction_read_only == PG_BOOL_UNKNOWN ||
+ conn->in_hot_standby == PG_BOOL_UNKNOWN)
+ {
+ /*
+ * We use PQsendQueryContinue so that
+ * conn->errorMessage does not get cleared. We need
+ * to preserve any error messages related to previous
+ * hosts we have tried and failed to connect to.
+ */
+ conn->status = CONNECTION_OK;
+ if (!PQsendQueryContinue(conn,
+ "SHOW transaction_read_only"))
+ goto error_return;
+ /* We'll return to this state when we have the answer */
+ conn->status = CONNECTION_CHECK_WRITABLE;
+ return PGRES_POLLING_READING;
+ }
+
+ /* OK, we can make the test */
+ read_only_server =
+ (conn->default_transaction_read_only == PG_BOOL_YES ||
+ conn->in_hot_standby == PG_BOOL_YES);
+
+ if ((conn->target_server_type == SERVER_TYPE_READ_WRITE) ?
+ read_only_server : !read_only_server)
+ {
+ /* Wrong server state, reject and try the next host */
+ if (conn->target_server_type == SERVER_TYPE_READ_WRITE)
+ libpq_append_conn_error(conn, "session is read-only");
+ else
+ libpq_append_conn_error(conn, "session is not read-only");
+
+ /* Close connection politely. */
+ conn->status = CONNECTION_OK;
+ sendTerminateConn(conn);
+
+ /*
+ * Try next host if any, but we don't want to consider
+ * additional addresses for this host.
+ */
+ conn->try_next_host = true;
+ goto keep_going;
+ }
+ }
+ else if (conn->target_server_type == SERVER_TYPE_PRIMARY ||
+ conn->target_server_type == SERVER_TYPE_STANDBY ||
+ conn->target_server_type == SERVER_TYPE_PREFER_STANDBY)
+ {
+ /*
+ * If the server didn't report "in_hot_standby" at
+ * startup, we must determine its state by sending the
+ * query "SELECT pg_catalog.pg_is_in_recovery()". Servers
+ * before 9.0 don't have that function, but by the same
+ * token they don't have any standby mode, so we may just
+ * assume the result.
+ */
+ if (conn->sversion < 90000)
+ conn->in_hot_standby = PG_BOOL_NO;
+
+ if (conn->in_hot_standby == PG_BOOL_UNKNOWN)
+ {
+ /*
+ * We use PQsendQueryContinue so that
+ * conn->errorMessage does not get cleared. We need
+ * to preserve any error messages related to previous
+ * hosts we have tried and failed to connect to.
+ */
+ conn->status = CONNECTION_OK;
+ if (!PQsendQueryContinue(conn,
+ "SELECT pg_catalog.pg_is_in_recovery()"))
+ goto error_return;
+ /* We'll return to this state when we have the answer */
+ conn->status = CONNECTION_CHECK_STANDBY;
+ return PGRES_POLLING_READING;
+ }
+
+ /* OK, we can make the test */
+ if ((conn->target_server_type == SERVER_TYPE_PRIMARY) ?
+ (conn->in_hot_standby == PG_BOOL_YES) :
+ (conn->in_hot_standby == PG_BOOL_NO))
+ {
+ /* Wrong server state, reject and try the next host */
+ if (conn->target_server_type == SERVER_TYPE_PRIMARY)
+ libpq_append_conn_error(conn, "server is in hot standby mode");
+ else
+ libpq_append_conn_error(conn, "server is not in hot standby mode");
+
+ /* Close connection politely. */
+ conn->status = CONNECTION_OK;
+ sendTerminateConn(conn);
+
+ /*
+ * Try next host if any, but we don't want to consider
+ * additional addresses for this host.
+ */
+ conn->try_next_host = true;
+ goto keep_going;
+ }
+ }
+
+ /* We can release the address list now. */
+ release_conn_addrinfo(conn);
+
+ /*
+ * Contents of conn->errorMessage are no longer interesting
+ * (and it seems some clients expect it to be empty after a
+ * successful connection).
+ */
+ pqClearConnErrorState(conn);
+
+ /* We are open for business! */
+ conn->status = CONNECTION_OK;
+ return PGRES_POLLING_OK;
+ }
+
+ case CONNECTION_CONSUME:
+ {
+ /*
+ * This state just makes sure the connection is idle after
+ * we've obtained the result of a SHOW or SELECT query. Once
+ * we're clear, return to CONNECTION_CHECK_TARGET state to
+ * decide what to do next. We must transiently set status =
+ * CONNECTION_OK in order to use the result-consuming
+ * subroutines.
+ */
+ conn->status = CONNECTION_OK;
+ if (!PQconsumeInput(conn))
+ goto error_return;
+
+ if (PQisBusy(conn))
+ {
+ conn->status = CONNECTION_CONSUME;
+ return PGRES_POLLING_READING;
+ }
+
+ /* Call PQgetResult() again until we get a NULL result */
+ res = PQgetResult(conn);
+ if (res != NULL)
+ {
+ PQclear(res);
+ conn->status = CONNECTION_CONSUME;
+ return PGRES_POLLING_READING;
+ }
+
+ conn->status = CONNECTION_CHECK_TARGET;
+ goto keep_going;
+ }
+
+ case CONNECTION_CHECK_WRITABLE:
+ {
+ /*
+ * Waiting for result of "SHOW transaction_read_only". We
+ * must transiently set status = CONNECTION_OK in order to use
+ * the result-consuming subroutines.
+ */
+ conn->status = CONNECTION_OK;
+ if (!PQconsumeInput(conn))
+ goto error_return;
+
+ if (PQisBusy(conn))
+ {
+ conn->status = CONNECTION_CHECK_WRITABLE;
+ return PGRES_POLLING_READING;
+ }
+
+ res = PQgetResult(conn);
+ if (res && PQresultStatus(res) == PGRES_TUPLES_OK &&
+ PQntuples(res) == 1)
+ {
+ char *val = PQgetvalue(res, 0, 0);
+
+ /*
+ * "transaction_read_only = on" proves that at least one
+ * of default_transaction_read_only and in_hot_standby is
+ * on, but we don't actually know which. We don't care
+ * though for the purpose of identifying a read-only
+ * session, so satisfy the CONNECTION_CHECK_TARGET code by
+ * claiming they are both on. On the other hand, if it's
+ * a read-write session, they are certainly both off.
+ */
+ if (strncmp(val, "on", 2) == 0)
+ {
+ conn->default_transaction_read_only = PG_BOOL_YES;
+ conn->in_hot_standby = PG_BOOL_YES;
+ }
+ else
+ {
+ conn->default_transaction_read_only = PG_BOOL_NO;
+ conn->in_hot_standby = PG_BOOL_NO;
+ }
+ PQclear(res);
+
+ /* Finish reading messages before continuing */
+ conn->status = CONNECTION_CONSUME;
+ goto keep_going;
+ }
+
+ /* Something went wrong with "SHOW transaction_read_only". */
+ PQclear(res);
+
+ /* Append error report to conn->errorMessage. */
+ libpq_append_conn_error(conn, "\"%s\" failed",
+ "SHOW transaction_read_only");
+
+ /* Close connection politely. */
+ conn->status = CONNECTION_OK;
+ sendTerminateConn(conn);
+
+ /* Try next host. */
+ conn->try_next_host = true;
+ goto keep_going;
+ }
+
+ case CONNECTION_CHECK_STANDBY:
+ {
+ /*
+ * Waiting for result of "SELECT pg_is_in_recovery()". We
+ * must transiently set status = CONNECTION_OK in order to use
+ * the result-consuming subroutines.
+ */
+ conn->status = CONNECTION_OK;
+ if (!PQconsumeInput(conn))
+ goto error_return;
+
+ if (PQisBusy(conn))
+ {
+ conn->status = CONNECTION_CHECK_STANDBY;
+ return PGRES_POLLING_READING;
+ }
+
+ res = PQgetResult(conn);
+ if (res && PQresultStatus(res) == PGRES_TUPLES_OK &&
+ PQntuples(res) == 1)
+ {
+ char *val = PQgetvalue(res, 0, 0);
+
+ if (strncmp(val, "t", 1) == 0)
+ conn->in_hot_standby = PG_BOOL_YES;
+ else
+ conn->in_hot_standby = PG_BOOL_NO;
+ PQclear(res);
+
+ /* Finish reading messages before continuing */
+ conn->status = CONNECTION_CONSUME;
+ goto keep_going;
+ }
+
+ /* Something went wrong with "SELECT pg_is_in_recovery()". */
+ PQclear(res);
+
+ /* Append error report to conn->errorMessage. */
+ libpq_append_conn_error(conn, "\"%s\" failed",
+ "SELECT pg_is_in_recovery()");
+
+ /* Close connection politely. */
+ conn->status = CONNECTION_OK;
+ sendTerminateConn(conn);
+
+ /* Try next host. */
+ conn->try_next_host = true;
+ goto keep_going;
+ }
+
+ default:
+ libpq_append_conn_error(conn,
+ "invalid connection state %d, probably indicative of memory corruption",
+ conn->status);
+ goto error_return;
+ }
+
+ /* Unreachable */
+
+error_return:
+
+ /*
+ * We used to close the socket at this point, but that makes it awkward
+ * for those above us if they wish to remove this socket from their own
+ * records (an fd_set for example). We'll just have this socket closed
+ * when PQfinish is called (which is compulsory even after an error, since
+ * the connection structure must be freed).
+ */
+ conn->status = CONNECTION_BAD;
+ return PGRES_POLLING_FAILED;
+}
+
+
+/*
+ * internal_ping
+ * Determine if a server is running and if we can connect to it.
+ *
+ * The argument is a connection that's been started, but not completed.
+ */
+static PGPing
+internal_ping(PGconn *conn)
+{
+ /* Say "no attempt" if we never got to PQconnectPoll */
+ if (!conn || !conn->options_valid)
+ return PQPING_NO_ATTEMPT;
+
+ /* Attempt to complete the connection */
+ if (conn->status != CONNECTION_BAD)
+ (void) connectDBComplete(conn);
+
+ /* Definitely OK if we succeeded */
+ if (conn->status != CONNECTION_BAD)
+ return PQPING_OK;
+
+ /*
+ * Here begins the interesting part of "ping": determine the cause of the
+ * failure in sufficient detail to decide what to return. We do not want
+ * to report that the server is not up just because we didn't have a valid
+ * password, for example. In fact, any sort of authentication request
+ * implies the server is up. (We need this check since the libpq side of
+ * things might have pulled the plug on the connection before getting an
+ * error as such from the postmaster.)
+ */
+ if (conn->auth_req_received)
+ return PQPING_OK;
+
+ /*
+ * If we failed to get any ERROR response from the postmaster, report
+ * PQPING_NO_RESPONSE. This result could be somewhat misleading for a
+ * pre-7.4 server, since it won't send back a SQLSTATE, but those are long
+ * out of support. Another corner case where the server could return a
+ * failure without a SQLSTATE is fork failure, but PQPING_NO_RESPONSE
+ * isn't totally unreasonable for that anyway. We expect that every other
+ * failure case in a modern server will produce a report with a SQLSTATE.
+ *
+ * NOTE: whenever we get around to making libpq generate SQLSTATEs for
+ * client-side errors, we should either not store those into
+ * last_sqlstate, or add an extra flag so we can tell client-side errors
+ * apart from server-side ones.
+ */
+ if (strlen(conn->last_sqlstate) != 5)
+ return PQPING_NO_RESPONSE;
+
+ /*
+ * Report PQPING_REJECT if server says it's not accepting connections.
+ */
+ if (strcmp(conn->last_sqlstate, ERRCODE_CANNOT_CONNECT_NOW) == 0)
+ return PQPING_REJECT;
+
+ /*
+ * Any other SQLSTATE can be taken to indicate that the server is up.
+ * Presumably it didn't like our username, password, or database name; or
+ * perhaps it had some transient failure, but that should not be taken as
+ * meaning "it's down".
+ */
+ return PQPING_OK;
+}
+
+
+/*
+ * makeEmptyPGconn
+ * - create a PGconn data structure with (as yet) no interesting data
+ */
+static PGconn *
+makeEmptyPGconn(void)
+{
+ PGconn *conn;
+
+#ifdef WIN32
+
+ /*
+ * Make sure socket support is up and running in this process.
+ *
+ * Note: the Windows documentation says that we should eventually do a
+ * matching WSACleanup() call, but experience suggests that that is at
+ * least as likely to cause problems as fix them. So we don't.
+ */
+ static bool wsastartup_done = false;
+
+ if (!wsastartup_done)
+ {
+ WSADATA wsaData;
+
+ if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
+ return NULL;
+ wsastartup_done = true;
+ }
+
+ /* Forget any earlier error */
+ WSASetLastError(0);
+#endif /* WIN32 */
+
+ conn = (PGconn *) malloc(sizeof(PGconn));
+ if (conn == NULL)
+ return conn;
+
+ /* Zero all pointers and booleans */
+ MemSet(conn, 0, sizeof(PGconn));
+
+ /* install default notice hooks */
+ conn->noticeHooks.noticeRec = defaultNoticeReceiver;
+ conn->noticeHooks.noticeProc = defaultNoticeProcessor;
+
+ conn->status = CONNECTION_BAD;
+ conn->asyncStatus = PGASYNC_IDLE;
+ conn->pipelineStatus = PQ_PIPELINE_OFF;
+ conn->xactStatus = PQTRANS_IDLE;
+ conn->options_valid = false;
+ conn->nonblocking = false;
+ conn->client_encoding = PG_SQL_ASCII;
+ conn->std_strings = false; /* unless server says differently */
+ conn->default_transaction_read_only = PG_BOOL_UNKNOWN;
+ conn->in_hot_standby = PG_BOOL_UNKNOWN;
+ conn->scram_sha_256_iterations = SCRAM_SHA_256_DEFAULT_ITERATIONS;
+ conn->verbosity = PQERRORS_DEFAULT;
+ conn->show_context = PQSHOW_CONTEXT_ERRORS;
+ conn->sock = PGINVALID_SOCKET;
+ conn->Pfdebug = NULL;
+
+ /*
+ * We try to send at least 8K at a time, which is the usual size of pipe
+ * buffers on Unix systems. That way, when we are sending a large amount
+ * of data, we avoid incurring extra kernel context swaps for partial
+ * bufferloads. The output buffer is initially made 16K in size, and we
+ * try to dump it after accumulating 8K.
+ *
+ * With the same goal of minimizing context swaps, the input buffer will
+ * be enlarged anytime it has less than 8K free, so we initially allocate
+ * twice that.
+ */
+ conn->inBufSize = 16 * 1024;
+ conn->inBuffer = (char *) malloc(conn->inBufSize);
+ conn->outBufSize = 16 * 1024;
+ conn->outBuffer = (char *) malloc(conn->outBufSize);
+ conn->rowBufLen = 32;
+ conn->rowBuf = (PGdataValue *) malloc(conn->rowBufLen * sizeof(PGdataValue));
+ initPQExpBuffer(&conn->errorMessage);
+ initPQExpBuffer(&conn->workBuffer);
+
+ if (conn->inBuffer == NULL ||
+ conn->outBuffer == NULL ||
+ conn->rowBuf == NULL ||
+ PQExpBufferBroken(&conn->errorMessage) ||
+ PQExpBufferBroken(&conn->workBuffer))
+ {
+ /* out of memory already :-( */
+ freePGconn(conn);
+ conn = NULL;
+ }
+
+ return conn;
+}
+
+/*
+ * freePGconn
+ * - free an idle (closed) PGconn data structure
+ *
+ * NOTE: this should not overlap any functionality with closePGconn().
+ * Clearing/resetting of transient state belongs there; what we do here is
+ * release data that is to be held for the life of the PGconn structure.
+ * If a value ought to be cleared/freed during PQreset(), do it there not here.
+ */
+static void
+freePGconn(PGconn *conn)
+{
+ /* let any event procs clean up their state data */
+ for (int i = 0; i < conn->nEvents; i++)
+ {
+ PGEventConnDestroy evt;
+
+ evt.conn = conn;
+ (void) conn->events[i].proc(PGEVT_CONNDESTROY, &evt,
+ conn->events[i].passThrough);
+ free(conn->events[i].name);
+ }
+
+ /* clean up pg_conn_host structures */
+ for (int i = 0; i < conn->nconnhost; ++i)
+ {
+ free(conn->connhost[i].host);
+ free(conn->connhost[i].hostaddr);
+ free(conn->connhost[i].port);
+ if (conn->connhost[i].password != NULL)
+ {
+ explicit_bzero(conn->connhost[i].password, strlen(conn->connhost[i].password));
+ free(conn->connhost[i].password);
+ }
+ }
+ free(conn->connhost);
+
+ free(conn->client_encoding_initial);
+ free(conn->events);
+ free(conn->pghost);
+ free(conn->pghostaddr);
+ free(conn->pgport);
+ free(conn->connect_timeout);
+ free(conn->pgtcp_user_timeout);
+ free(conn->pgoptions);
+ free(conn->appname);
+ free(conn->fbappname);
+ free(conn->dbName);
+ free(conn->replication);
+ free(conn->pguser);
+ if (conn->pgpass)
+ {
+ explicit_bzero(conn->pgpass, strlen(conn->pgpass));
+ free(conn->pgpass);
+ }
+ free(conn->pgpassfile);
+ free(conn->channel_binding);
+ free(conn->keepalives);
+ free(conn->keepalives_idle);
+ free(conn->keepalives_interval);
+ free(conn->keepalives_count);
+ free(conn->sslmode);
+ free(conn->sslcert);
+ free(conn->sslkey);
+ if (conn->sslpassword)
+ {
+ explicit_bzero(conn->sslpassword, strlen(conn->sslpassword));
+ free(conn->sslpassword);
+ }
+ free(conn->sslcertmode);
+ free(conn->sslrootcert);
+ free(conn->sslcrl);
+ free(conn->sslcrldir);
+ free(conn->sslcompression);
+ free(conn->sslsni);
+ free(conn->requirepeer);
+ free(conn->require_auth);
+ free(conn->ssl_min_protocol_version);
+ free(conn->ssl_max_protocol_version);
+ free(conn->gssencmode);
+ free(conn->krbsrvname);
+ free(conn->gsslib);
+ free(conn->gssdelegation);
+ free(conn->connip);
+ /* Note that conn->Pfdebug is not ours to close or free */
+ free(conn->write_err_msg);
+ free(conn->inBuffer);
+ free(conn->outBuffer);
+ free(conn->rowBuf);
+ free(conn->target_session_attrs);
+ free(conn->load_balance_hosts);
+ termPQExpBuffer(&conn->errorMessage);
+ termPQExpBuffer(&conn->workBuffer);
+
+ free(conn);
+}
+
+/*
+ * store_conn_addrinfo
+ * - copy addrinfo to PGconn object
+ *
+ * Copies the addrinfos from addrlist to the PGconn object such that the
+ * addrinfos can be manipulated by libpq. Returns a positive integer on
+ * failure, otherwise zero.
+ */
+static int
+store_conn_addrinfo(PGconn *conn, struct addrinfo *addrlist)
+{
+ struct addrinfo *ai = addrlist;
+
+ conn->whichaddr = 0;
+
+ conn->naddr = 0;
+ while (ai)
+ {
+ ai = ai->ai_next;
+ conn->naddr++;
+ }
+
+ conn->addr = calloc(conn->naddr, sizeof(AddrInfo));
+ if (conn->addr == NULL)
+ {
+ libpq_append_conn_error(conn, "out of memory");
+ return 1;
+ }
+
+ ai = addrlist;
+ for (int i = 0; i < conn->naddr; i++)
+ {
+ conn->addr[i].family = ai->ai_family;
+
+ memcpy(&conn->addr[i].addr.addr, ai->ai_addr,
+ ai->ai_addrlen);
+ conn->addr[i].addr.salen = ai->ai_addrlen;
+ ai = ai->ai_next;
+ }
+
+ return 0;
+}
+
+/*
+ * release_conn_addrinfo
+ * - Free any addrinfo list in the PGconn.
+ */
+static void
+release_conn_addrinfo(PGconn *conn)
+{
+ if (conn->addr)
+ {
+ free(conn->addr);
+ conn->addr = NULL;
+ }
+}
+
+/*
+ * sendTerminateConn
+ * - Send a terminate message to backend.
+ */
+static void
+sendTerminateConn(PGconn *conn)
+{
+ /*
+ * Note that the protocol doesn't allow us to send Terminate messages
+ * during the startup phase.
+ */
+ if (conn->sock != PGINVALID_SOCKET && conn->status == CONNECTION_OK)
+ {
+ /*
+ * Try to send "close connection" message to backend. Ignore any
+ * error.
+ */
+ pqPutMsgStart('X', conn);
+ pqPutMsgEnd(conn);
+ (void) pqFlush(conn);
+ }
+}
+
+/*
+ * closePGconn
+ * - properly close a connection to the backend
+ *
+ * This should reset or release all transient state, but NOT the connection
+ * parameters. On exit, the PGconn should be in condition to start a fresh
+ * connection with the same parameters (see PQreset()).
+ */
+static void
+closePGconn(PGconn *conn)
+{
+ /*
+ * If possible, send Terminate message to close the connection politely.
+ */
+ sendTerminateConn(conn);
+
+ /*
+ * Must reset the blocking status so a possible reconnect will work.
+ *
+ * Don't call PQsetnonblocking() because it will fail if it's unable to
+ * flush the connection.
+ */
+ conn->nonblocking = false;
+
+ /*
+ * Close the connection, reset all transient state, flush I/O buffers.
+ * Note that this includes clearing conn's error state; we're no longer
+ * interested in any failures associated with the old connection, and we
+ * want a clean slate for any new connection attempt.
+ */
+ pqDropConnection(conn, true);
+ conn->status = CONNECTION_BAD; /* Well, not really _bad_ - just absent */
+ conn->asyncStatus = PGASYNC_IDLE;
+ conn->xactStatus = PQTRANS_IDLE;
+ conn->pipelineStatus = PQ_PIPELINE_OFF;
+ pqClearAsyncResult(conn); /* deallocate result */
+ pqClearConnErrorState(conn);
+ release_conn_addrinfo(conn);
+
+ /* Reset all state obtained from server, too */
+ pqDropServerData(conn);
+}
+
+/*
+ * PQfinish: properly close a connection to the backend. Also frees
+ * the PGconn data structure so it shouldn't be re-used after this.
+ */
+void
+PQfinish(PGconn *conn)
+{
+ if (conn)
+ {
+ closePGconn(conn);
+ freePGconn(conn);
+ }
+}
+
+/*
+ * PQreset: resets the connection to the backend by closing the
+ * existing connection and creating a new one.
+ */
+void
+PQreset(PGconn *conn)
+{
+ if (conn)
+ {
+ closePGconn(conn);
+
+ if (connectDBStart(conn) && connectDBComplete(conn))
+ {
+ /*
+ * Notify event procs of successful reset.
+ */
+ int i;
+
+ for (i = 0; i < conn->nEvents; i++)
+ {
+ PGEventConnReset evt;
+
+ evt.conn = conn;
+ (void) conn->events[i].proc(PGEVT_CONNRESET, &evt,
+ conn->events[i].passThrough);
+ }
+ }
+ }
+}
+
+
+/*
+ * PQresetStart:
+ * resets the connection to the backend
+ * closes the existing connection and makes a new one
+ * Returns 1 on success, 0 on failure.
+ */
+int
+PQresetStart(PGconn *conn)
+{
+ if (conn)
+ {
+ closePGconn(conn);
+
+ return connectDBStart(conn);
+ }
+
+ return 0;
+}
+
+
+/*
+ * PQresetPoll:
+ * resets the connection to the backend
+ * closes the existing connection and makes a new one
+ */
+PostgresPollingStatusType
+PQresetPoll(PGconn *conn)
+{
+ if (conn)
+ {
+ PostgresPollingStatusType status = PQconnectPoll(conn);
+
+ if (status == PGRES_POLLING_OK)
+ {
+ /*
+ * Notify event procs of successful reset.
+ */
+ int i;
+
+ for (i = 0; i < conn->nEvents; i++)
+ {
+ PGEventConnReset evt;
+
+ evt.conn = conn;
+ (void) conn->events[i].proc(PGEVT_CONNRESET, &evt,
+ conn->events[i].passThrough);
+ }
+ }
+
+ return status;
+ }
+
+ return PGRES_POLLING_FAILED;
+}
+
+/*
+ * PQgetCancel: get a PGcancel structure corresponding to a connection.
+ *
+ * A copy is needed to be able to cancel a running query from a different
+ * thread. If the same structure is used all structure members would have
+ * to be individually locked (if the entire structure was locked, it would
+ * be impossible to cancel a synchronous query because the structure would
+ * have to stay locked for the duration of the query).
+ */
+PGcancel *
+PQgetCancel(PGconn *conn)
+{
+ PGcancel *cancel;
+
+ if (!conn)
+ return NULL;
+
+ if (conn->sock == PGINVALID_SOCKET)
+ return NULL;
+
+ cancel = malloc(sizeof(PGcancel));
+ if (cancel == NULL)
+ return NULL;
+
+ memcpy(&cancel->raddr, &conn->raddr, sizeof(SockAddr));
+ cancel->be_pid = conn->be_pid;
+ cancel->be_key = conn->be_key;
+ /* We use -1 to indicate an unset connection option */
+ cancel->pgtcp_user_timeout = -1;
+ cancel->keepalives = -1;
+ cancel->keepalives_idle = -1;
+ cancel->keepalives_interval = -1;
+ cancel->keepalives_count = -1;
+ if (conn->pgtcp_user_timeout != NULL)
+ {
+ if (!parse_int_param(conn->pgtcp_user_timeout,
+ &cancel->pgtcp_user_timeout,
+ conn, "tcp_user_timeout"))
+ goto fail;
+ }
+ if (conn->keepalives != NULL)
+ {
+ if (!parse_int_param(conn->keepalives,
+ &cancel->keepalives,
+ conn, "keepalives"))
+ goto fail;
+ }
+ if (conn->keepalives_idle != NULL)
+ {
+ if (!parse_int_param(conn->keepalives_idle,
+ &cancel->keepalives_idle,
+ conn, "keepalives_idle"))
+ goto fail;
+ }
+ if (conn->keepalives_interval != NULL)
+ {
+ if (!parse_int_param(conn->keepalives_interval,
+ &cancel->keepalives_interval,
+ conn, "keepalives_interval"))
+ goto fail;
+ }
+ if (conn->keepalives_count != NULL)
+ {
+ if (!parse_int_param(conn->keepalives_count,
+ &cancel->keepalives_count,
+ conn, "keepalives_count"))
+ goto fail;
+ }
+
+ return cancel;
+
+fail:
+ free(cancel);
+ return NULL;
+}
+
+/* PQfreeCancel: free a cancel structure */
+void
+PQfreeCancel(PGcancel *cancel)
+{
+ free(cancel);
+}
+
+
+/*
+ * Sets an integer socket option on a TCP socket, if the provided value is
+ * not negative. Returns false if setsockopt fails for some reason.
+ *
+ * CAUTION: This needs to be signal safe, since it's used by PQcancel.
+ */
+#if defined(TCP_USER_TIMEOUT) || !defined(WIN32)
+static bool
+optional_setsockopt(int fd, int protoid, int optid, int value)
+{
+ if (value < 0)
+ return true;
+ if (setsockopt(fd, protoid, optid, (char *) &value, sizeof(value)) < 0)
+ return false;
+ return true;
+}
+#endif
+
+
+/*
+ * PQcancel: request query cancel
+ *
+ * The return value is true if the cancel request was successfully
+ * dispatched, false if not (in which case an error message is available).
+ * Note: successful dispatch is no guarantee that there will be any effect at
+ * the backend. The application must read the operation result as usual.
+ *
+ * On failure, an error message is stored in *errbuf, which must be of size
+ * errbufsize (recommended size is 256 bytes). *errbuf is not changed on
+ * success return.
+ *
+ * CAUTION: we want this routine to be safely callable from a signal handler
+ * (for example, an application might want to call it in a SIGINT handler).
+ * This means we cannot use any C library routine that might be non-reentrant.
+ * malloc/free are often non-reentrant, and anything that might call them is
+ * just as dangerous. We avoid sprintf here for that reason. Building up
+ * error messages with strcpy/strcat is tedious but should be quite safe.
+ * We also save/restore errno in case the signal handler support doesn't.
+ */
+int
+PQcancel(PGcancel *cancel, char *errbuf, int errbufsize)
+{
+ int save_errno = SOCK_ERRNO;
+ pgsocket tmpsock = PGINVALID_SOCKET;
+ int maxlen;
+ struct
+ {
+ uint32 packetlen;
+ CancelRequestPacket cp;
+ } crp;
+
+ if (!cancel)
+ {
+ strlcpy(errbuf, "PQcancel() -- no cancel object supplied", errbufsize);
+ /* strlcpy probably doesn't change errno, but be paranoid */
+ SOCK_ERRNO_SET(save_errno);
+ return false;
+ }
+
+ /*
+ * We need to open a temporary connection to the postmaster. Do this with
+ * only kernel calls.
+ */
+ if ((tmpsock = socket(cancel->raddr.addr.ss_family, SOCK_STREAM, 0)) == PGINVALID_SOCKET)
+ {
+ strlcpy(errbuf, "PQcancel() -- socket() failed: ", errbufsize);
+ goto cancel_errReturn;
+ }
+
+ /*
+ * Since this connection will only be used to send a single packet of
+ * data, we don't need NODELAY. We also don't set the socket to
+ * nonblocking mode, because the API definition of PQcancel requires the
+ * cancel to be sent in a blocking way.
+ *
+ * We do set socket options related to keepalives and other TCP timeouts.
+ * This ensures that this function does not block indefinitely when
+ * reasonable keepalive and timeout settings have been provided.
+ */
+ if (cancel->raddr.addr.ss_family != AF_UNIX &&
+ cancel->keepalives != 0)
+ {
+#ifndef WIN32
+ if (!optional_setsockopt(tmpsock, SOL_SOCKET, SO_KEEPALIVE, 1))
+ {
+ strlcpy(errbuf, "PQcancel() -- setsockopt(SO_KEEPALIVE) failed: ", errbufsize);
+ goto cancel_errReturn;
+ }
+
+#ifdef PG_TCP_KEEPALIVE_IDLE
+ if (!optional_setsockopt(tmpsock, IPPROTO_TCP, PG_TCP_KEEPALIVE_IDLE,
+ cancel->keepalives_idle))
+ {
+ strlcpy(errbuf, "PQcancel() -- setsockopt(" PG_TCP_KEEPALIVE_IDLE_STR ") failed: ", errbufsize);
+ goto cancel_errReturn;
+ }
+#endif
+
+#ifdef TCP_KEEPINTVL
+ if (!optional_setsockopt(tmpsock, IPPROTO_TCP, TCP_KEEPINTVL,
+ cancel->keepalives_interval))
+ {
+ strlcpy(errbuf, "PQcancel() -- setsockopt(TCP_KEEPINTVL) failed: ", errbufsize);
+ goto cancel_errReturn;
+ }
+#endif
+
+#ifdef TCP_KEEPCNT
+ if (!optional_setsockopt(tmpsock, IPPROTO_TCP, TCP_KEEPCNT,
+ cancel->keepalives_count))
+ {
+ strlcpy(errbuf, "PQcancel() -- setsockopt(TCP_KEEPCNT) failed: ", errbufsize);
+ goto cancel_errReturn;
+ }
+#endif
+
+#else /* WIN32 */
+
+#ifdef SIO_KEEPALIVE_VALS
+ if (!setKeepalivesWin32(tmpsock,
+ cancel->keepalives_idle,
+ cancel->keepalives_interval))
+ {
+ strlcpy(errbuf, "PQcancel() -- WSAIoctl(SIO_KEEPALIVE_VALS) failed: ", errbufsize);
+ goto cancel_errReturn;
+ }
+#endif /* SIO_KEEPALIVE_VALS */
+#endif /* WIN32 */
+
+ /* TCP_USER_TIMEOUT works the same way on Unix and Windows */
+#ifdef TCP_USER_TIMEOUT
+ if (!optional_setsockopt(tmpsock, IPPROTO_TCP, TCP_USER_TIMEOUT,
+ cancel->pgtcp_user_timeout))
+ {
+ strlcpy(errbuf, "PQcancel() -- setsockopt(TCP_USER_TIMEOUT) failed: ", errbufsize);
+ goto cancel_errReturn;
+ }
+#endif
+ }
+
+retry3:
+ if (connect(tmpsock, (struct sockaddr *) &cancel->raddr.addr,
+ cancel->raddr.salen) < 0)
+ {
+ if (SOCK_ERRNO == EINTR)
+ /* Interrupted system call - we'll just try again */
+ goto retry3;
+ strlcpy(errbuf, "PQcancel() -- connect() failed: ", errbufsize);
+ goto cancel_errReturn;
+ }
+
+ /* Create and send the cancel request packet. */
+
+ crp.packetlen = pg_hton32((uint32) sizeof(crp));
+ crp.cp.cancelRequestCode = (MsgType) pg_hton32(CANCEL_REQUEST_CODE);
+ crp.cp.backendPID = pg_hton32(cancel->be_pid);
+ crp.cp.cancelAuthCode = pg_hton32(cancel->be_key);
+
+retry4:
+ if (send(tmpsock, (char *) &crp, sizeof(crp), 0) != (int) sizeof(crp))
+ {
+ if (SOCK_ERRNO == EINTR)
+ /* Interrupted system call - we'll just try again */
+ goto retry4;
+ strlcpy(errbuf, "PQcancel() -- send() failed: ", errbufsize);
+ goto cancel_errReturn;
+ }
+
+ /*
+ * Wait for the postmaster to close the connection, which indicates that
+ * it's processed the request. Without this delay, we might issue another
+ * command only to find that our cancel zaps that command instead of the
+ * one we thought we were canceling. Note we don't actually expect this
+ * read to obtain any data, we are just waiting for EOF to be signaled.
+ */
+retry5:
+ if (recv(tmpsock, (char *) &crp, 1, 0) < 0)
+ {
+ if (SOCK_ERRNO == EINTR)
+ /* Interrupted system call - we'll just try again */
+ goto retry5;
+ /* we ignore other error conditions */
+ }
+
+ /* All done */
+ closesocket(tmpsock);
+ SOCK_ERRNO_SET(save_errno);
+ return true;
+
+cancel_errReturn:
+
+ /*
+ * Make sure we don't overflow the error buffer. Leave space for the \n at
+ * the end, and for the terminating zero.
+ */
+ maxlen = errbufsize - strlen(errbuf) - 2;
+ if (maxlen >= 0)
+ {
+ /*
+ * We can't invoke strerror here, since it's not signal-safe. Settle
+ * for printing the decimal value of errno. Even that has to be done
+ * the hard way.
+ */
+ int val = SOCK_ERRNO;
+ char buf[32];
+ char *bufp;
+
+ bufp = buf + sizeof(buf) - 1;
+ *bufp = '\0';
+ do
+ {
+ *(--bufp) = (val % 10) + '0';
+ val /= 10;
+ } while (val > 0);
+ bufp -= 6;
+ memcpy(bufp, "error ", 6);
+ strncat(errbuf, bufp, maxlen);
+ strcat(errbuf, "\n");
+ }
+ if (tmpsock != PGINVALID_SOCKET)
+ closesocket(tmpsock);
+ SOCK_ERRNO_SET(save_errno);
+ return false;
+}
+
+
+/*
+ * PQrequestCancel: old, not thread-safe function for requesting query cancel
+ *
+ * Returns true if able to send the cancel request, false if not.
+ *
+ * On failure, the error message is saved in conn->errorMessage; this means
+ * that this can't be used when there might be other active operations on
+ * the connection object.
+ *
+ * NOTE: error messages will be cut off at the current size of the
+ * error message buffer, since we dare not try to expand conn->errorMessage!
+ */
+int
+PQrequestCancel(PGconn *conn)
+{
+ int r;
+ PGcancel *cancel;
+
+ /* Check we have an open connection */
+ if (!conn)
+ return false;
+
+ if (conn->sock == PGINVALID_SOCKET)
+ {
+ strlcpy(conn->errorMessage.data,
+ "PQrequestCancel() -- connection is not open\n",
+ conn->errorMessage.maxlen);
+ conn->errorMessage.len = strlen(conn->errorMessage.data);
+ conn->errorReported = 0;
+
+ return false;
+ }
+
+ cancel = PQgetCancel(conn);
+ if (cancel)
+ {
+ r = PQcancel(cancel, conn->errorMessage.data,
+ conn->errorMessage.maxlen);
+ PQfreeCancel(cancel);
+ }
+ else
+ {
+ strlcpy(conn->errorMessage.data, "out of memory",
+ conn->errorMessage.maxlen);
+ r = false;
+ }
+
+ if (!r)
+ {
+ conn->errorMessage.len = strlen(conn->errorMessage.data);
+ conn->errorReported = 0;
+ }
+
+ return r;
+}
+
+
+/*
+ * pqPacketSend() -- convenience routine to send a message to server.
+ *
+ * pack_type: the single-byte message type code. (Pass zero for startup
+ * packets, which have no message type code.)
+ *
+ * buf, buf_len: contents of message. The given length includes only what
+ * is in buf; the message type and message length fields are added here.
+ *
+ * RETURNS: STATUS_ERROR if the write fails, STATUS_OK otherwise.
+ * SIDE_EFFECTS: may block.
+ */
+int
+pqPacketSend(PGconn *conn, char pack_type,
+ const void *buf, size_t buf_len)
+{
+ /* Start the message. */
+ if (pqPutMsgStart(pack_type, conn))
+ return STATUS_ERROR;
+
+ /* Send the message body. */
+ if (pqPutnchar(buf, buf_len, conn))
+ return STATUS_ERROR;
+
+ /* Finish the message. */
+ if (pqPutMsgEnd(conn))
+ return STATUS_ERROR;
+
+ /* Flush to ensure backend gets it. */
+ if (pqFlush(conn))
+ return STATUS_ERROR;
+
+ return STATUS_OK;
+}
+
+#ifdef USE_LDAP
+
+#define LDAP_URL "ldap://"
+#define LDAP_DEF_PORT 389
+#define PGLDAP_TIMEOUT 2
+
+#define ld_is_sp_tab(x) ((x) == ' ' || (x) == '\t')
+#define ld_is_nl_cr(x) ((x) == '\r' || (x) == '\n')
+
+
+/*
+ * ldapServiceLookup
+ *
+ * Search the LDAP URL passed as first argument, treat the result as a
+ * string of connection options that are parsed and added to the array of
+ * options passed as second argument.
+ *
+ * LDAP URLs must conform to RFC 1959 without escape sequences.
+ * ldap://host:port/dn?attributes?scope?filter?extensions
+ *
+ * Returns
+ * 0 if the lookup was successful,
+ * 1 if the connection to the LDAP server could be established but
+ * the search was unsuccessful,
+ * 2 if a connection could not be established, and
+ * 3 if a fatal error occurred.
+ *
+ * An error message is appended to *errorMessage for return codes 1 and 3.
+ */
+static int
+ldapServiceLookup(const char *purl, PQconninfoOption *options,
+ PQExpBuffer errorMessage)
+{
+ int port = LDAP_DEF_PORT,
+ scope,
+ rc,
+ size,
+ state,
+ oldstate,
+ i;
+#ifndef WIN32
+ int msgid;
+#endif
+ bool found_keyword;
+ char *url,
+ *hostname,
+ *portstr,
+ *endptr,
+ *dn,
+ *scopestr,
+ *filter,
+ *result,
+ *p,
+ *p1 = NULL,
+ *optname = NULL,
+ *optval = NULL;
+ char *attrs[2] = {NULL, NULL};
+ LDAP *ld = NULL;
+ LDAPMessage *res,
+ *entry;
+ struct berval **values;
+ LDAP_TIMEVAL time = {PGLDAP_TIMEOUT, 0};
+
+ if ((url = strdup(purl)) == NULL)
+ {
+ libpq_append_error(errorMessage, "out of memory");
+ return 3;
+ }
+
+ /*
+ * Parse URL components, check for correctness. Basically, url has '\0'
+ * placed at component boundaries and variables are pointed at each
+ * component.
+ */
+
+ if (pg_strncasecmp(url, LDAP_URL, strlen(LDAP_URL)) != 0)
+ {
+ libpq_append_error(errorMessage,
+ "invalid LDAP URL \"%s\": scheme must be ldap://", purl);
+ free(url);
+ return 3;
+ }
+
+ /* hostname */
+ hostname = url + strlen(LDAP_URL);
+ if (*hostname == '/') /* no hostname? */
+ hostname = DefaultHost; /* the default */
+
+ /* dn, "distinguished name" */
+ p = strchr(url + strlen(LDAP_URL), '/');
+ if (p == NULL || *(p + 1) == '\0' || *(p + 1) == '?')
+ {
+ libpq_append_error(errorMessage,
+ "invalid LDAP URL \"%s\": missing distinguished name",
+ purl);
+ free(url);
+ return 3;
+ }
+ *p = '\0'; /* terminate hostname */
+ dn = p + 1;
+
+ /* attribute */
+ if ((p = strchr(dn, '?')) == NULL || *(p + 1) == '\0' || *(p + 1) == '?')
+ {
+ libpq_append_error(errorMessage,
+ "invalid LDAP URL \"%s\": must have exactly one attribute",
+ purl);
+ free(url);
+ return 3;
+ }
+ *p = '\0';
+ attrs[0] = p + 1;
+
+ /* scope */
+ if ((p = strchr(attrs[0], '?')) == NULL || *(p + 1) == '\0' || *(p + 1) == '?')
+ {
+ libpq_append_error(errorMessage,
+ "invalid LDAP URL \"%s\": must have search scope (base/one/sub)",
+ purl);
+ free(url);
+ return 3;
+ }
+ *p = '\0';
+ scopestr = p + 1;
+
+ /* filter */
+ if ((p = strchr(scopestr, '?')) == NULL || *(p + 1) == '\0' || *(p + 1) == '?')
+ {
+ libpq_append_error(errorMessage,
+ "invalid LDAP URL \"%s\": no filter",
+ purl);
+ free(url);
+ return 3;
+ }
+ *p = '\0';
+ filter = p + 1;
+ if ((p = strchr(filter, '?')) != NULL)
+ *p = '\0';
+
+ /* port number? */
+ if ((p1 = strchr(hostname, ':')) != NULL)
+ {
+ long lport;
+
+ *p1 = '\0';
+ portstr = p1 + 1;
+ errno = 0;
+ lport = strtol(portstr, &endptr, 10);
+ if (*portstr == '\0' || *endptr != '\0' || errno || lport < 0 || lport > 65535)
+ {
+ libpq_append_error(errorMessage,
+ "invalid LDAP URL \"%s\": invalid port number",
+ purl);
+ free(url);
+ return 3;
+ }
+ port = (int) lport;
+ }
+
+ /* Allow only one attribute */
+ if (strchr(attrs[0], ',') != NULL)
+ {
+ libpq_append_error(errorMessage,
+ "invalid LDAP URL \"%s\": must have exactly one attribute",
+ purl);
+ free(url);
+ return 3;
+ }
+
+ /* set scope */
+ if (pg_strcasecmp(scopestr, "base") == 0)
+ scope = LDAP_SCOPE_BASE;
+ else if (pg_strcasecmp(scopestr, "one") == 0)
+ scope = LDAP_SCOPE_ONELEVEL;
+ else if (pg_strcasecmp(scopestr, "sub") == 0)
+ scope = LDAP_SCOPE_SUBTREE;
+ else
+ {
+ libpq_append_error(errorMessage,
+ "invalid LDAP URL \"%s\": must have search scope (base/one/sub)",
+ purl);
+ free(url);
+ return 3;
+ }
+
+ /* initialize LDAP structure */
+ if ((ld = ldap_init(hostname, port)) == NULL)
+ {
+ libpq_append_error(errorMessage, "could not create LDAP structure");
+ free(url);
+ return 3;
+ }
+
+ /*
+ * Perform an explicit anonymous bind.
+ *
+ * LDAP does not require that an anonymous bind is performed explicitly,
+ * but we want to distinguish between the case where LDAP bind does not
+ * succeed within PGLDAP_TIMEOUT seconds (return 2 to continue parsing the
+ * service control file) and the case where querying the LDAP server fails
+ * (return 1 to end parsing).
+ *
+ * Unfortunately there is no way of setting a timeout that works for both
+ * Windows and OpenLDAP.
+ */
+#ifdef WIN32
+ /* the nonstandard ldap_connect function performs an anonymous bind */
+ if (ldap_connect(ld, &time) != LDAP_SUCCESS)
+ {
+ /* error or timeout in ldap_connect */
+ free(url);
+ ldap_unbind(ld);
+ return 2;
+ }
+#else /* !WIN32 */
+ /* in OpenLDAP, use the LDAP_OPT_NETWORK_TIMEOUT option */
+ if (ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT, &time) != LDAP_SUCCESS)
+ {
+ free(url);
+ ldap_unbind(ld);
+ return 3;
+ }
+
+ /* anonymous bind */
+ if ((msgid = ldap_simple_bind(ld, NULL, NULL)) == -1)
+ {
+ /* error or network timeout */
+ free(url);
+ ldap_unbind(ld);
+ return 2;
+ }
+
+ /* wait some time for the connection to succeed */
+ res = NULL;
+ if ((rc = ldap_result(ld, msgid, LDAP_MSG_ALL, &time, &res)) == -1 ||
+ res == NULL)
+ {
+ /* error or timeout */
+ if (res != NULL)
+ ldap_msgfree(res);
+ free(url);
+ ldap_unbind(ld);
+ return 2;
+ }
+ ldap_msgfree(res);
+
+ /* reset timeout */
+ time.tv_sec = -1;
+ if (ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT, &time) != LDAP_SUCCESS)
+ {
+ free(url);
+ ldap_unbind(ld);
+ return 3;
+ }
+#endif /* WIN32 */
+
+ /* search */
+ res = NULL;
+ if ((rc = ldap_search_st(ld, dn, scope, filter, attrs, 0, &time, &res))
+ != LDAP_SUCCESS)
+ {
+ if (res != NULL)
+ ldap_msgfree(res);
+ libpq_append_error(errorMessage, "lookup on LDAP server failed: %s", ldap_err2string(rc));
+ ldap_unbind(ld);
+ free(url);
+ return 1;
+ }
+
+ /* complain if there was not exactly one result */
+ if ((rc = ldap_count_entries(ld, res)) != 1)
+ {
+ if (rc > 1)
+ libpq_append_error(errorMessage, "more than one entry found on LDAP lookup");
+ else
+ libpq_append_error(errorMessage, "no entry found on LDAP lookup");
+ ldap_msgfree(res);
+ ldap_unbind(ld);
+ free(url);
+ return 1;
+ }
+
+ /* get entry */
+ if ((entry = ldap_first_entry(ld, res)) == NULL)
+ {
+ /* should never happen */
+ libpq_append_error(errorMessage, "no entry found on LDAP lookup");
+ ldap_msgfree(res);
+ ldap_unbind(ld);
+ free(url);
+ return 1;
+ }
+
+ /* get values */
+ if ((values = ldap_get_values_len(ld, entry, attrs[0])) == NULL)
+ {
+ libpq_append_error(errorMessage, "attribute has no values on LDAP lookup");
+ ldap_msgfree(res);
+ ldap_unbind(ld);
+ free(url);
+ return 1;
+ }
+
+ ldap_msgfree(res);
+ free(url);
+
+ if (values[0] == NULL)
+ {
+ libpq_append_error(errorMessage, "attribute has no values on LDAP lookup");
+ ldap_value_free_len(values);
+ ldap_unbind(ld);
+ return 1;
+ }
+
+ /* concatenate values into a single string with newline terminators */
+ size = 1; /* for the trailing null */
+ for (i = 0; values[i] != NULL; i++)
+ size += values[i]->bv_len + 1;
+ if ((result = malloc(size)) == NULL)
+ {
+ libpq_append_error(errorMessage, "out of memory");
+ ldap_value_free_len(values);
+ ldap_unbind(ld);
+ return 3;
+ }
+ p = result;
+ for (i = 0; values[i] != NULL; i++)
+ {
+ memcpy(p, values[i]->bv_val, values[i]->bv_len);
+ p += values[i]->bv_len;
+ *(p++) = '\n';
+ }
+ *p = '\0';
+
+ ldap_value_free_len(values);
+ ldap_unbind(ld);
+
+ /* parse result string */
+ oldstate = state = 0;
+ for (p = result; *p != '\0'; ++p)
+ {
+ switch (state)
+ {
+ case 0: /* between entries */
+ if (!ld_is_sp_tab(*p) && !ld_is_nl_cr(*p))
+ {
+ optname = p;
+ state = 1;
+ }
+ break;
+ case 1: /* in option name */
+ if (ld_is_sp_tab(*p))
+ {
+ *p = '\0';
+ state = 2;
+ }
+ else if (ld_is_nl_cr(*p))
+ {
+ libpq_append_error(errorMessage,
+ "missing \"=\" after \"%s\" in connection info string",
+ optname);
+ free(result);
+ return 3;
+ }
+ else if (*p == '=')
+ {
+ *p = '\0';
+ state = 3;
+ }
+ break;
+ case 2: /* after option name */
+ if (*p == '=')
+ {
+ state = 3;
+ }
+ else if (!ld_is_sp_tab(*p))
+ {
+ libpq_append_error(errorMessage,
+ "missing \"=\" after \"%s\" in connection info string",
+ optname);
+ free(result);
+ return 3;
+ }
+ break;
+ case 3: /* before option value */
+ if (*p == '\'')
+ {
+ optval = p + 1;
+ p1 = p + 1;
+ state = 5;
+ }
+ else if (ld_is_nl_cr(*p))
+ {
+ optval = optname + strlen(optname); /* empty */
+ state = 0;
+ }
+ else if (!ld_is_sp_tab(*p))
+ {
+ optval = p;
+ state = 4;
+ }
+ break;
+ case 4: /* in unquoted option value */
+ if (ld_is_sp_tab(*p) || ld_is_nl_cr(*p))
+ {
+ *p = '\0';
+ state = 0;
+ }
+ break;
+ case 5: /* in quoted option value */
+ if (*p == '\'')
+ {
+ *p1 = '\0';
+ state = 0;
+ }
+ else if (*p == '\\')
+ state = 6;
+ else
+ *(p1++) = *p;
+ break;
+ case 6: /* in quoted option value after escape */
+ *(p1++) = *p;
+ state = 5;
+ break;
+ }
+
+ if (state == 0 && oldstate != 0)
+ {
+ found_keyword = false;
+ for (i = 0; options[i].keyword; i++)
+ {
+ if (strcmp(options[i].keyword, optname) == 0)
+ {
+ if (options[i].val == NULL)
+ {
+ options[i].val = strdup(optval);
+ if (!options[i].val)
+ {
+ libpq_append_error(errorMessage, "out of memory");
+ free(result);
+ return 3;
+ }
+ }
+ found_keyword = true;
+ break;
+ }
+ }
+ if (!found_keyword)
+ {
+ libpq_append_error(errorMessage, "invalid connection option \"%s\"", optname);
+ free(result);
+ return 1;
+ }
+ optname = NULL;
+ optval = NULL;
+ }
+ oldstate = state;
+ }
+
+ free(result);
+
+ if (state == 5 || state == 6)
+ {
+ libpq_append_error(errorMessage,
+ "unterminated quoted string in connection info string");
+ return 3;
+ }
+
+ return 0;
+}
+
+#endif /* USE_LDAP */
+
+/*
+ * parseServiceInfo: if a service name has been given, look it up and absorb
+ * connection options from it into *options.
+ *
+ * Returns 0 on success, nonzero on failure. On failure, if errorMessage
+ * isn't null, also store an error message there. (Note: the only reason
+ * this function and related ones don't dump core on errorMessage == NULL
+ * is the undocumented fact that appendPQExpBuffer does nothing when passed
+ * a null PQExpBuffer pointer.)
+ */
+static int
+parseServiceInfo(PQconninfoOption *options, PQExpBuffer errorMessage)
+{
+ const char *service = conninfo_getval(options, "service");
+ char serviceFile[MAXPGPATH];
+ char *env;
+ bool group_found = false;
+ int status;
+ struct stat stat_buf;
+
+ /*
+ * We have to special-case the environment variable PGSERVICE here, since
+ * this is and should be called before inserting environment defaults for
+ * other connection options.
+ */
+ if (service == NULL)
+ service = getenv("PGSERVICE");
+
+ /* If no service name given, nothing to do */
+ if (service == NULL)
+ return 0;
+
+ /*
+ * Try PGSERVICEFILE if specified, else try ~/.pg_service.conf (if that
+ * exists).
+ */
+ if ((env = getenv("PGSERVICEFILE")) != NULL)
+ strlcpy(serviceFile, env, sizeof(serviceFile));
+ else
+ {
+ char homedir[MAXPGPATH];
+
+ if (!pqGetHomeDirectory(homedir, sizeof(homedir)))
+ goto next_file;
+ snprintf(serviceFile, MAXPGPATH, "%s/%s", homedir, ".pg_service.conf");
+ if (stat(serviceFile, &stat_buf) != 0)
+ goto next_file;
+ }
+
+ status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found);
+ if (group_found || status != 0)
+ return status;
+
+next_file:
+
+ /*
+ * This could be used by any application so we can't use the binary
+ * location to find our config files.
+ */
+ snprintf(serviceFile, MAXPGPATH, "%s/pg_service.conf",
+ getenv("PGSYSCONFDIR") ? getenv("PGSYSCONFDIR") : SYSCONFDIR);
+ if (stat(serviceFile, &stat_buf) != 0)
+ goto last_file;
+
+ status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found);
+ if (status != 0)
+ return status;
+
+last_file:
+ if (!group_found)
+ {
+ libpq_append_error(errorMessage, "definition of service \"%s\" not found", service);
+ return 3;
+ }
+
+ return 0;
+}
+
+static int
+parseServiceFile(const char *serviceFile,
+ const char *service,
+ PQconninfoOption *options,
+ PQExpBuffer errorMessage,
+ bool *group_found)
+{
+ int result = 0,
+ linenr = 0,
+ i;
+ FILE *f;
+ char *line;
+ char buf[1024];
+
+ *group_found = false;
+
+ f = fopen(serviceFile, "r");
+ if (f == NULL)
+ {
+ libpq_append_error(errorMessage, "service file \"%s\" not found", serviceFile);
+ return 1;
+ }
+
+ while ((line = fgets(buf, sizeof(buf), f)) != NULL)
+ {
+ int len;
+
+ linenr++;
+
+ if (strlen(line) >= sizeof(buf) - 1)
+ {
+ libpq_append_error(errorMessage,
+ "line %d too long in service file \"%s\"",
+ linenr,
+ serviceFile);
+ result = 2;
+ goto exit;
+ }
+
+ /* ignore whitespace at end of line, especially the newline */
+ len = strlen(line);
+ while (len > 0 && isspace((unsigned char) line[len - 1]))
+ line[--len] = '\0';
+
+ /* ignore leading whitespace too */
+ while (*line && isspace((unsigned char) line[0]))
+ line++;
+
+ /* ignore comments and empty lines */
+ if (line[0] == '\0' || line[0] == '#')
+ continue;
+
+ /* Check for right groupname */
+ if (line[0] == '[')
+ {
+ if (*group_found)
+ {
+ /* end of desired group reached; return success */
+ goto exit;
+ }
+
+ if (strncmp(line + 1, service, strlen(service)) == 0 &&
+ line[strlen(service) + 1] == ']')
+ *group_found = true;
+ else
+ *group_found = false;
+ }
+ else
+ {
+ if (*group_found)
+ {
+ /*
+ * Finally, we are in the right group and can parse the line
+ */
+ char *key,
+ *val;
+ bool found_keyword;
+
+#ifdef USE_LDAP
+ if (strncmp(line, "ldap", 4) == 0)
+ {
+ int rc = ldapServiceLookup(line, options, errorMessage);
+
+ /* if rc = 2, go on reading for fallback */
+ switch (rc)
+ {
+ case 0:
+ goto exit;
+ case 1:
+ case 3:
+ result = 3;
+ goto exit;
+ case 2:
+ continue;
+ }
+ }
+#endif
+
+ key = line;
+ val = strchr(line, '=');
+ if (val == NULL)
+ {
+ libpq_append_error(errorMessage,
+ "syntax error in service file \"%s\", line %d",
+ serviceFile,
+ linenr);
+ result = 3;
+ goto exit;
+ }
+ *val++ = '\0';
+
+ if (strcmp(key, "service") == 0)
+ {
+ libpq_append_error(errorMessage,
+ "nested service specifications not supported in service file \"%s\", line %d",
+ serviceFile,
+ linenr);
+ result = 3;
+ goto exit;
+ }
+
+ /*
+ * Set the parameter --- but don't override any previous
+ * explicit setting.
+ */
+ found_keyword = false;
+ for (i = 0; options[i].keyword; i++)
+ {
+ if (strcmp(options[i].keyword, key) == 0)
+ {
+ if (options[i].val == NULL)
+ options[i].val = strdup(val);
+ if (!options[i].val)
+ {
+ libpq_append_error(errorMessage, "out of memory");
+ result = 3;
+ goto exit;
+ }
+ found_keyword = true;
+ break;
+ }
+ }
+
+ if (!found_keyword)
+ {
+ libpq_append_error(errorMessage,
+ "syntax error in service file \"%s\", line %d",
+ serviceFile,
+ linenr);
+ result = 3;
+ goto exit;
+ }
+ }
+ }
+ }
+
+exit:
+ fclose(f);
+
+ return result;
+}
+
+
+/*
+ * PQconninfoParse
+ *
+ * Parse a string like PQconnectdb() would do and return the
+ * resulting connection options array. NULL is returned on failure.
+ * The result contains only options specified directly in the string,
+ * not any possible default values.
+ *
+ * If errmsg isn't NULL, *errmsg is set to NULL on success, or a malloc'd
+ * string on failure (use PQfreemem to free it). In out-of-memory conditions
+ * both *errmsg and the result could be NULL.
+ *
+ * NOTE: the returned array is dynamically allocated and should
+ * be freed when no longer needed via PQconninfoFree().
+ */
+PQconninfoOption *
+PQconninfoParse(const char *conninfo, char **errmsg)
+{
+ PQExpBufferData errorBuf;
+ PQconninfoOption *connOptions;
+
+ if (errmsg)
+ *errmsg = NULL; /* default */
+ initPQExpBuffer(&errorBuf);
+ if (PQExpBufferDataBroken(errorBuf))
+ return NULL; /* out of memory already :-( */
+ connOptions = parse_connection_string(conninfo, &errorBuf, false);
+ if (connOptions == NULL && errmsg)
+ *errmsg = errorBuf.data;
+ else
+ termPQExpBuffer(&errorBuf);
+ return connOptions;
+}
+
+/*
+ * Build a working copy of the constant PQconninfoOptions array.
+ */
+static PQconninfoOption *
+conninfo_init(PQExpBuffer errorMessage)
+{
+ PQconninfoOption *options;
+ PQconninfoOption *opt_dest;
+ const internalPQconninfoOption *cur_opt;
+
+ /*
+ * Get enough memory for all options in PQconninfoOptions, even if some
+ * end up being filtered out.
+ */
+ options = (PQconninfoOption *) malloc(sizeof(PQconninfoOption) * sizeof(PQconninfoOptions) / sizeof(PQconninfoOptions[0]));
+ if (options == NULL)
+ {
+ libpq_append_error(errorMessage, "out of memory");
+ return NULL;
+ }
+ opt_dest = options;
+
+ for (cur_opt = PQconninfoOptions; cur_opt->keyword; cur_opt++)
+ {
+ /* Only copy the public part of the struct, not the full internal */
+ memcpy(opt_dest, cur_opt, sizeof(PQconninfoOption));
+ opt_dest++;
+ }
+ MemSet(opt_dest, 0, sizeof(PQconninfoOption));
+
+ return options;
+}
+
+/*
+ * Connection string parser
+ *
+ * Returns a malloc'd PQconninfoOption array, if parsing is successful.
+ * Otherwise, NULL is returned and an error message is added to errorMessage.
+ *
+ * If use_defaults is true, default values are filled in (from a service file,
+ * environment variables, etc).
+ */
+static PQconninfoOption *
+parse_connection_string(const char *connstr, PQExpBuffer errorMessage,
+ bool use_defaults)
+{
+ /* Parse as URI if connection string matches URI prefix */
+ if (uri_prefix_length(connstr) != 0)
+ return conninfo_uri_parse(connstr, errorMessage, use_defaults);
+
+ /* Parse as default otherwise */
+ return conninfo_parse(connstr, errorMessage, use_defaults);
+}
+
+/*
+ * Checks if connection string starts with either of the valid URI prefix
+ * designators.
+ *
+ * Returns the URI prefix length, 0 if the string doesn't contain a URI prefix.
+ *
+ * XXX this is duplicated in psql/common.c.
+ */
+static int
+uri_prefix_length(const char *connstr)
+{
+ if (strncmp(connstr, uri_designator,
+ sizeof(uri_designator) - 1) == 0)
+ return sizeof(uri_designator) - 1;
+
+ if (strncmp(connstr, short_uri_designator,
+ sizeof(short_uri_designator) - 1) == 0)
+ return sizeof(short_uri_designator) - 1;
+
+ return 0;
+}
+
+/*
+ * Recognized connection string either starts with a valid URI prefix or
+ * contains a "=" in it.
+ *
+ * Must be consistent with parse_connection_string: anything for which this
+ * returns true should at least look like it's parseable by that routine.
+ *
+ * XXX this is duplicated in psql/common.c
+ */
+static bool
+recognized_connection_string(const char *connstr)
+{
+ return uri_prefix_length(connstr) != 0 || strchr(connstr, '=') != NULL;
+}
+
+/*
+ * Subroutine for parse_connection_string
+ *
+ * Deal with a string containing key=value pairs.
+ */
+static PQconninfoOption *
+conninfo_parse(const char *conninfo, PQExpBuffer errorMessage,
+ bool use_defaults)
+{
+ char *pname;
+ char *pval;
+ char *buf;
+ char *cp;
+ char *cp2;
+ PQconninfoOption *options;
+
+ /* Make a working copy of PQconninfoOptions */
+ options = conninfo_init(errorMessage);
+ if (options == NULL)
+ return NULL;
+
+ /* Need a modifiable copy of the input string */
+ if ((buf = strdup(conninfo)) == NULL)
+ {
+ libpq_append_error(errorMessage, "out of memory");
+ PQconninfoFree(options);
+ return NULL;
+ }
+ cp = buf;
+
+ while (*cp)
+ {
+ /* Skip blanks before the parameter name */
+ if (isspace((unsigned char) *cp))
+ {
+ cp++;
+ continue;
+ }
+
+ /* Get the parameter name */
+ pname = cp;
+ while (*cp)
+ {
+ if (*cp == '=')
+ break;
+ if (isspace((unsigned char) *cp))
+ {
+ *cp++ = '\0';
+ while (*cp)
+ {
+ if (!isspace((unsigned char) *cp))
+ break;
+ cp++;
+ }
+ break;
+ }
+ cp++;
+ }
+
+ /* Check that there is a following '=' */
+ if (*cp != '=')
+ {
+ libpq_append_error(errorMessage,
+ "missing \"=\" after \"%s\" in connection info string",
+ pname);
+ PQconninfoFree(options);
+ free(buf);
+ return NULL;
+ }
+ *cp++ = '\0';
+
+ /* Skip blanks after the '=' */
+ while (*cp)
+ {
+ if (!isspace((unsigned char) *cp))
+ break;
+ cp++;
+ }
+
+ /* Get the parameter value */
+ pval = cp;
+
+ if (*cp != '\'')
+ {
+ cp2 = pval;
+ while (*cp)
+ {
+ if (isspace((unsigned char) *cp))
+ {
+ *cp++ = '\0';
+ break;
+ }
+ if (*cp == '\\')
+ {
+ cp++;
+ if (*cp != '\0')
+ *cp2++ = *cp++;
+ }
+ else
+ *cp2++ = *cp++;
+ }
+ *cp2 = '\0';
+ }
+ else
+ {
+ cp2 = pval;
+ cp++;
+ for (;;)
+ {
+ if (*cp == '\0')
+ {
+ libpq_append_error(errorMessage, "unterminated quoted string in connection info string");
+ PQconninfoFree(options);
+ free(buf);
+ return NULL;
+ }
+ if (*cp == '\\')
+ {
+ cp++;
+ if (*cp != '\0')
+ *cp2++ = *cp++;
+ continue;
+ }
+ if (*cp == '\'')
+ {
+ *cp2 = '\0';
+ cp++;
+ break;
+ }
+ *cp2++ = *cp++;
+ }
+ }
+
+ /*
+ * Now that we have the name and the value, store the record.
+ */
+ if (!conninfo_storeval(options, pname, pval, errorMessage, false, false))
+ {
+ PQconninfoFree(options);
+ free(buf);
+ return NULL;
+ }
+ }
+
+ /* Done with the modifiable input string */
+ free(buf);
+
+ /*
+ * Add in defaults if the caller wants that.
+ */
+ if (use_defaults)
+ {
+ if (!conninfo_add_defaults(options, errorMessage))
+ {
+ PQconninfoFree(options);
+ return NULL;
+ }
+ }
+
+ return options;
+}
+
+/*
+ * Conninfo array parser routine
+ *
+ * If successful, a malloc'd PQconninfoOption array is returned.
+ * If not successful, NULL is returned and an error message is
+ * appended to errorMessage.
+ * Defaults are supplied (from a service file, environment variables, etc)
+ * for unspecified options, but only if use_defaults is true.
+ *
+ * If expand_dbname is non-zero, and the value passed for the first occurrence
+ * of "dbname" keyword is a connection string (as indicated by
+ * recognized_connection_string) then parse and process it, overriding any
+ * previously processed conflicting keywords. Subsequent keywords will take
+ * precedence, however. In-tree programs generally specify expand_dbname=true,
+ * so command-line arguments naming a database can use a connection string.
+ * Some code acquires arbitrary database names from known-literal sources like
+ * PQdb(), PQconninfoParse() and pg_database.datname. When connecting to such
+ * a database, in-tree code first wraps the name in a connection string.
+ */
+static PQconninfoOption *
+conninfo_array_parse(const char *const *keywords, const char *const *values,
+ PQExpBuffer errorMessage, bool use_defaults,
+ int expand_dbname)
+{
+ PQconninfoOption *options;
+ PQconninfoOption *dbname_options = NULL;
+ PQconninfoOption *option;
+ int i = 0;
+
+ /*
+ * If expand_dbname is non-zero, check keyword "dbname" to see if val is
+ * actually a recognized connection string.
+ */
+ while (expand_dbname && keywords[i])
+ {
+ const char *pname = keywords[i];
+ const char *pvalue = values[i];
+
+ /* first find "dbname" if any */
+ if (strcmp(pname, "dbname") == 0 && pvalue)
+ {
+ /*
+ * If value is a connection string, parse it, but do not use
+ * defaults here -- those get picked up later. We only want to
+ * override for those parameters actually passed.
+ */
+ if (recognized_connection_string(pvalue))
+ {
+ dbname_options = parse_connection_string(pvalue, errorMessage, false);
+ if (dbname_options == NULL)
+ return NULL;
+ }
+ break;
+ }
+ ++i;
+ }
+
+ /* Make a working copy of PQconninfoOptions */
+ options = conninfo_init(errorMessage);
+ if (options == NULL)
+ {
+ PQconninfoFree(dbname_options);
+ return NULL;
+ }
+
+ /* Parse the keywords/values arrays */
+ i = 0;
+ while (keywords[i])
+ {
+ const char *pname = keywords[i];
+ const char *pvalue = values[i];
+
+ if (pvalue != NULL && pvalue[0] != '\0')
+ {
+ /* Search for the param record */
+ for (option = options; option->keyword != NULL; option++)
+ {
+ if (strcmp(option->keyword, pname) == 0)
+ break;
+ }
+
+ /* Check for invalid connection option */
+ if (option->keyword == NULL)
+ {
+ libpq_append_error(errorMessage, "invalid connection option \"%s\"", pname);
+ PQconninfoFree(options);
+ PQconninfoFree(dbname_options);
+ return NULL;
+ }
+
+ /*
+ * If we are on the first dbname parameter, and we have a parsed
+ * connection string, copy those parameters across, overriding any
+ * existing previous settings.
+ */
+ if (strcmp(pname, "dbname") == 0 && dbname_options)
+ {
+ PQconninfoOption *str_option;
+
+ for (str_option = dbname_options; str_option->keyword != NULL; str_option++)
+ {
+ if (str_option->val != NULL)
+ {
+ int k;
+
+ for (k = 0; options[k].keyword; k++)
+ {
+ if (strcmp(options[k].keyword, str_option->keyword) == 0)
+ {
+ free(options[k].val);
+ options[k].val = strdup(str_option->val);
+ if (!options[k].val)
+ {
+ libpq_append_error(errorMessage, "out of memory");
+ PQconninfoFree(options);
+ PQconninfoFree(dbname_options);
+ return NULL;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ /*
+ * Forget the parsed connection string, so that any subsequent
+ * dbname parameters will not be expanded.
+ */
+ PQconninfoFree(dbname_options);
+ dbname_options = NULL;
+ }
+ else
+ {
+ /*
+ * Store the value, overriding previous settings
+ */
+ free(option->val);
+ option->val = strdup(pvalue);
+ if (!option->val)
+ {
+ libpq_append_error(errorMessage, "out of memory");
+ PQconninfoFree(options);
+ PQconninfoFree(dbname_options);
+ return NULL;
+ }
+ }
+ }
+ ++i;
+ }
+ PQconninfoFree(dbname_options);
+
+ /*
+ * Add in defaults if the caller wants that.
+ */
+ if (use_defaults)
+ {
+ if (!conninfo_add_defaults(options, errorMessage))
+ {
+ PQconninfoFree(options);
+ return NULL;
+ }
+ }
+
+ return options;
+}
+
+/*
+ * Add the default values for any unspecified options to the connection
+ * options array.
+ *
+ * Defaults are obtained from a service file, environment variables, etc.
+ *
+ * Returns true if successful, otherwise false; errorMessage, if supplied,
+ * is filled in upon failure. Note that failure to locate a default value
+ * is not an error condition here --- we just leave the option's value as
+ * NULL.
+ */
+static bool
+conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
+{
+ PQconninfoOption *option;
+ PQconninfoOption *sslmode_default = NULL,
+ *sslrootcert = NULL;
+ char *tmp;
+
+ /*
+ * If there's a service spec, use it to obtain any not-explicitly-given
+ * parameters. Ignore error if no error message buffer is passed because
+ * there is no way to pass back the failure message.
+ */
+ if (parseServiceInfo(options, errorMessage) != 0 && errorMessage)
+ return false;
+
+ /*
+ * Get the fallback resources for parameters not specified in the conninfo
+ * string nor the service.
+ */
+ for (option = options; option->keyword != NULL; option++)
+ {
+ if (strcmp(option->keyword, "sslrootcert") == 0)
+ sslrootcert = option; /* save for later */
+
+ if (option->val != NULL)
+ continue; /* Value was in conninfo or service */
+
+ /*
+ * Try to get the environment variable fallback
+ */
+ if (option->envvar != NULL)
+ {
+ if ((tmp = getenv(option->envvar)) != NULL)
+ {
+ option->val = strdup(tmp);
+ if (!option->val)
+ {
+ if (errorMessage)
+ libpq_append_error(errorMessage, "out of memory");
+ return false;
+ }
+ continue;
+ }
+ }
+
+ /*
+ * Interpret the deprecated PGREQUIRESSL environment variable. Per
+ * tradition, translate values starting with "1" to sslmode=require,
+ * and ignore other values. Given both PGREQUIRESSL=1 and PGSSLMODE,
+ * PGSSLMODE takes precedence; the opposite was true before v9.3.
+ */
+ if (strcmp(option->keyword, "sslmode") == 0)
+ {
+ const char *requiresslenv = getenv("PGREQUIRESSL");
+
+ if (requiresslenv != NULL && requiresslenv[0] == '1')
+ {
+ option->val = strdup("require");
+ if (!option->val)
+ {
+ if (errorMessage)
+ libpq_append_error(errorMessage, "out of memory");
+ return false;
+ }
+ continue;
+ }
+
+ /*
+ * sslmode is not specified. Let it be filled in with the compiled
+ * default for now, but if sslrootcert=system, we'll override the
+ * default later before returning.
+ */
+ sslmode_default = option;
+ }
+
+ /*
+ * No environment variable specified or the variable isn't set - try
+ * compiled-in default
+ */
+ if (option->compiled != NULL)
+ {
+ option->val = strdup(option->compiled);
+ if (!option->val)
+ {
+ if (errorMessage)
+ libpq_append_error(errorMessage, "out of memory");
+ return false;
+ }
+ continue;
+ }
+
+ /*
+ * Special handling for "user" option. Note that if pg_fe_getauthname
+ * fails, we just leave the value as NULL; there's no need for this to
+ * be an error condition if the caller provides a user name. The only
+ * reason we do this now at all is so that callers of PQconndefaults
+ * will see a correct default (barring error, of course).
+ */
+ if (strcmp(option->keyword, "user") == 0)
+ {
+ option->val = pg_fe_getauthname(NULL);
+ continue;
+ }
+ }
+
+ /*
+ * Special handling for sslrootcert=system with no sslmode explicitly
+ * defined. In this case we want to strengthen the default sslmode to
+ * verify-full.
+ */
+ if (sslmode_default && sslrootcert)
+ {
+ if (sslrootcert->val && strcmp(sslrootcert->val, "system") == 0)
+ {
+ free(sslmode_default->val);
+
+ sslmode_default->val = strdup("verify-full");
+ if (!sslmode_default->val)
+ {
+ if (errorMessage)
+ libpq_append_error(errorMessage, "out of memory");
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+/*
+ * Subroutine for parse_connection_string
+ *
+ * Deal with a URI connection string.
+ */
+static PQconninfoOption *
+conninfo_uri_parse(const char *uri, PQExpBuffer errorMessage,
+ bool use_defaults)
+{
+ PQconninfoOption *options;
+
+ /* Make a working copy of PQconninfoOptions */
+ options = conninfo_init(errorMessage);
+ if (options == NULL)
+ return NULL;
+
+ if (!conninfo_uri_parse_options(options, uri, errorMessage))
+ {
+ PQconninfoFree(options);
+ return NULL;
+ }
+
+ /*
+ * Add in defaults if the caller wants that.
+ */
+ if (use_defaults)
+ {
+ if (!conninfo_add_defaults(options, errorMessage))
+ {
+ PQconninfoFree(options);
+ return NULL;
+ }
+ }
+
+ return options;
+}
+
+/*
+ * conninfo_uri_parse_options
+ * Actual URI parser.
+ *
+ * If successful, returns true while the options array is filled with parsed
+ * options from the URI.
+ * If not successful, returns false and fills errorMessage accordingly.
+ *
+ * Parses the connection URI string in 'uri' according to the URI syntax (RFC
+ * 3986):
+ *
+ * postgresql://[user[:password]@][netloc][:port][/dbname][?param1=value1&...]
+ *
+ * where "netloc" is a hostname, an IPv4 address, or an IPv6 address surrounded
+ * by literal square brackets. As an extension, we also allow multiple
+ * netloc[:port] specifications, separated by commas:
+ *
+ * postgresql://[user[:password]@][netloc][:port][,...][/dbname][?param1=value1&...]
+ *
+ * Any of the URI parts might use percent-encoding (%xy).
+ */
+static bool
+conninfo_uri_parse_options(PQconninfoOption *options, const char *uri,
+ PQExpBuffer errorMessage)
+{
+ int prefix_len;
+ char *p;
+ char *buf = NULL;
+ char *start;
+ char prevchar = '\0';
+ char *user = NULL;
+ char *host = NULL;
+ bool retval = false;
+ PQExpBufferData hostbuf;
+ PQExpBufferData portbuf;
+
+ initPQExpBuffer(&hostbuf);
+ initPQExpBuffer(&portbuf);
+ if (PQExpBufferDataBroken(hostbuf) || PQExpBufferDataBroken(portbuf))
+ {
+ libpq_append_error(errorMessage, "out of memory");
+ goto cleanup;
+ }
+
+ /* need a modifiable copy of the input URI */
+ buf = strdup(uri);
+ if (buf == NULL)
+ {
+ libpq_append_error(errorMessage, "out of memory");
+ goto cleanup;
+ }
+ start = buf;
+
+ /* Skip the URI prefix */
+ prefix_len = uri_prefix_length(uri);
+ if (prefix_len == 0)
+ {
+ /* Should never happen */
+ libpq_append_error(errorMessage,
+ "invalid URI propagated to internal parser routine: \"%s\"",
+ uri);
+ goto cleanup;
+ }
+ start += prefix_len;
+ p = start;
+
+ /* Look ahead for possible user credentials designator */
+ while (*p && *p != '@' && *p != '/')
+ ++p;
+ if (*p == '@')
+ {
+ /*
+ * Found username/password designator, so URI should be of the form
+ * "scheme://user[:password]@[netloc]".
+ */
+ user = start;
+
+ p = user;
+ while (*p != ':' && *p != '@')
+ ++p;
+
+ /* Save last char and cut off at end of user name */
+ prevchar = *p;
+ *p = '\0';
+
+ if (*user &&
+ !conninfo_storeval(options, "user", user,
+ errorMessage, false, true))
+ goto cleanup;
+
+ if (prevchar == ':')
+ {
+ const char *password = p + 1;
+
+ while (*p != '@')
+ ++p;
+ *p = '\0';
+
+ if (*password &&
+ !conninfo_storeval(options, "password", password,
+ errorMessage, false, true))
+ goto cleanup;
+ }
+
+ /* Advance past end of parsed user name or password token */
+ ++p;
+ }
+ else
+ {
+ /*
+ * No username/password designator found. Reset to start of URI.
+ */
+ p = start;
+ }
+
+ /*
+ * There may be multiple netloc[:port] pairs, each separated from the next
+ * by a comma. When we initially enter this loop, "p" has been
+ * incremented past optional URI credential information at this point and
+ * now points at the "netloc" part of the URI. On subsequent loop
+ * iterations, "p" has been incremented past the comma separator and now
+ * points at the start of the next "netloc".
+ */
+ for (;;)
+ {
+ /*
+ * Look for IPv6 address.
+ */
+ if (*p == '[')
+ {
+ host = ++p;
+ while (*p && *p != ']')
+ ++p;
+ if (!*p)
+ {
+ libpq_append_error(errorMessage,
+ "end of string reached when looking for matching \"]\" in IPv6 host address in URI: \"%s\"",
+ uri);
+ goto cleanup;
+ }
+ if (p == host)
+ {
+ libpq_append_error(errorMessage,
+ "IPv6 host address may not be empty in URI: \"%s\"",
+ uri);
+ goto cleanup;
+ }
+
+ /* Cut off the bracket and advance */
+ *(p++) = '\0';
+
+ /*
+ * The address may be followed by a port specifier or a slash or a
+ * query or a separator comma.
+ */
+ if (*p && *p != ':' && *p != '/' && *p != '?' && *p != ',')
+ {
+ libpq_append_error(errorMessage,
+ "unexpected character \"%c\" at position %d in URI (expected \":\" or \"/\"): \"%s\"",
+ *p, (int) (p - buf + 1), uri);
+ goto cleanup;
+ }
+ }
+ else
+ {
+ /* not an IPv6 address: DNS-named or IPv4 netloc */
+ host = p;
+
+ /*
+ * Look for port specifier (colon) or end of host specifier
+ * (slash) or query (question mark) or host separator (comma).
+ */
+ while (*p && *p != ':' && *p != '/' && *p != '?' && *p != ',')
+ ++p;
+ }
+
+ /* Save the hostname terminator before we null it */
+ prevchar = *p;
+ *p = '\0';
+
+ appendPQExpBufferStr(&hostbuf, host);
+
+ if (prevchar == ':')
+ {
+ const char *port = ++p; /* advance past host terminator */
+
+ while (*p && *p != '/' && *p != '?' && *p != ',')
+ ++p;
+
+ prevchar = *p;
+ *p = '\0';
+
+ appendPQExpBufferStr(&portbuf, port);
+ }
+
+ if (prevchar != ',')
+ break;
+ ++p; /* advance past comma separator */
+ appendPQExpBufferChar(&hostbuf, ',');
+ appendPQExpBufferChar(&portbuf, ',');
+ }
+
+ /* Save final values for host and port. */
+ if (PQExpBufferDataBroken(hostbuf) || PQExpBufferDataBroken(portbuf))
+ goto cleanup;
+ if (hostbuf.data[0] &&
+ !conninfo_storeval(options, "host", hostbuf.data,
+ errorMessage, false, true))
+ goto cleanup;
+ if (portbuf.data[0] &&
+ !conninfo_storeval(options, "port", portbuf.data,
+ errorMessage, false, true))
+ goto cleanup;
+
+ if (prevchar && prevchar != '?')
+ {
+ const char *dbname = ++p; /* advance past host terminator */
+
+ /* Look for query parameters */
+ while (*p && *p != '?')
+ ++p;
+
+ prevchar = *p;
+ *p = '\0';
+
+ /*
+ * Avoid setting dbname to an empty string, as it forces the default
+ * value (username) and ignores $PGDATABASE, as opposed to not setting
+ * it at all.
+ */
+ if (*dbname &&
+ !conninfo_storeval(options, "dbname", dbname,
+ errorMessage, false, true))
+ goto cleanup;
+ }
+
+ if (prevchar)
+ {
+ ++p; /* advance past terminator */
+
+ if (!conninfo_uri_parse_params(p, options, errorMessage))
+ goto cleanup;
+ }
+
+ /* everything parsed okay */
+ retval = true;
+
+cleanup:
+ termPQExpBuffer(&hostbuf);
+ termPQExpBuffer(&portbuf);
+ free(buf);
+ return retval;
+}
+
+/*
+ * Connection URI parameters parser routine
+ *
+ * If successful, returns true while connOptions is filled with parsed
+ * parameters. Otherwise, returns false and fills errorMessage appropriately.
+ *
+ * Destructively modifies 'params' buffer.
+ */
+static bool
+conninfo_uri_parse_params(char *params,
+ PQconninfoOption *connOptions,
+ PQExpBuffer errorMessage)
+{
+ while (*params)
+ {
+ char *keyword = params;
+ char *value = NULL;
+ char *p = params;
+ bool malloced = false;
+ int oldmsglen;
+
+ /*
+ * Scan the params string for '=' and '&', marking the end of keyword
+ * and value respectively.
+ */
+ for (;;)
+ {
+ if (*p == '=')
+ {
+ /* Was there '=' already? */
+ if (value != NULL)
+ {
+ libpq_append_error(errorMessage,
+ "extra key/value separator \"=\" in URI query parameter: \"%s\"",
+ keyword);
+ return false;
+ }
+ /* Cut off keyword, advance to value */
+ *p++ = '\0';
+ value = p;
+ }
+ else if (*p == '&' || *p == '\0')
+ {
+ /*
+ * If not at the end, cut off value and advance; leave p
+ * pointing to start of the next parameter, if any.
+ */
+ if (*p != '\0')
+ *p++ = '\0';
+ /* Was there '=' at all? */
+ if (value == NULL)
+ {
+ libpq_append_error(errorMessage,
+ "missing key/value separator \"=\" in URI query parameter: \"%s\"",
+ keyword);
+ return false;
+ }
+ /* Got keyword and value, go process them. */
+ break;
+ }
+ else
+ ++p; /* Advance over all other bytes. */
+ }
+
+ keyword = conninfo_uri_decode(keyword, errorMessage);
+ if (keyword == NULL)
+ {
+ /* conninfo_uri_decode already set an error message */
+ return false;
+ }
+ value = conninfo_uri_decode(value, errorMessage);
+ if (value == NULL)
+ {
+ /* conninfo_uri_decode already set an error message */
+ free(keyword);
+ return false;
+ }
+ malloced = true;
+
+ /*
+ * Special keyword handling for improved JDBC compatibility.
+ */
+ if (strcmp(keyword, "ssl") == 0 &&
+ strcmp(value, "true") == 0)
+ {
+ free(keyword);
+ free(value);
+ malloced = false;
+
+ keyword = "sslmode";
+ value = "require";
+ }
+
+ /*
+ * Store the value if the corresponding option exists; ignore
+ * otherwise. At this point both keyword and value are not
+ * URI-encoded.
+ */
+ oldmsglen = errorMessage->len;
+ if (!conninfo_storeval(connOptions, keyword, value,
+ errorMessage, true, false))
+ {
+ /* Insert generic message if conninfo_storeval didn't give one. */
+ if (errorMessage->len == oldmsglen)
+ libpq_append_error(errorMessage,
+ "invalid URI query parameter: \"%s\"",
+ keyword);
+ /* And fail. */
+ if (malloced)
+ {
+ free(keyword);
+ free(value);
+ }
+ return false;
+ }
+
+ if (malloced)
+ {
+ free(keyword);
+ free(value);
+ }
+
+ /* Proceed to next key=value pair, if any */
+ params = p;
+ }
+
+ return true;
+}
+
+/*
+ * Connection URI decoder routine
+ *
+ * If successful, returns the malloc'd decoded string.
+ * If not successful, returns NULL and fills errorMessage accordingly.
+ *
+ * The string is decoded by replacing any percent-encoded tokens with
+ * corresponding characters, while preserving any non-encoded characters. A
+ * percent-encoded token is a character triplet: a percent sign, followed by a
+ * pair of hexadecimal digits (0-9A-F), where lower- and upper-case letters are
+ * treated identically.
+ */
+static char *
+conninfo_uri_decode(const char *str, PQExpBuffer errorMessage)
+{
+ char *buf;
+ char *p;
+ const char *q = str;
+
+ buf = malloc(strlen(str) + 1);
+ if (buf == NULL)
+ {
+ libpq_append_error(errorMessage, "out of memory");
+ return NULL;
+ }
+ p = buf;
+
+ for (;;)
+ {
+ if (*q != '%')
+ {
+ /* copy and check for NUL terminator */
+ if (!(*(p++) = *(q++)))
+ break;
+ }
+ else
+ {
+ int hi;
+ int lo;
+ int c;
+
+ ++q; /* skip the percent sign itself */
+
+ /*
+ * Possible EOL will be caught by the first call to
+ * get_hexdigit(), so we never dereference an invalid q pointer.
+ */
+ if (!(get_hexdigit(*q++, &hi) && get_hexdigit(*q++, &lo)))
+ {
+ libpq_append_error(errorMessage,
+ "invalid percent-encoded token: \"%s\"",
+ str);
+ free(buf);
+ return NULL;
+ }
+
+ c = (hi << 4) | lo;
+ if (c == 0)
+ {
+ libpq_append_error(errorMessage,
+ "forbidden value %%00 in percent-encoded value: \"%s\"",
+ str);
+ free(buf);
+ return NULL;
+ }
+ *(p++) = c;
+ }
+ }
+
+ return buf;
+}
+
+/*
+ * Convert hexadecimal digit character to its integer value.
+ *
+ * If successful, returns true and value is filled with digit's base 16 value.
+ * If not successful, returns false.
+ *
+ * Lower- and upper-case letters in the range A-F are treated identically.
+ */
+static bool
+get_hexdigit(char digit, int *value)
+{
+ if ('0' <= digit && digit <= '9')
+ *value = digit - '0';
+ else if ('A' <= digit && digit <= 'F')
+ *value = digit - 'A' + 10;
+ else if ('a' <= digit && digit <= 'f')
+ *value = digit - 'a' + 10;
+ else
+ return false;
+
+ return true;
+}
+
+/*
+ * Find an option value corresponding to the keyword in the connOptions array.
+ *
+ * If successful, returns a pointer to the corresponding option's value.
+ * If not successful, returns NULL.
+ */
+static const char *
+conninfo_getval(PQconninfoOption *connOptions,
+ const char *keyword)
+{
+ PQconninfoOption *option;
+
+ option = conninfo_find(connOptions, keyword);
+
+ return option ? option->val : NULL;
+}
+
+/*
+ * Store a (new) value for an option corresponding to the keyword in
+ * connOptions array.
+ *
+ * If uri_decode is true, the value is URI-decoded. The keyword is always
+ * assumed to be non URI-encoded.
+ *
+ * If successful, returns a pointer to the corresponding PQconninfoOption,
+ * which value is replaced with a strdup'd copy of the passed value string.
+ * The existing value for the option is free'd before replacing, if any.
+ *
+ * If not successful, returns NULL and fills errorMessage accordingly.
+ * However, if the reason of failure is an invalid keyword being passed and
+ * ignoreMissing is true, errorMessage will be left untouched.
+ */
+static PQconninfoOption *
+conninfo_storeval(PQconninfoOption *connOptions,
+ const char *keyword, const char *value,
+ PQExpBuffer errorMessage, bool ignoreMissing,
+ bool uri_decode)
+{
+ PQconninfoOption *option;
+ char *value_copy;
+
+ /*
+ * For backwards compatibility, requiressl=1 gets translated to
+ * sslmode=require, and requiressl=0 gets translated to sslmode=prefer
+ * (which is the default for sslmode).
+ */
+ if (strcmp(keyword, "requiressl") == 0)
+ {
+ keyword = "sslmode";
+ if (value[0] == '1')
+ value = "require";
+ else
+ value = "prefer";
+ }
+
+ option = conninfo_find(connOptions, keyword);
+ if (option == NULL)
+ {
+ if (!ignoreMissing)
+ libpq_append_error(errorMessage,
+ "invalid connection option \"%s\"",
+ keyword);
+ return NULL;
+ }
+
+ if (uri_decode)
+ {
+ value_copy = conninfo_uri_decode(value, errorMessage);
+ if (value_copy == NULL)
+ /* conninfo_uri_decode already set an error message */
+ return NULL;
+ }
+ else
+ {
+ value_copy = strdup(value);
+ if (value_copy == NULL)
+ {
+ libpq_append_error(errorMessage, "out of memory");
+ return NULL;
+ }
+ }
+
+ free(option->val);
+ option->val = value_copy;
+
+ return option;
+}
+
+/*
+ * Find a PQconninfoOption option corresponding to the keyword in the
+ * connOptions array.
+ *
+ * If successful, returns a pointer to the corresponding PQconninfoOption
+ * structure.
+ * If not successful, returns NULL.
+ */
+static PQconninfoOption *
+conninfo_find(PQconninfoOption *connOptions, const char *keyword)
+{
+ PQconninfoOption *option;
+
+ for (option = connOptions; option->keyword != NULL; option++)
+ {
+ if (strcmp(option->keyword, keyword) == 0)
+ return option;
+ }
+
+ return NULL;
+}
+
+
+/*
+ * Return the connection options used for the connection
+ */
+PQconninfoOption *
+PQconninfo(PGconn *conn)
+{
+ PQExpBufferData errorBuf;
+ PQconninfoOption *connOptions;
+
+ if (conn == NULL)
+ return NULL;
+
+ /*
+ * We don't actually report any errors here, but callees want a buffer,
+ * and we prefer not to trash the conn's errorMessage.
+ */
+ initPQExpBuffer(&errorBuf);
+ if (PQExpBufferDataBroken(errorBuf))
+ return NULL; /* out of memory already :-( */
+
+ connOptions = conninfo_init(&errorBuf);
+
+ if (connOptions != NULL)
+ {
+ const internalPQconninfoOption *option;
+
+ for (option = PQconninfoOptions; option->keyword; option++)
+ {
+ char **connmember;
+
+ if (option->connofs < 0)
+ continue;
+
+ connmember = (char **) ((char *) conn + option->connofs);
+
+ if (*connmember)
+ conninfo_storeval(connOptions, option->keyword, *connmember,
+ &errorBuf, true, false);
+ }
+ }
+
+ termPQExpBuffer(&errorBuf);
+
+ return connOptions;
+}
+
+
+void
+PQconninfoFree(PQconninfoOption *connOptions)
+{
+ if (connOptions == NULL)
+ return;
+
+ for (PQconninfoOption *option = connOptions; option->keyword != NULL; option++)
+ free(option->val);
+ free(connOptions);
+}
+
+
+/* =========== accessor functions for PGconn ========= */
+char *
+PQdb(const PGconn *conn)
+{
+ if (!conn)
+ return NULL;
+ return conn->dbName;
+}
+
+char *
+PQuser(const PGconn *conn)
+{
+ if (!conn)
+ return NULL;
+ return conn->pguser;
+}
+
+char *
+PQpass(const PGconn *conn)
+{
+ char *password = NULL;
+
+ if (!conn)
+ return NULL;
+ if (conn->connhost != NULL)
+ password = conn->connhost[conn->whichhost].password;
+ if (password == NULL)
+ password = conn->pgpass;
+ /* Historically we've returned "" not NULL for no password specified */
+ if (password == NULL)
+ password = "";
+ return password;
+}
+
+char *
+PQhost(const PGconn *conn)
+{
+ if (!conn)
+ return NULL;
+
+ if (conn->connhost != NULL)
+ {
+ /*
+ * Return the verbatim host value provided by user, or hostaddr in its
+ * lack.
+ */
+ if (conn->connhost[conn->whichhost].host != NULL &&
+ conn->connhost[conn->whichhost].host[0] != '\0')
+ return conn->connhost[conn->whichhost].host;
+ else if (conn->connhost[conn->whichhost].hostaddr != NULL &&
+ conn->connhost[conn->whichhost].hostaddr[0] != '\0')
+ return conn->connhost[conn->whichhost].hostaddr;
+ }
+
+ return "";
+}
+
+char *
+PQhostaddr(const PGconn *conn)
+{
+ if (!conn)
+ return NULL;
+
+ /* Return the parsed IP address */
+ if (conn->connhost != NULL && conn->connip != NULL)
+ return conn->connip;
+
+ return "";
+}
+
+char *
+PQport(const PGconn *conn)
+{
+ if (!conn)
+ return NULL;
+
+ if (conn->connhost != NULL)
+ return conn->connhost[conn->whichhost].port;
+
+ return "";
+}
+
+/*
+ * No longer does anything, but the function remains for API backwards
+ * compatibility.
+ */
+char *
+PQtty(const PGconn *conn)
+{
+ if (!conn)
+ return NULL;
+ return "";
+}
+
+char *
+PQoptions(const PGconn *conn)
+{
+ if (!conn)
+ return NULL;
+ return conn->pgoptions;
+}
+
+ConnStatusType
+PQstatus(const PGconn *conn)
+{
+ if (!conn)
+ return CONNECTION_BAD;
+ return conn->status;
+}
+
+PGTransactionStatusType
+PQtransactionStatus(const PGconn *conn)
+{
+ if (!conn || conn->status != CONNECTION_OK)
+ return PQTRANS_UNKNOWN;
+ if (conn->asyncStatus != PGASYNC_IDLE)
+ return PQTRANS_ACTIVE;
+ return conn->xactStatus;
+}
+
+const char *
+PQparameterStatus(const PGconn *conn, const char *paramName)
+{
+ const pgParameterStatus *pstatus;
+
+ if (!conn || !paramName)
+ return NULL;
+ for (pstatus = conn->pstatus; pstatus != NULL; pstatus = pstatus->next)
+ {
+ if (strcmp(pstatus->name, paramName) == 0)
+ return pstatus->value;
+ }
+ return NULL;
+}
+
+int
+PQprotocolVersion(const PGconn *conn)
+{
+ if (!conn)
+ return 0;
+ if (conn->status == CONNECTION_BAD)
+ return 0;
+ return PG_PROTOCOL_MAJOR(conn->pversion);
+}
+
+int
+PQserverVersion(const PGconn *conn)
+{
+ if (!conn)
+ return 0;
+ if (conn->status == CONNECTION_BAD)
+ return 0;
+ return conn->sversion;
+}
+
+char *
+PQerrorMessage(const PGconn *conn)
+{
+ if (!conn)
+ return libpq_gettext("connection pointer is NULL\n");
+
+ /*
+ * The errorMessage buffer might be marked "broken" due to having
+ * previously failed to allocate enough memory for the message. In that
+ * case, tell the application we ran out of memory.
+ */
+ if (PQExpBufferBroken(&conn->errorMessage))
+ return libpq_gettext("out of memory\n");
+
+ return conn->errorMessage.data;
+}
+
+/*
+ * In Windows, socket values are unsigned, and an invalid socket value
+ * (INVALID_SOCKET) is ~0, which equals -1 in comparisons (with no compiler
+ * warning). Ideally we would return an unsigned value for PQsocket() on
+ * Windows, but that would cause the function's return value to differ from
+ * Unix, so we just return -1 for invalid sockets.
+ * http://msdn.microsoft.com/en-us/library/windows/desktop/cc507522%28v=vs.85%29.aspx
+ * http://stackoverflow.com/questions/10817252/why-is-invalid-socket-defined-as-0-in-winsock2-h-c
+ */
+int
+PQsocket(const PGconn *conn)
+{
+ if (!conn)
+ return -1;
+ return (conn->sock != PGINVALID_SOCKET) ? conn->sock : -1;
+}
+
+int
+PQbackendPID(const PGconn *conn)
+{
+ if (!conn || conn->status != CONNECTION_OK)
+ return 0;
+ return conn->be_pid;
+}
+
+PGpipelineStatus
+PQpipelineStatus(const PGconn *conn)
+{
+ if (!conn)
+ return PQ_PIPELINE_OFF;
+
+ return conn->pipelineStatus;
+}
+
+int
+PQconnectionNeedsPassword(const PGconn *conn)
+{
+ char *password;
+
+ if (!conn)
+ return false;
+ password = PQpass(conn);
+ if (conn->password_needed &&
+ (password == NULL || password[0] == '\0'))
+ return true;
+ else
+ return false;
+}
+
+int
+PQconnectionUsedPassword(const PGconn *conn)
+{
+ if (!conn)
+ return false;
+ if (conn->password_needed)
+ return true;
+ else
+ return false;
+}
+
+int
+PQconnectionUsedGSSAPI(const PGconn *conn)
+{
+ if (!conn)
+ return false;
+ if (conn->gssapi_used)
+ return true;
+ else
+ return false;
+}
+
+int
+PQclientEncoding(const PGconn *conn)
+{
+ if (!conn || conn->status != CONNECTION_OK)
+ return -1;
+ return conn->client_encoding;
+}
+
+int
+PQsetClientEncoding(PGconn *conn, const char *encoding)
+{
+ char qbuf[128];
+ static const char query[] = "set client_encoding to '%s'";
+ PGresult *res;
+ int status;
+
+ if (!conn || conn->status != CONNECTION_OK)
+ return -1;
+
+ if (!encoding)
+ return -1;
+
+ /* Resolve special "auto" value from the locale */
+ if (strcmp(encoding, "auto") == 0)
+ encoding = pg_encoding_to_char(pg_get_encoding_from_locale(NULL, true));
+
+ /* check query buffer overflow */
+ if (sizeof(qbuf) < (sizeof(query) + strlen(encoding)))
+ return -1;
+
+ /* ok, now send a query */
+ sprintf(qbuf, query, encoding);
+ res = PQexec(conn, qbuf);
+
+ if (res == NULL)
+ return -1;
+ if (res->resultStatus != PGRES_COMMAND_OK)
+ status = -1;
+ else
+ {
+ /*
+ * We rely on the backend to report the parameter value, and we'll
+ * change state at that time.
+ */
+ status = 0; /* everything is ok */
+ }
+ PQclear(res);
+ return status;
+}
+
+PGVerbosity
+PQsetErrorVerbosity(PGconn *conn, PGVerbosity verbosity)
+{
+ PGVerbosity old;
+
+ if (!conn)
+ return PQERRORS_DEFAULT;
+ old = conn->verbosity;
+ conn->verbosity = verbosity;
+ return old;
+}
+
+PGContextVisibility
+PQsetErrorContextVisibility(PGconn *conn, PGContextVisibility show_context)
+{
+ PGContextVisibility old;
+
+ if (!conn)
+ return PQSHOW_CONTEXT_ERRORS;
+ old = conn->show_context;
+ conn->show_context = show_context;
+ return old;
+}
+
+PQnoticeReceiver
+PQsetNoticeReceiver(PGconn *conn, PQnoticeReceiver proc, void *arg)
+{
+ PQnoticeReceiver old;
+
+ if (conn == NULL)
+ return NULL;
+
+ old = conn->noticeHooks.noticeRec;
+ if (proc)
+ {
+ conn->noticeHooks.noticeRec = proc;
+ conn->noticeHooks.noticeRecArg = arg;
+ }
+ return old;
+}
+
+PQnoticeProcessor
+PQsetNoticeProcessor(PGconn *conn, PQnoticeProcessor proc, void *arg)
+{
+ PQnoticeProcessor old;
+
+ if (conn == NULL)
+ return NULL;
+
+ old = conn->noticeHooks.noticeProc;
+ if (proc)
+ {
+ conn->noticeHooks.noticeProc = proc;
+ conn->noticeHooks.noticeProcArg = arg;
+ }
+ return old;
+}
+
+/*
+ * The default notice message receiver just gets the standard notice text
+ * and sends it to the notice processor. This two-level setup exists
+ * mostly for backwards compatibility; perhaps we should deprecate use of
+ * PQsetNoticeProcessor?
+ */
+static void
+defaultNoticeReceiver(void *arg, const PGresult *res)
+{
+ (void) arg; /* not used */
+ if (res->noticeHooks.noticeProc != NULL)
+ res->noticeHooks.noticeProc(res->noticeHooks.noticeProcArg,
+ PQresultErrorMessage(res));
+}
+
+/*
+ * The default notice message processor just prints the
+ * message on stderr. Applications can override this if they
+ * want the messages to go elsewhere (a window, for example).
+ * Note that simply discarding notices is probably a bad idea.
+ */
+static void
+defaultNoticeProcessor(void *arg, const char *message)
+{
+ (void) arg; /* not used */
+ /* Note: we expect the supplied string to end with a newline already. */
+ fprintf(stderr, "%s", message);
+}
+
+/*
+ * returns a pointer to the next token or NULL if the current
+ * token doesn't match
+ */
+static char *
+pwdfMatchesString(char *buf, const char *token)
+{
+ char *tbuf;
+ const char *ttok;
+ bool bslash = false;
+
+ if (buf == NULL || token == NULL)
+ return NULL;
+ tbuf = buf;
+ ttok = token;
+ if (tbuf[0] == '*' && tbuf[1] == ':')
+ return tbuf + 2;
+ while (*tbuf != 0)
+ {
+ if (*tbuf == '\\' && !bslash)
+ {
+ tbuf++;
+ bslash = true;
+ }
+ if (*tbuf == ':' && *ttok == 0 && !bslash)
+ return tbuf + 1;
+ bslash = false;
+ if (*ttok == 0)
+ return NULL;
+ if (*tbuf == *ttok)
+ {
+ tbuf++;
+ ttok++;
+ }
+ else
+ return NULL;
+ }
+ return NULL;
+}
+
+/* Get a password from the password file. Return value is malloc'd. */
+static char *
+passwordFromFile(const char *hostname, const char *port, const char *dbname,
+ const char *username, const char *pgpassfile)
+{
+ FILE *fp;
+ struct stat stat_buf;
+ PQExpBufferData buf;
+
+ if (dbname == NULL || dbname[0] == '\0')
+ return NULL;
+
+ if (username == NULL || username[0] == '\0')
+ return NULL;
+
+ /* 'localhost' matches pghost of '' or the default socket directory */
+ if (hostname == NULL || hostname[0] == '\0')
+ hostname = DefaultHost;
+ else if (is_unixsock_path(hostname))
+
+ /*
+ * We should probably use canonicalize_path(), but then we have to
+ * bring path.c into libpq, and it doesn't seem worth it.
+ */
+ if (strcmp(hostname, DEFAULT_PGSOCKET_DIR) == 0)
+ hostname = DefaultHost;
+
+ if (port == NULL || port[0] == '\0')
+ port = DEF_PGPORT_STR;
+
+ /* If password file cannot be opened, ignore it. */
+ if (stat(pgpassfile, &stat_buf) != 0)
+ return NULL;
+
+#ifndef WIN32
+ if (!S_ISREG(stat_buf.st_mode))
+ {
+ fprintf(stderr,
+ libpq_gettext("WARNING: password file \"%s\" is not a plain file\n"),
+ pgpassfile);
+ return NULL;
+ }
+
+ /* If password file is insecure, alert the user and ignore it. */
+ if (stat_buf.st_mode & (S_IRWXG | S_IRWXO))
+ {
+ fprintf(stderr,
+ libpq_gettext("WARNING: password file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n"),
+ pgpassfile);
+ return NULL;
+ }
+#else
+
+ /*
+ * On Win32, the directory is protected, so we don't have to check the
+ * file.
+ */
+#endif
+
+ fp = fopen(pgpassfile, "r");
+ if (fp == NULL)
+ return NULL;
+
+ /* Use an expansible buffer to accommodate any reasonable line length */
+ initPQExpBuffer(&buf);
+
+ while (!feof(fp) && !ferror(fp))
+ {
+ /* Make sure there's a reasonable amount of room in the buffer */
+ if (!enlargePQExpBuffer(&buf, 128))
+ break;
+
+ /* Read some data, appending it to what we already have */
+ if (fgets(buf.data + buf.len, buf.maxlen - buf.len, fp) == NULL)
+ break;
+ buf.len += strlen(buf.data + buf.len);
+
+ /* If we don't yet have a whole line, loop around to read more */
+ if (!(buf.len > 0 && buf.data[buf.len - 1] == '\n') && !feof(fp))
+ continue;
+
+ /* ignore comments */
+ if (buf.data[0] != '#')
+ {
+ char *t = buf.data;
+ int len;
+
+ /* strip trailing newline and carriage return */
+ len = pg_strip_crlf(t);
+
+ if (len > 0 &&
+ (t = pwdfMatchesString(t, hostname)) != NULL &&
+ (t = pwdfMatchesString(t, port)) != NULL &&
+ (t = pwdfMatchesString(t, dbname)) != NULL &&
+ (t = pwdfMatchesString(t, username)) != NULL)
+ {
+ /* Found a match. */
+ char *ret,
+ *p1,
+ *p2;
+
+ ret = strdup(t);
+
+ fclose(fp);
+ explicit_bzero(buf.data, buf.maxlen);
+ termPQExpBuffer(&buf);
+
+ if (!ret)
+ {
+ /* Out of memory. XXX: an error message would be nice. */
+ return NULL;
+ }
+
+ /* De-escape password. */
+ for (p1 = p2 = ret; *p1 != ':' && *p1 != '\0'; ++p1, ++p2)
+ {
+ if (*p1 == '\\' && p1[1] != '\0')
+ ++p1;
+ *p2 = *p1;
+ }
+ *p2 = '\0';
+
+ return ret;
+ }
+ }
+
+ /* No match, reset buffer to prepare for next line. */
+ buf.len = 0;
+ }
+
+ fclose(fp);
+ explicit_bzero(buf.data, buf.maxlen);
+ termPQExpBuffer(&buf);
+ return NULL;
+}
+
+
+/*
+ * If the connection failed due to bad password, we should mention
+ * if we got the password from the pgpassfile.
+ */
+static void
+pgpassfileWarning(PGconn *conn)
+{
+ /* If it was 'invalid authorization', add pgpassfile mention */
+ /* only works with >= 9.0 servers */
+ if (conn->password_needed &&
+ conn->connhost[conn->whichhost].password != NULL &&
+ conn->result)
+ {
+ const char *sqlstate = PQresultErrorField(conn->result,
+ PG_DIAG_SQLSTATE);
+
+ if (sqlstate && strcmp(sqlstate, ERRCODE_INVALID_PASSWORD) == 0)
+ libpq_append_conn_error(conn, "password retrieved from file \"%s\"",
+ conn->pgpassfile);
+ }
+}
+
+/*
+ * Check if the SSL protocol value given in input is valid or not.
+ * This is used as a sanity check routine for the connection parameters
+ * ssl_min_protocol_version and ssl_max_protocol_version.
+ */
+static bool
+sslVerifyProtocolVersion(const char *version)
+{
+ /*
+ * An empty string and a NULL value are considered valid as it is
+ * equivalent to ignoring the parameter.
+ */
+ if (!version || strlen(version) == 0)
+ return true;
+
+ if (pg_strcasecmp(version, "TLSv1") == 0 ||
+ pg_strcasecmp(version, "TLSv1.1") == 0 ||
+ pg_strcasecmp(version, "TLSv1.2") == 0 ||
+ pg_strcasecmp(version, "TLSv1.3") == 0)
+ return true;
+
+ /* anything else is wrong */
+ return false;
+}
+
+
+/*
+ * Ensure that the SSL protocol range given in input is correct. The check
+ * is performed on the input string to keep it TLS backend agnostic. Input
+ * to this function is expected verified with sslVerifyProtocolVersion().
+ */
+static bool
+sslVerifyProtocolRange(const char *min, const char *max)
+{
+ Assert(sslVerifyProtocolVersion(min) &&
+ sslVerifyProtocolVersion(max));
+
+ /* If at least one of the bounds is not set, the range is valid */
+ if (min == NULL || max == NULL || strlen(min) == 0 || strlen(max) == 0)
+ return true;
+
+ /*
+ * If the minimum version is the lowest one we accept, then all options
+ * for the maximum are valid.
+ */
+ if (pg_strcasecmp(min, "TLSv1") == 0)
+ return true;
+
+ /*
+ * The minimum bound is valid, and cannot be TLSv1, so using TLSv1 for the
+ * maximum is incorrect.
+ */
+ if (pg_strcasecmp(max, "TLSv1") == 0)
+ return false;
+
+ /*
+ * At this point we know that we have a mix of TLSv1.1 through 1.3
+ * versions.
+ */
+ if (pg_strcasecmp(min, max) > 0)
+ return false;
+
+ return true;
+}
+
+
+/*
+ * Obtain user's home directory, return in given buffer
+ *
+ * On Unix, this actually returns the user's home directory. On Windows
+ * it returns the PostgreSQL-specific application data folder.
+ *
+ * This is essentially the same as get_home_path(), but we don't use that
+ * because we don't want to pull path.c into libpq (it pollutes application
+ * namespace).
+ *
+ * Returns true on success, false on failure to obtain the directory name.
+ *
+ * CAUTION: although in most situations failure is unexpected, there are users
+ * who like to run applications in a home-directory-less environment. On
+ * failure, you almost certainly DO NOT want to report an error. Just act as
+ * though whatever file you were hoping to find in the home directory isn't
+ * there (which it isn't).
+ */
+bool
+pqGetHomeDirectory(char *buf, int bufsize)
+{
+#ifndef WIN32
+ const char *home;
+
+ home = getenv("HOME");
+ if (home == NULL || home[0] == '\0')
+ return pg_get_user_home_dir(geteuid(), buf, bufsize);
+ strlcpy(buf, home, bufsize);
+ return true;
+#else
+ char tmppath[MAX_PATH];
+
+ ZeroMemory(tmppath, sizeof(tmppath));
+ if (SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, tmppath) != S_OK)
+ return false;
+ snprintf(buf, bufsize, "%s/postgresql", tmppath);
+ return true;
+#endif
+}
+
+/*
+ * To keep the API consistent, the locking stubs are always provided, even
+ * if they are not required.
+ *
+ * Since we neglected to provide any error-return convention in the
+ * pgthreadlock_t API, we can't do much except Assert upon failure of any
+ * mutex primitive. Fortunately, such failures appear to be nonexistent in
+ * the field.
+ */
+
+static void
+default_threadlock(int acquire)
+{
+#ifdef ENABLE_THREAD_SAFETY
+#ifndef WIN32
+ static pthread_mutex_t singlethread_lock = PTHREAD_MUTEX_INITIALIZER;
+#else
+ static pthread_mutex_t singlethread_lock = NULL;
+ static long mutex_initlock = 0;
+
+ if (singlethread_lock == NULL)
+ {
+ while (InterlockedExchange(&mutex_initlock, 1) == 1)
+ /* loop, another thread own the lock */ ;
+ if (singlethread_lock == NULL)
+ {
+ if (pthread_mutex_init(&singlethread_lock, NULL))
+ Assert(false);
+ }
+ InterlockedExchange(&mutex_initlock, 0);
+ }
+#endif
+ if (acquire)
+ {
+ if (pthread_mutex_lock(&singlethread_lock))
+ Assert(false);
+ }
+ else
+ {
+ if (pthread_mutex_unlock(&singlethread_lock))
+ Assert(false);
+ }
+#endif
+}
+
+pgthreadlock_t
+PQregisterThreadLock(pgthreadlock_t newhandler)
+{
+ pgthreadlock_t prev = pg_g_threadlock;
+
+ if (newhandler)
+ pg_g_threadlock = newhandler;
+ else
+ pg_g_threadlock = default_threadlock;
+
+ return prev;
+}
diff --git a/contrib/libs/libpq/src/interfaces/libpq/fe-exec.c b/contrib/libs/libpq/src/interfaces/libpq/fe-exec.c
new file mode 100644
index 0000000000..26564955d0
--- /dev/null
+++ b/contrib/libs/libpq/src/interfaces/libpq/fe-exec.c
@@ -0,0 +1,4445 @@
+/*-------------------------------------------------------------------------
+ *
+ * fe-exec.c
+ * functions related to sending a query down to the backend
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/interfaces/libpq/fe-exec.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres_fe.h"
+
+#include <ctype.h>
+#include <fcntl.h>
+#include <limits.h>
+
+#ifdef WIN32
+#include "win32.h"
+#else
+#include <unistd.h>
+#endif
+
+#include "libpq-fe.h"
+#include "libpq-int.h"
+#include "mb/pg_wchar.h"
+
+/* keep this in same order as ExecStatusType in libpq-fe.h */
+char *const pgresStatus[] = {
+ "PGRES_EMPTY_QUERY",
+ "PGRES_COMMAND_OK",
+ "PGRES_TUPLES_OK",
+ "PGRES_COPY_OUT",
+ "PGRES_COPY_IN",
+ "PGRES_BAD_RESPONSE",
+ "PGRES_NONFATAL_ERROR",
+ "PGRES_FATAL_ERROR",
+ "PGRES_COPY_BOTH",
+ "PGRES_SINGLE_TUPLE",
+ "PGRES_PIPELINE_SYNC",
+ "PGRES_PIPELINE_ABORTED"
+};
+
+/* We return this if we're unable to make a PGresult at all */
+static const PGresult OOM_result = {
+ .resultStatus = PGRES_FATAL_ERROR,
+ .client_encoding = PG_SQL_ASCII,
+ .errMsg = "out of memory\n",
+};
+
+/*
+ * static state needed by PQescapeString and PQescapeBytea; initialize to
+ * values that result in backward-compatible behavior
+ */
+static int static_client_encoding = PG_SQL_ASCII;
+static bool static_std_strings = false;
+
+
+static PGEvent *dupEvents(PGEvent *events, int count, size_t *memSize);
+static bool pqAddTuple(PGresult *res, PGresAttValue *tup,
+ const char **errmsgp);
+static int PQsendQueryInternal(PGconn *conn, const char *query, bool newQuery);
+static bool PQsendQueryStart(PGconn *conn, bool newQuery);
+static int PQsendQueryGuts(PGconn *conn,
+ const char *command,
+ const char *stmtName,
+ int nParams,
+ const Oid *paramTypes,
+ const char *const *paramValues,
+ const int *paramLengths,
+ const int *paramFormats,
+ int resultFormat);
+static void parseInput(PGconn *conn);
+static PGresult *getCopyResult(PGconn *conn, ExecStatusType copytype);
+static bool PQexecStart(PGconn *conn);
+static PGresult *PQexecFinish(PGconn *conn);
+static int PQsendDescribe(PGconn *conn, char desc_type,
+ const char *desc_target);
+static int check_field_number(const PGresult *res, int field_num);
+static void pqPipelineProcessQueue(PGconn *conn);
+static int pqPipelineFlush(PGconn *conn);
+
+
+/* ----------------
+ * Space management for PGresult.
+ *
+ * Formerly, libpq did a separate malloc() for each field of each tuple
+ * returned by a query. This was remarkably expensive --- malloc/free
+ * consumed a sizable part of the application's runtime. And there is
+ * no real need to keep track of the fields separately, since they will
+ * all be freed together when the PGresult is released. So now, we grab
+ * large blocks of storage from malloc and allocate space for query data
+ * within these blocks, using a trivially simple allocator. This reduces
+ * the number of malloc/free calls dramatically, and it also avoids
+ * fragmentation of the malloc storage arena.
+ * The PGresult structure itself is still malloc'd separately. We could
+ * combine it with the first allocation block, but that would waste space
+ * for the common case that no extra storage is actually needed (that is,
+ * the SQL command did not return tuples).
+ *
+ * We also malloc the top-level array of tuple pointers separately, because
+ * we need to be able to enlarge it via realloc, and our trivial space
+ * allocator doesn't handle that effectively. (Too bad the FE/BE protocol
+ * doesn't tell us up front how many tuples will be returned.)
+ * All other subsidiary storage for a PGresult is kept in PGresult_data blocks
+ * of size PGRESULT_DATA_BLOCKSIZE. The overhead at the start of each block
+ * is just a link to the next one, if any. Free-space management info is
+ * kept in the owning PGresult.
+ * A query returning a small amount of data will thus require three malloc
+ * calls: one for the PGresult, one for the tuples pointer array, and one
+ * PGresult_data block.
+ *
+ * Only the most recently allocated PGresult_data block is a candidate to
+ * have more stuff added to it --- any extra space left over in older blocks
+ * is wasted. We could be smarter and search the whole chain, but the point
+ * here is to be simple and fast. Typical applications do not keep a PGresult
+ * around very long anyway, so some wasted space within one is not a problem.
+ *
+ * Tuning constants for the space allocator are:
+ * PGRESULT_DATA_BLOCKSIZE: size of a standard allocation block, in bytes
+ * PGRESULT_ALIGN_BOUNDARY: assumed alignment requirement for binary data
+ * PGRESULT_SEP_ALLOC_THRESHOLD: objects bigger than this are given separate
+ * blocks, instead of being crammed into a regular allocation block.
+ * Requirements for correct function are:
+ * PGRESULT_ALIGN_BOUNDARY must be a multiple of the alignment requirements
+ * of all machine data types. (Currently this is set from configure
+ * tests, so it should be OK automatically.)
+ * PGRESULT_SEP_ALLOC_THRESHOLD + PGRESULT_BLOCK_OVERHEAD <=
+ * PGRESULT_DATA_BLOCKSIZE
+ * pqResultAlloc assumes an object smaller than the threshold will fit
+ * in a new block.
+ * The amount of space wasted at the end of a block could be as much as
+ * PGRESULT_SEP_ALLOC_THRESHOLD, so it doesn't pay to make that too large.
+ * ----------------
+ */
+
+#define PGRESULT_DATA_BLOCKSIZE 2048
+#define PGRESULT_ALIGN_BOUNDARY MAXIMUM_ALIGNOF /* from configure */
+#define PGRESULT_BLOCK_OVERHEAD Max(sizeof(PGresult_data), PGRESULT_ALIGN_BOUNDARY)
+#define PGRESULT_SEP_ALLOC_THRESHOLD (PGRESULT_DATA_BLOCKSIZE / 2)
+
+
+/*
+ * PQmakeEmptyPGresult
+ * returns a newly allocated, initialized PGresult with given status.
+ * If conn is not NULL and status indicates an error, the conn's
+ * errorMessage is copied. Also, any PGEvents are copied from the conn.
+ *
+ * Note: the logic to copy the conn's errorMessage is now vestigial;
+ * no internal caller uses it. However, that behavior is documented for
+ * outside callers, so we'd better keep it.
+ */
+PGresult *
+PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
+{
+ PGresult *result;
+
+ result = (PGresult *) malloc(sizeof(PGresult));
+ if (!result)
+ return NULL;
+
+ result->ntups = 0;
+ result->numAttributes = 0;
+ result->attDescs = NULL;
+ result->tuples = NULL;
+ result->tupArrSize = 0;
+ result->numParameters = 0;
+ result->paramDescs = NULL;
+ result->resultStatus = status;
+ result->cmdStatus[0] = '\0';
+ result->binary = 0;
+ result->events = NULL;
+ result->nEvents = 0;
+ result->errMsg = NULL;
+ result->errFields = NULL;
+ result->errQuery = NULL;
+ result->null_field[0] = '\0';
+ result->curBlock = NULL;
+ result->curOffset = 0;
+ result->spaceLeft = 0;
+ result->memorySize = sizeof(PGresult);
+
+ if (conn)
+ {
+ /* copy connection data we might need for operations on PGresult */
+ result->noticeHooks = conn->noticeHooks;
+ result->client_encoding = conn->client_encoding;
+
+ /* consider copying conn's errorMessage */
+ switch (status)
+ {
+ case PGRES_EMPTY_QUERY:
+ case PGRES_COMMAND_OK:
+ case PGRES_TUPLES_OK:
+ case PGRES_COPY_OUT:
+ case PGRES_COPY_IN:
+ case PGRES_COPY_BOTH:
+ case PGRES_SINGLE_TUPLE:
+ /* non-error cases */
+ break;
+ default:
+ /* we intentionally do not use or modify errorReported here */
+ pqSetResultError(result, &conn->errorMessage, 0);
+ break;
+ }
+
+ /* copy events last; result must be valid if we need to PQclear */
+ if (conn->nEvents > 0)
+ {
+ result->events = dupEvents(conn->events, conn->nEvents,
+ &result->memorySize);
+ if (!result->events)
+ {
+ PQclear(result);
+ return NULL;
+ }
+ result->nEvents = conn->nEvents;
+ }
+ }
+ else
+ {
+ /* defaults... */
+ result->noticeHooks.noticeRec = NULL;
+ result->noticeHooks.noticeRecArg = NULL;
+ result->noticeHooks.noticeProc = NULL;
+ result->noticeHooks.noticeProcArg = NULL;
+ result->client_encoding = PG_SQL_ASCII;
+ }
+
+ return result;
+}
+
+/*
+ * PQsetResultAttrs
+ *
+ * Set the attributes for a given result. This function fails if there are
+ * already attributes contained in the provided result. The call is
+ * ignored if numAttributes is zero or attDescs is NULL. If the
+ * function fails, it returns zero. If the function succeeds, it
+ * returns a non-zero value.
+ */
+int
+PQsetResultAttrs(PGresult *res, int numAttributes, PGresAttDesc *attDescs)
+{
+ int i;
+
+ /* Fail if argument is NULL or OOM_result */
+ if (!res || (const PGresult *) res == &OOM_result)
+ return false;
+
+ /* If attrs already exist, they cannot be overwritten. */
+ if (res->numAttributes > 0)
+ return false;
+
+ /* ignore no-op request */
+ if (numAttributes <= 0 || !attDescs)
+ return true;
+
+ res->attDescs = (PGresAttDesc *)
+ PQresultAlloc(res, numAttributes * sizeof(PGresAttDesc));
+
+ if (!res->attDescs)
+ return false;
+
+ res->numAttributes = numAttributes;
+ memcpy(res->attDescs, attDescs, numAttributes * sizeof(PGresAttDesc));
+
+ /* deep-copy the attribute names, and determine format */
+ res->binary = 1;
+ for (i = 0; i < res->numAttributes; i++)
+ {
+ if (res->attDescs[i].name)
+ res->attDescs[i].name = pqResultStrdup(res, res->attDescs[i].name);
+ else
+ res->attDescs[i].name = res->null_field;
+
+ if (!res->attDescs[i].name)
+ return false;
+
+ if (res->attDescs[i].format == 0)
+ res->binary = 0;
+ }
+
+ return true;
+}
+
+/*
+ * PQcopyResult
+ *
+ * Returns a deep copy of the provided 'src' PGresult, which cannot be NULL.
+ * The 'flags' argument controls which portions of the result will or will
+ * NOT be copied. The created result is always put into the
+ * PGRES_TUPLES_OK status. The source result error message is not copied,
+ * although cmdStatus is.
+ *
+ * To set custom attributes, use PQsetResultAttrs. That function requires
+ * that there are no attrs contained in the result, so to use that
+ * function you cannot use the PG_COPYRES_ATTRS or PG_COPYRES_TUPLES
+ * options with this function.
+ *
+ * Options:
+ * PG_COPYRES_ATTRS - Copy the source result's attributes
+ *
+ * PG_COPYRES_TUPLES - Copy the source result's tuples. This implies
+ * copying the attrs, seeing how the attrs are needed by the tuples.
+ *
+ * PG_COPYRES_EVENTS - Copy the source result's events.
+ *
+ * PG_COPYRES_NOTICEHOOKS - Copy the source result's notice hooks.
+ */
+PGresult *
+PQcopyResult(const PGresult *src, int flags)
+{
+ PGresult *dest;
+ int i;
+
+ if (!src)
+ return NULL;
+
+ dest = PQmakeEmptyPGresult(NULL, PGRES_TUPLES_OK);
+ if (!dest)
+ return NULL;
+
+ /* Always copy these over. Is cmdStatus really useful here? */
+ dest->client_encoding = src->client_encoding;
+ strcpy(dest->cmdStatus, src->cmdStatus);
+
+ /* Wants attrs? */
+ if (flags & (PG_COPYRES_ATTRS | PG_COPYRES_TUPLES))
+ {
+ if (!PQsetResultAttrs(dest, src->numAttributes, src->attDescs))
+ {
+ PQclear(dest);
+ return NULL;
+ }
+ }
+
+ /* Wants to copy tuples? */
+ if (flags & PG_COPYRES_TUPLES)
+ {
+ int tup,
+ field;
+
+ for (tup = 0; tup < src->ntups; tup++)
+ {
+ for (field = 0; field < src->numAttributes; field++)
+ {
+ if (!PQsetvalue(dest, tup, field,
+ src->tuples[tup][field].value,
+ src->tuples[tup][field].len))
+ {
+ PQclear(dest);
+ return NULL;
+ }
+ }
+ }
+ }
+
+ /* Wants to copy notice hooks? */
+ if (flags & PG_COPYRES_NOTICEHOOKS)
+ dest->noticeHooks = src->noticeHooks;
+
+ /* Wants to copy PGEvents? */
+ if ((flags & PG_COPYRES_EVENTS) && src->nEvents > 0)
+ {
+ dest->events = dupEvents(src->events, src->nEvents,
+ &dest->memorySize);
+ if (!dest->events)
+ {
+ PQclear(dest);
+ return NULL;
+ }
+ dest->nEvents = src->nEvents;
+ }
+
+ /* Okay, trigger PGEVT_RESULTCOPY event */
+ for (i = 0; i < dest->nEvents; i++)
+ {
+ /* We don't fire events that had some previous failure */
+ if (src->events[i].resultInitialized)
+ {
+ PGEventResultCopy evt;
+
+ evt.src = src;
+ evt.dest = dest;
+ if (dest->events[i].proc(PGEVT_RESULTCOPY, &evt,
+ dest->events[i].passThrough))
+ dest->events[i].resultInitialized = true;
+ }
+ }
+
+ return dest;
+}
+
+/*
+ * Copy an array of PGEvents (with no extra space for more).
+ * Does not duplicate the event instance data, sets this to NULL.
+ * Also, the resultInitialized flags are all cleared.
+ * The total space allocated is added to *memSize.
+ */
+static PGEvent *
+dupEvents(PGEvent *events, int count, size_t *memSize)
+{
+ PGEvent *newEvents;
+ size_t msize;
+ int i;
+
+ if (!events || count <= 0)
+ return NULL;
+
+ msize = count * sizeof(PGEvent);
+ newEvents = (PGEvent *) malloc(msize);
+ if (!newEvents)
+ return NULL;
+
+ for (i = 0; i < count; i++)
+ {
+ newEvents[i].proc = events[i].proc;
+ newEvents[i].passThrough = events[i].passThrough;
+ newEvents[i].data = NULL;
+ newEvents[i].resultInitialized = false;
+ newEvents[i].name = strdup(events[i].name);
+ if (!newEvents[i].name)
+ {
+ while (--i >= 0)
+ free(newEvents[i].name);
+ free(newEvents);
+ return NULL;
+ }
+ msize += strlen(events[i].name) + 1;
+ }
+
+ *memSize += msize;
+ return newEvents;
+}
+
+
+/*
+ * Sets the value for a tuple field. The tup_num must be less than or
+ * equal to PQntuples(res). If it is equal, a new tuple is created and
+ * added to the result.
+ * Returns a non-zero value for success and zero for failure.
+ * (On failure, we report the specific problem via pqInternalNotice.)
+ */
+int
+PQsetvalue(PGresult *res, int tup_num, int field_num, char *value, int len)
+{
+ PGresAttValue *attval;
+ const char *errmsg = NULL;
+
+ /* Fail if argument is NULL or OOM_result */
+ if (!res || (const PGresult *) res == &OOM_result)
+ return false;
+
+ /* Invalid field_num? */
+ if (!check_field_number(res, field_num))
+ return false;
+
+ /* Invalid tup_num, must be <= ntups */
+ if (tup_num < 0 || tup_num > res->ntups)
+ {
+ pqInternalNotice(&res->noticeHooks,
+ "row number %d is out of range 0..%d",
+ tup_num, res->ntups);
+ return false;
+ }
+
+ /* need to allocate a new tuple? */
+ if (tup_num == res->ntups)
+ {
+ PGresAttValue *tup;
+ int i;
+
+ tup = (PGresAttValue *)
+ pqResultAlloc(res, res->numAttributes * sizeof(PGresAttValue),
+ true);
+
+ if (!tup)
+ goto fail;
+
+ /* initialize each column to NULL */
+ for (i = 0; i < res->numAttributes; i++)
+ {
+ tup[i].len = NULL_LEN;
+ tup[i].value = res->null_field;
+ }
+
+ /* add it to the array */
+ if (!pqAddTuple(res, tup, &errmsg))
+ goto fail;
+ }
+
+ attval = &res->tuples[tup_num][field_num];
+
+ /* treat either NULL_LEN or NULL value pointer as a NULL field */
+ if (len == NULL_LEN || value == NULL)
+ {
+ attval->len = NULL_LEN;
+ attval->value = res->null_field;
+ }
+ else if (len <= 0)
+ {
+ attval->len = 0;
+ attval->value = res->null_field;
+ }
+ else
+ {
+ attval->value = (char *) pqResultAlloc(res, len + 1, true);
+ if (!attval->value)
+ goto fail;
+ attval->len = len;
+ memcpy(attval->value, value, len);
+ attval->value[len] = '\0';
+ }
+
+ return true;
+
+ /*
+ * Report failure via pqInternalNotice. If preceding code didn't provide
+ * an error message, assume "out of memory" was meant.
+ */
+fail:
+ if (!errmsg)
+ errmsg = libpq_gettext("out of memory");
+ pqInternalNotice(&res->noticeHooks, "%s", errmsg);
+
+ return false;
+}
+
+/*
+ * pqResultAlloc - exported routine to allocate local storage in a PGresult.
+ *
+ * We force all such allocations to be maxaligned, since we don't know
+ * whether the value might be binary.
+ */
+void *
+PQresultAlloc(PGresult *res, size_t nBytes)
+{
+ /* Fail if argument is NULL or OOM_result */
+ if (!res || (const PGresult *) res == &OOM_result)
+ return NULL;
+
+ return pqResultAlloc(res, nBytes, true);
+}
+
+/*
+ * pqResultAlloc -
+ * Allocate subsidiary storage for a PGresult.
+ *
+ * nBytes is the amount of space needed for the object.
+ * If isBinary is true, we assume that we need to align the object on
+ * a machine allocation boundary.
+ * If isBinary is false, we assume the object is a char string and can
+ * be allocated on any byte boundary.
+ */
+void *
+pqResultAlloc(PGresult *res, size_t nBytes, bool isBinary)
+{
+ char *space;
+ PGresult_data *block;
+
+ if (!res)
+ return NULL;
+
+ if (nBytes <= 0)
+ return res->null_field;
+
+ /*
+ * If alignment is needed, round up the current position to an alignment
+ * boundary.
+ */
+ if (isBinary)
+ {
+ int offset = res->curOffset % PGRESULT_ALIGN_BOUNDARY;
+
+ if (offset)
+ {
+ res->curOffset += PGRESULT_ALIGN_BOUNDARY - offset;
+ res->spaceLeft -= PGRESULT_ALIGN_BOUNDARY - offset;
+ }
+ }
+
+ /* If there's enough space in the current block, no problem. */
+ if (nBytes <= (size_t) res->spaceLeft)
+ {
+ space = res->curBlock->space + res->curOffset;
+ res->curOffset += nBytes;
+ res->spaceLeft -= nBytes;
+ return space;
+ }
+
+ /*
+ * If the requested object is very large, give it its own block; this
+ * avoids wasting what might be most of the current block to start a new
+ * block. (We'd have to special-case requests bigger than the block size
+ * anyway.) The object is always given binary alignment in this case.
+ */
+ if (nBytes >= PGRESULT_SEP_ALLOC_THRESHOLD)
+ {
+ size_t alloc_size = nBytes + PGRESULT_BLOCK_OVERHEAD;
+
+ block = (PGresult_data *) malloc(alloc_size);
+ if (!block)
+ return NULL;
+ res->memorySize += alloc_size;
+ space = block->space + PGRESULT_BLOCK_OVERHEAD;
+ if (res->curBlock)
+ {
+ /*
+ * Tuck special block below the active block, so that we don't
+ * have to waste the free space in the active block.
+ */
+ block->next = res->curBlock->next;
+ res->curBlock->next = block;
+ }
+ else
+ {
+ /* Must set up the new block as the first active block. */
+ block->next = NULL;
+ res->curBlock = block;
+ res->spaceLeft = 0; /* be sure it's marked full */
+ }
+ return space;
+ }
+
+ /* Otherwise, start a new block. */
+ block = (PGresult_data *) malloc(PGRESULT_DATA_BLOCKSIZE);
+ if (!block)
+ return NULL;
+ res->memorySize += PGRESULT_DATA_BLOCKSIZE;
+ block->next = res->curBlock;
+ res->curBlock = block;
+ if (isBinary)
+ {
+ /* object needs full alignment */
+ res->curOffset = PGRESULT_BLOCK_OVERHEAD;
+ res->spaceLeft = PGRESULT_DATA_BLOCKSIZE - PGRESULT_BLOCK_OVERHEAD;
+ }
+ else
+ {
+ /* we can cram it right after the overhead pointer */
+ res->curOffset = sizeof(PGresult_data);
+ res->spaceLeft = PGRESULT_DATA_BLOCKSIZE - sizeof(PGresult_data);
+ }
+
+ space = block->space + res->curOffset;
+ res->curOffset += nBytes;
+ res->spaceLeft -= nBytes;
+ return space;
+}
+
+/*
+ * PQresultMemorySize -
+ * Returns total space allocated for the PGresult.
+ */
+size_t
+PQresultMemorySize(const PGresult *res)
+{
+ if (!res)
+ return 0;
+ return res->memorySize;
+}
+
+/*
+ * pqResultStrdup -
+ * Like strdup, but the space is subsidiary PGresult space.
+ */
+char *
+pqResultStrdup(PGresult *res, const char *str)
+{
+ char *space = (char *) pqResultAlloc(res, strlen(str) + 1, false);
+
+ if (space)
+ strcpy(space, str);
+ return space;
+}
+
+/*
+ * pqSetResultError -
+ * assign a new error message to a PGresult
+ *
+ * Copy text from errorMessage buffer beginning at given offset
+ * (it's caller's responsibility that offset is valid)
+ */
+void
+pqSetResultError(PGresult *res, PQExpBuffer errorMessage, int offset)
+{
+ char *msg;
+
+ if (!res)
+ return;
+
+ /*
+ * We handle two OOM scenarios here. The errorMessage buffer might be
+ * marked "broken" due to having previously failed to allocate enough
+ * memory for the message, or it might be fine but pqResultStrdup fails
+ * and returns NULL. In either case, just make res->errMsg point directly
+ * at a constant "out of memory" string.
+ */
+ if (!PQExpBufferBroken(errorMessage))
+ msg = pqResultStrdup(res, errorMessage->data + offset);
+ else
+ msg = NULL;
+ if (msg)
+ res->errMsg = msg;
+ else
+ res->errMsg = libpq_gettext("out of memory\n");
+}
+
+/*
+ * PQclear -
+ * free's the memory associated with a PGresult
+ */
+void
+PQclear(PGresult *res)
+{
+ PGresult_data *block;
+ int i;
+
+ /* As a convenience, do nothing for a NULL pointer */
+ if (!res)
+ return;
+ /* Also, do nothing if the argument is OOM_result */
+ if ((const PGresult *) res == &OOM_result)
+ return;
+
+ /* Close down any events we may have */
+ for (i = 0; i < res->nEvents; i++)
+ {
+ /* only send DESTROY to successfully-initialized event procs */
+ if (res->events[i].resultInitialized)
+ {
+ PGEventResultDestroy evt;
+
+ evt.result = res;
+ (void) res->events[i].proc(PGEVT_RESULTDESTROY, &evt,
+ res->events[i].passThrough);
+ }
+ free(res->events[i].name);
+ }
+
+ free(res->events);
+
+ /* Free all the subsidiary blocks */
+ while ((block = res->curBlock) != NULL)
+ {
+ res->curBlock = block->next;
+ free(block);
+ }
+
+ /* Free the top-level tuple pointer array */
+ free(res->tuples);
+
+ /* zero out the pointer fields to catch programming errors */
+ res->attDescs = NULL;
+ res->tuples = NULL;
+ res->paramDescs = NULL;
+ res->errFields = NULL;
+ res->events = NULL;
+ res->nEvents = 0;
+ /* res->curBlock was zeroed out earlier */
+
+ /* Free the PGresult structure itself */
+ free(res);
+}
+
+/*
+ * Handy subroutine to deallocate any partially constructed async result.
+ *
+ * Any "next" result gets cleared too.
+ */
+void
+pqClearAsyncResult(PGconn *conn)
+{
+ PQclear(conn->result);
+ conn->result = NULL;
+ conn->error_result = false;
+ PQclear(conn->next_result);
+ conn->next_result = NULL;
+}
+
+/*
+ * pqSaveErrorResult -
+ * remember that we have an error condition
+ *
+ * In much of libpq, reporting an error just requires appending text to
+ * conn->errorMessage and returning a failure code to one's caller.
+ * Where returning a failure code is impractical, instead call this
+ * function to remember that an error needs to be reported.
+ *
+ * (It might seem that appending text to conn->errorMessage should be
+ * sufficient, but we can't rely on that working under out-of-memory
+ * conditions. The OOM hazard is also why we don't try to make a new
+ * PGresult right here.)
+ */
+void
+pqSaveErrorResult(PGconn *conn)
+{
+ /* Drop any pending result ... */
+ pqClearAsyncResult(conn);
+ /* ... and set flag to remember to make an error result later */
+ conn->error_result = true;
+}
+
+/*
+ * pqSaveWriteError -
+ * report a write failure
+ *
+ * As above, after appending conn->write_err_msg to whatever other error we
+ * have. This is used when we've detected a write failure and have exhausted
+ * our chances of reporting something else instead.
+ */
+static void
+pqSaveWriteError(PGconn *conn)
+{
+ /*
+ * If write_err_msg is null because of previous strdup failure, do what we
+ * can. (It's likely our machinations here will get OOM failures as well,
+ * but might as well try.)
+ */
+ if (conn->write_err_msg)
+ {
+ appendPQExpBufferStr(&conn->errorMessage, conn->write_err_msg);
+ /* Avoid possibly appending the same message twice */
+ conn->write_err_msg[0] = '\0';
+ }
+ else
+ libpq_append_conn_error(conn, "write to server failed");
+
+ pqSaveErrorResult(conn);
+}
+
+/*
+ * pqPrepareAsyncResult -
+ * prepare the current async result object for return to the caller
+ *
+ * If there is not already an async result object, build an error object
+ * using whatever is in conn->errorMessage. In any case, clear the async
+ * result storage, and update our notion of how much error text has been
+ * returned to the application.
+ */
+PGresult *
+pqPrepareAsyncResult(PGconn *conn)
+{
+ PGresult *res;
+
+ res = conn->result;
+ if (res)
+ {
+ /*
+ * If the pre-existing result is an ERROR (presumably something
+ * received from the server), assume that it represents whatever is in
+ * conn->errorMessage, and advance errorReported.
+ */
+ if (res->resultStatus == PGRES_FATAL_ERROR)
+ conn->errorReported = conn->errorMessage.len;
+ }
+ else
+ {
+ /*
+ * We get here after internal-to-libpq errors. We should probably
+ * always have error_result = true, but if we don't, gin up some error
+ * text.
+ */
+ if (!conn->error_result)
+ libpq_append_conn_error(conn, "no error text available");
+
+ /* Paranoia: be sure errorReported offset is sane */
+ if (conn->errorReported < 0 ||
+ conn->errorReported >= conn->errorMessage.len)
+ conn->errorReported = 0;
+
+ /*
+ * Make a PGresult struct for the error. We temporarily lie about the
+ * result status, so that PQmakeEmptyPGresult doesn't uselessly copy
+ * all of conn->errorMessage.
+ */
+ res = PQmakeEmptyPGresult(conn, PGRES_EMPTY_QUERY);
+ if (res)
+ {
+ /*
+ * Report whatever new error text we have, and advance
+ * errorReported.
+ */
+ res->resultStatus = PGRES_FATAL_ERROR;
+ pqSetResultError(res, &conn->errorMessage, conn->errorReported);
+ conn->errorReported = conn->errorMessage.len;
+ }
+ else
+ {
+ /*
+ * Ouch, not enough memory for a PGresult. Fortunately, we have a
+ * card up our sleeve: we can use the static OOM_result. Casting
+ * away const here is a bit ugly, but it seems best to declare
+ * OOM_result as const, in hopes it will be allocated in read-only
+ * storage.
+ */
+ res = unconstify(PGresult *, &OOM_result);
+
+ /*
+ * Don't advance errorReported. Perhaps we'll be able to report
+ * the text later.
+ */
+ }
+ }
+
+ /*
+ * Replace conn->result with next_result, if any. In the normal case
+ * there isn't a next result and we're just dropping ownership of the
+ * current result. In single-row mode this restores the situation to what
+ * it was before we created the current single-row result.
+ */
+ conn->result = conn->next_result;
+ conn->error_result = false; /* next_result is never an error */
+ conn->next_result = NULL;
+
+ return res;
+}
+
+/*
+ * pqInternalNotice - produce an internally-generated notice message
+ *
+ * A format string and optional arguments can be passed. Note that we do
+ * libpq_gettext() here, so callers need not.
+ *
+ * The supplied text is taken as primary message (ie., it should not include
+ * a trailing newline, and should not be more than one line).
+ */
+void
+pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt,...)
+{
+ char msgBuf[1024];
+ va_list args;
+ PGresult *res;
+
+ if (hooks->noticeRec == NULL)
+ return; /* nobody home to receive notice? */
+
+ /* Format the message */
+ va_start(args, fmt);
+ vsnprintf(msgBuf, sizeof(msgBuf), libpq_gettext(fmt), args);
+ va_end(args);
+ msgBuf[sizeof(msgBuf) - 1] = '\0'; /* make real sure it's terminated */
+
+ /* Make a PGresult to pass to the notice receiver */
+ res = PQmakeEmptyPGresult(NULL, PGRES_NONFATAL_ERROR);
+ if (!res)
+ return;
+ res->noticeHooks = *hooks;
+
+ /*
+ * Set up fields of notice.
+ */
+ pqSaveMessageField(res, PG_DIAG_MESSAGE_PRIMARY, msgBuf);
+ pqSaveMessageField(res, PG_DIAG_SEVERITY, libpq_gettext("NOTICE"));
+ pqSaveMessageField(res, PG_DIAG_SEVERITY_NONLOCALIZED, "NOTICE");
+ /* XXX should provide a SQLSTATE too? */
+
+ /*
+ * Result text is always just the primary message + newline. If we can't
+ * allocate it, substitute "out of memory", as in pqSetResultError.
+ */
+ res->errMsg = (char *) pqResultAlloc(res, strlen(msgBuf) + 2, false);
+ if (res->errMsg)
+ sprintf(res->errMsg, "%s\n", msgBuf);
+ else
+ res->errMsg = libpq_gettext("out of memory\n");
+
+ /*
+ * Pass to receiver, then free it.
+ */
+ res->noticeHooks.noticeRec(res->noticeHooks.noticeRecArg, res);
+ PQclear(res);
+}
+
+/*
+ * pqAddTuple
+ * add a row pointer to the PGresult structure, growing it if necessary
+ * Returns true if OK, false if an error prevented adding the row
+ *
+ * On error, *errmsgp can be set to an error string to be returned.
+ * If it is left NULL, the error is presumed to be "out of memory".
+ */
+static bool
+pqAddTuple(PGresult *res, PGresAttValue *tup, const char **errmsgp)
+{
+ if (res->ntups >= res->tupArrSize)
+ {
+ /*
+ * Try to grow the array.
+ *
+ * We can use realloc because shallow copying of the structure is
+ * okay. Note that the first time through, res->tuples is NULL. While
+ * ANSI says that realloc() should act like malloc() in that case,
+ * some old C libraries (like SunOS 4.1.x) coredump instead. On
+ * failure realloc is supposed to return NULL without damaging the
+ * existing allocation. Note that the positions beyond res->ntups are
+ * garbage, not necessarily NULL.
+ */
+ int newSize;
+ PGresAttValue **newTuples;
+
+ /*
+ * Since we use integers for row numbers, we can't support more than
+ * INT_MAX rows. Make sure we allow that many, though.
+ */
+ if (res->tupArrSize <= INT_MAX / 2)
+ newSize = (res->tupArrSize > 0) ? res->tupArrSize * 2 : 128;
+ else if (res->tupArrSize < INT_MAX)
+ newSize = INT_MAX;
+ else
+ {
+ *errmsgp = libpq_gettext("PGresult cannot support more than INT_MAX tuples");
+ return false;
+ }
+
+ /*
+ * Also, on 32-bit platforms we could, in theory, overflow size_t even
+ * before newSize gets to INT_MAX. (In practice we'd doubtless hit
+ * OOM long before that, but let's check.)
+ */
+#if INT_MAX >= (SIZE_MAX / 2)
+ if (newSize > SIZE_MAX / sizeof(PGresAttValue *))
+ {
+ *errmsgp = libpq_gettext("size_t overflow");
+ return false;
+ }
+#endif
+
+ if (res->tuples == NULL)
+ newTuples = (PGresAttValue **)
+ malloc(newSize * sizeof(PGresAttValue *));
+ else
+ newTuples = (PGresAttValue **)
+ realloc(res->tuples, newSize * sizeof(PGresAttValue *));
+ if (!newTuples)
+ return false; /* malloc or realloc failed */
+ res->memorySize +=
+ (newSize - res->tupArrSize) * sizeof(PGresAttValue *);
+ res->tupArrSize = newSize;
+ res->tuples = newTuples;
+ }
+ res->tuples[res->ntups] = tup;
+ res->ntups++;
+ return true;
+}
+
+/*
+ * pqSaveMessageField - save one field of an error or notice message
+ */
+void
+pqSaveMessageField(PGresult *res, char code, const char *value)
+{
+ PGMessageField *pfield;
+
+ pfield = (PGMessageField *)
+ pqResultAlloc(res,
+ offsetof(PGMessageField, contents) +
+ strlen(value) + 1,
+ true);
+ if (!pfield)
+ return; /* out of memory? */
+ pfield->code = code;
+ strcpy(pfield->contents, value);
+ pfield->next = res->errFields;
+ res->errFields = pfield;
+}
+
+/*
+ * pqSaveParameterStatus - remember parameter status sent by backend
+ */
+void
+pqSaveParameterStatus(PGconn *conn, const char *name, const char *value)
+{
+ pgParameterStatus *pstatus;
+ pgParameterStatus *prev;
+
+ /*
+ * Forget any old information about the parameter
+ */
+ for (pstatus = conn->pstatus, prev = NULL;
+ pstatus != NULL;
+ prev = pstatus, pstatus = pstatus->next)
+ {
+ if (strcmp(pstatus->name, name) == 0)
+ {
+ if (prev)
+ prev->next = pstatus->next;
+ else
+ conn->pstatus = pstatus->next;
+ free(pstatus); /* frees name and value strings too */
+ break;
+ }
+ }
+
+ /*
+ * Store new info as a single malloc block
+ */
+ pstatus = (pgParameterStatus *) malloc(sizeof(pgParameterStatus) +
+ strlen(name) + strlen(value) + 2);
+ if (pstatus)
+ {
+ char *ptr;
+
+ ptr = ((char *) pstatus) + sizeof(pgParameterStatus);
+ pstatus->name = ptr;
+ strcpy(ptr, name);
+ ptr += strlen(name) + 1;
+ pstatus->value = ptr;
+ strcpy(ptr, value);
+ pstatus->next = conn->pstatus;
+ conn->pstatus = pstatus;
+ }
+
+ /*
+ * Save values of settings that are of interest to libpq in fields of the
+ * PGconn object. We keep client_encoding and standard_conforming_strings
+ * in static variables as well, so that PQescapeString and PQescapeBytea
+ * can behave somewhat sanely (at least in single-connection-using
+ * programs).
+ */
+ if (strcmp(name, "client_encoding") == 0)
+ {
+ conn->client_encoding = pg_char_to_encoding(value);
+ /* if we don't recognize the encoding name, fall back to SQL_ASCII */
+ if (conn->client_encoding < 0)
+ conn->client_encoding = PG_SQL_ASCII;
+ static_client_encoding = conn->client_encoding;
+ }
+ else if (strcmp(name, "standard_conforming_strings") == 0)
+ {
+ conn->std_strings = (strcmp(value, "on") == 0);
+ static_std_strings = conn->std_strings;
+ }
+ else if (strcmp(name, "server_version") == 0)
+ {
+ /* We convert the server version to numeric form. */
+ int cnt;
+ int vmaj,
+ vmin,
+ vrev;
+
+ cnt = sscanf(value, "%d.%d.%d", &vmaj, &vmin, &vrev);
+
+ if (cnt == 3)
+ {
+ /* old style, e.g. 9.6.1 */
+ conn->sversion = (100 * vmaj + vmin) * 100 + vrev;
+ }
+ else if (cnt == 2)
+ {
+ if (vmaj >= 10)
+ {
+ /* new style, e.g. 10.1 */
+ conn->sversion = 100 * 100 * vmaj + vmin;
+ }
+ else
+ {
+ /* old style without minor version, e.g. 9.6devel */
+ conn->sversion = (100 * vmaj + vmin) * 100;
+ }
+ }
+ else if (cnt == 1)
+ {
+ /* new style without minor version, e.g. 10devel */
+ conn->sversion = 100 * 100 * vmaj;
+ }
+ else
+ conn->sversion = 0; /* unknown */
+ }
+ else if (strcmp(name, "default_transaction_read_only") == 0)
+ {
+ conn->default_transaction_read_only =
+ (strcmp(value, "on") == 0) ? PG_BOOL_YES : PG_BOOL_NO;
+ }
+ else if (strcmp(name, "in_hot_standby") == 0)
+ {
+ conn->in_hot_standby =
+ (strcmp(value, "on") == 0) ? PG_BOOL_YES : PG_BOOL_NO;
+ }
+ else if (strcmp(name, "scram_iterations") == 0)
+ {
+ conn->scram_sha_256_iterations = atoi(value);
+ }
+}
+
+
+/*
+ * pqRowProcessor
+ * Add the received row to the current async result (conn->result).
+ * Returns 1 if OK, 0 if error occurred.
+ *
+ * On error, *errmsgp can be set to an error string to be returned.
+ * (Such a string should already be translated via libpq_gettext().)
+ * If it is left NULL, the error is presumed to be "out of memory".
+ *
+ * In single-row mode, we create a new result holding just the current row,
+ * stashing the previous result in conn->next_result so that it becomes
+ * active again after pqPrepareAsyncResult(). This allows the result metadata
+ * (column descriptions) to be carried forward to each result row.
+ */
+int
+pqRowProcessor(PGconn *conn, const char **errmsgp)
+{
+ PGresult *res = conn->result;
+ int nfields = res->numAttributes;
+ const PGdataValue *columns = conn->rowBuf;
+ PGresAttValue *tup;
+ int i;
+
+ /*
+ * In single-row mode, make a new PGresult that will hold just this one
+ * row; the original conn->result is left unchanged so that it can be used
+ * again as the template for future rows.
+ */
+ if (conn->singleRowMode)
+ {
+ /* Copy everything that should be in the result at this point */
+ res = PQcopyResult(res,
+ PG_COPYRES_ATTRS | PG_COPYRES_EVENTS |
+ PG_COPYRES_NOTICEHOOKS);
+ if (!res)
+ return 0;
+ }
+
+ /*
+ * Basically we just allocate space in the PGresult for each field and
+ * copy the data over.
+ *
+ * Note: on malloc failure, we return 0 leaving *errmsgp still NULL, which
+ * caller will take to mean "out of memory". This is preferable to trying
+ * to set up such a message here, because evidently there's not enough
+ * memory for gettext() to do anything.
+ */
+ tup = (PGresAttValue *)
+ pqResultAlloc(res, nfields * sizeof(PGresAttValue), true);
+ if (tup == NULL)
+ goto fail;
+
+ for (i = 0; i < nfields; i++)
+ {
+ int clen = columns[i].len;
+
+ if (clen < 0)
+ {
+ /* null field */
+ tup[i].len = NULL_LEN;
+ tup[i].value = res->null_field;
+ }
+ else
+ {
+ bool isbinary = (res->attDescs[i].format != 0);
+ char *val;
+
+ val = (char *) pqResultAlloc(res, clen + 1, isbinary);
+ if (val == NULL)
+ goto fail;
+
+ /* copy and zero-terminate the data (even if it's binary) */
+ memcpy(val, columns[i].value, clen);
+ val[clen] = '\0';
+
+ tup[i].len = clen;
+ tup[i].value = val;
+ }
+ }
+
+ /* And add the tuple to the PGresult's tuple array */
+ if (!pqAddTuple(res, tup, errmsgp))
+ goto fail;
+
+ /*
+ * Success. In single-row mode, make the result available to the client
+ * immediately.
+ */
+ if (conn->singleRowMode)
+ {
+ /* Change result status to special single-row value */
+ res->resultStatus = PGRES_SINGLE_TUPLE;
+ /* Stash old result for re-use later */
+ conn->next_result = conn->result;
+ conn->result = res;
+ /* And mark the result ready to return */
+ conn->asyncStatus = PGASYNC_READY_MORE;
+ }
+
+ return 1;
+
+fail:
+ /* release locally allocated PGresult, if we made one */
+ if (res != conn->result)
+ PQclear(res);
+ return 0;
+}
+
+
+/*
+ * pqAllocCmdQueueEntry
+ * Get a command queue entry for caller to fill.
+ *
+ * If the recycle queue has a free element, that is returned; if not, a
+ * fresh one is allocated. Caller is responsible for adding it to the
+ * command queue (pqAppendCmdQueueEntry) once the struct is filled in, or
+ * releasing the memory (pqRecycleCmdQueueEntry) if an error occurs.
+ *
+ * If allocation fails, sets the error message and returns NULL.
+ */
+static PGcmdQueueEntry *
+pqAllocCmdQueueEntry(PGconn *conn)
+{
+ PGcmdQueueEntry *entry;
+
+ if (conn->cmd_queue_recycle == NULL)
+ {
+ entry = (PGcmdQueueEntry *) malloc(sizeof(PGcmdQueueEntry));
+ if (entry == NULL)
+ {
+ libpq_append_conn_error(conn, "out of memory");
+ return NULL;
+ }
+ }
+ else
+ {
+ entry = conn->cmd_queue_recycle;
+ conn->cmd_queue_recycle = entry->next;
+ }
+ entry->next = NULL;
+ entry->query = NULL;
+
+ return entry;
+}
+
+/*
+ * pqAppendCmdQueueEntry
+ * Append a caller-allocated entry to the command queue, and update
+ * conn->asyncStatus to account for it.
+ *
+ * The query itself must already have been put in the output buffer by the
+ * caller.
+ */
+static void
+pqAppendCmdQueueEntry(PGconn *conn, PGcmdQueueEntry *entry)
+{
+ Assert(entry->next == NULL);
+
+ if (conn->cmd_queue_head == NULL)
+ conn->cmd_queue_head = entry;
+ else
+ conn->cmd_queue_tail->next = entry;
+
+ conn->cmd_queue_tail = entry;
+
+ switch (conn->pipelineStatus)
+ {
+ case PQ_PIPELINE_OFF:
+ case PQ_PIPELINE_ON:
+
+ /*
+ * When not in pipeline aborted state, if there's a result ready
+ * to be consumed, let it be so (that is, don't change away from
+ * READY or READY_MORE); otherwise set us busy to wait for
+ * something to arrive from the server.
+ */
+ if (conn->asyncStatus == PGASYNC_IDLE)
+ conn->asyncStatus = PGASYNC_BUSY;
+ break;
+
+ case PQ_PIPELINE_ABORTED:
+
+ /*
+ * In aborted pipeline state, we don't expect anything from the
+ * server (since we don't send any queries that are queued).
+ * Therefore, if IDLE then do what PQgetResult would do to let
+ * itself consume commands from the queue; if we're in any other
+ * state, we don't have to do anything.
+ */
+ if (conn->asyncStatus == PGASYNC_IDLE ||
+ conn->asyncStatus == PGASYNC_PIPELINE_IDLE)
+ pqPipelineProcessQueue(conn);
+ break;
+ }
+}
+
+/*
+ * pqRecycleCmdQueueEntry
+ * Push a command queue entry onto the freelist.
+ */
+static void
+pqRecycleCmdQueueEntry(PGconn *conn, PGcmdQueueEntry *entry)
+{
+ if (entry == NULL)
+ return;
+
+ /* recyclable entries should not have a follow-on command */
+ Assert(entry->next == NULL);
+
+ if (entry->query)
+ {
+ free(entry->query);
+ entry->query = NULL;
+ }
+
+ entry->next = conn->cmd_queue_recycle;
+ conn->cmd_queue_recycle = entry;
+}
+
+
+/*
+ * PQsendQuery
+ * Submit a query, but don't wait for it to finish
+ *
+ * Returns: 1 if successfully submitted
+ * 0 if error (conn->errorMessage is set)
+ *
+ * PQsendQueryContinue is a non-exported version that behaves identically
+ * except that it doesn't reset conn->errorMessage.
+ */
+int
+PQsendQuery(PGconn *conn, const char *query)
+{
+ return PQsendQueryInternal(conn, query, true);
+}
+
+int
+PQsendQueryContinue(PGconn *conn, const char *query)
+{
+ return PQsendQueryInternal(conn, query, false);
+}
+
+static int
+PQsendQueryInternal(PGconn *conn, const char *query, bool newQuery)
+{
+ PGcmdQueueEntry *entry = NULL;
+
+ if (!PQsendQueryStart(conn, newQuery))
+ return 0;
+
+ /* check the argument */
+ if (!query)
+ {
+ libpq_append_conn_error(conn, "command string is a null pointer");
+ return 0;
+ }
+
+ if (conn->pipelineStatus != PQ_PIPELINE_OFF)
+ {
+ libpq_append_conn_error(conn, "%s not allowed in pipeline mode",
+ "PQsendQuery");
+ return 0;
+ }
+
+ entry = pqAllocCmdQueueEntry(conn);
+ if (entry == NULL)
+ return 0; /* error msg already set */
+
+ /* Send the query message(s) */
+ /* construct the outgoing Query message */
+ if (pqPutMsgStart('Q', conn) < 0 ||
+ pqPuts(query, conn) < 0 ||
+ pqPutMsgEnd(conn) < 0)
+ {
+ /* error message should be set up already */
+ pqRecycleCmdQueueEntry(conn, entry);
+ return 0;
+ }
+
+ /* remember we are using simple query protocol */
+ entry->queryclass = PGQUERY_SIMPLE;
+ /* and remember the query text too, if possible */
+ entry->query = strdup(query);
+
+ /*
+ * Give the data a push. In nonblock mode, don't complain if we're unable
+ * to send it all; PQgetResult() will do any additional flushing needed.
+ */
+ if (pqFlush(conn) < 0)
+ goto sendFailed;
+
+ /* OK, it's launched! */
+ pqAppendCmdQueueEntry(conn, entry);
+
+ return 1;
+
+sendFailed:
+ pqRecycleCmdQueueEntry(conn, entry);
+ /* error message should be set up already */
+ return 0;
+}
+
+/*
+ * PQsendQueryParams
+ * Like PQsendQuery, but use extended query protocol so we can pass parameters
+ */
+int
+PQsendQueryParams(PGconn *conn,
+ const char *command,
+ int nParams,
+ const Oid *paramTypes,
+ const char *const *paramValues,
+ const int *paramLengths,
+ const int *paramFormats,
+ int resultFormat)
+{
+ if (!PQsendQueryStart(conn, true))
+ return 0;
+
+ /* check the arguments */
+ if (!command)
+ {
+ libpq_append_conn_error(conn, "command string is a null pointer");
+ return 0;
+ }
+ if (nParams < 0 || nParams > PQ_QUERY_PARAM_MAX_LIMIT)
+ {
+ libpq_append_conn_error(conn, "number of parameters must be between 0 and %d",
+ PQ_QUERY_PARAM_MAX_LIMIT);
+ return 0;
+ }
+
+ return PQsendQueryGuts(conn,
+ command,
+ "", /* use unnamed statement */
+ nParams,
+ paramTypes,
+ paramValues,
+ paramLengths,
+ paramFormats,
+ resultFormat);
+}
+
+/*
+ * PQsendPrepare
+ * Submit a Parse message, but don't wait for it to finish
+ *
+ * Returns: 1 if successfully submitted
+ * 0 if error (conn->errorMessage is set)
+ */
+int
+PQsendPrepare(PGconn *conn,
+ const char *stmtName, const char *query,
+ int nParams, const Oid *paramTypes)
+{
+ PGcmdQueueEntry *entry = NULL;
+
+ if (!PQsendQueryStart(conn, true))
+ return 0;
+
+ /* check the arguments */
+ if (!stmtName)
+ {
+ libpq_append_conn_error(conn, "statement name is a null pointer");
+ return 0;
+ }
+ if (!query)
+ {
+ libpq_append_conn_error(conn, "command string is a null pointer");
+ return 0;
+ }
+ if (nParams < 0 || nParams > PQ_QUERY_PARAM_MAX_LIMIT)
+ {
+ libpq_append_conn_error(conn, "number of parameters must be between 0 and %d",
+ PQ_QUERY_PARAM_MAX_LIMIT);
+ return 0;
+ }
+
+ entry = pqAllocCmdQueueEntry(conn);
+ if (entry == NULL)
+ return 0; /* error msg already set */
+
+ /* construct the Parse message */
+ if (pqPutMsgStart('P', conn) < 0 ||
+ pqPuts(stmtName, conn) < 0 ||
+ pqPuts(query, conn) < 0)
+ goto sendFailed;
+
+ if (nParams > 0 && paramTypes)
+ {
+ int i;
+
+ if (pqPutInt(nParams, 2, conn) < 0)
+ goto sendFailed;
+ for (i = 0; i < nParams; i++)
+ {
+ if (pqPutInt(paramTypes[i], 4, conn) < 0)
+ goto sendFailed;
+ }
+ }
+ else
+ {
+ if (pqPutInt(0, 2, conn) < 0)
+ goto sendFailed;
+ }
+ if (pqPutMsgEnd(conn) < 0)
+ goto sendFailed;
+
+ /* Add a Sync, unless in pipeline mode. */
+ if (conn->pipelineStatus == PQ_PIPELINE_OFF)
+ {
+ if (pqPutMsgStart('S', conn) < 0 ||
+ pqPutMsgEnd(conn) < 0)
+ goto sendFailed;
+ }
+
+ /* remember we are doing just a Parse */
+ entry->queryclass = PGQUERY_PREPARE;
+
+ /* and remember the query text too, if possible */
+ /* if insufficient memory, query just winds up NULL */
+ entry->query = strdup(query);
+
+ /*
+ * Give the data a push (in pipeline mode, only if we're past the size
+ * threshold). In nonblock mode, don't complain if we're unable to send
+ * it all; PQgetResult() will do any additional flushing needed.
+ */
+ if (pqPipelineFlush(conn) < 0)
+ goto sendFailed;
+
+ /* OK, it's launched! */
+ pqAppendCmdQueueEntry(conn, entry);
+
+ return 1;
+
+sendFailed:
+ pqRecycleCmdQueueEntry(conn, entry);
+ /* error message should be set up already */
+ return 0;
+}
+
+/*
+ * PQsendQueryPrepared
+ * Like PQsendQuery, but execute a previously prepared statement,
+ * using extended query protocol so we can pass parameters
+ */
+int
+PQsendQueryPrepared(PGconn *conn,
+ const char *stmtName,
+ int nParams,
+ const char *const *paramValues,
+ const int *paramLengths,
+ const int *paramFormats,
+ int resultFormat)
+{
+ if (!PQsendQueryStart(conn, true))
+ return 0;
+
+ /* check the arguments */
+ if (!stmtName)
+ {
+ libpq_append_conn_error(conn, "statement name is a null pointer");
+ return 0;
+ }
+ if (nParams < 0 || nParams > PQ_QUERY_PARAM_MAX_LIMIT)
+ {
+ libpq_append_conn_error(conn, "number of parameters must be between 0 and %d",
+ PQ_QUERY_PARAM_MAX_LIMIT);
+ return 0;
+ }
+
+ return PQsendQueryGuts(conn,
+ NULL, /* no command to parse */
+ stmtName,
+ nParams,
+ NULL, /* no param types */
+ paramValues,
+ paramLengths,
+ paramFormats,
+ resultFormat);
+}
+
+/*
+ * PQsendQueryStart
+ * Common startup code for PQsendQuery and sibling routines
+ */
+static bool
+PQsendQueryStart(PGconn *conn, bool newQuery)
+{
+ if (!conn)
+ return false;
+
+ /*
+ * If this is the beginning of a query cycle, reset the error state.
+ * However, in pipeline mode with something already queued, the error
+ * buffer belongs to that command and we shouldn't clear it.
+ */
+ if (newQuery && conn->cmd_queue_head == NULL)
+ pqClearConnErrorState(conn);
+
+ /* Don't try to send if we know there's no live connection. */
+ if (conn->status != CONNECTION_OK)
+ {
+ libpq_append_conn_error(conn, "no connection to the server");
+ return false;
+ }
+
+ /* Can't send while already busy, either, unless enqueuing for later */
+ if (conn->asyncStatus != PGASYNC_IDLE &&
+ conn->pipelineStatus == PQ_PIPELINE_OFF)
+ {
+ libpq_append_conn_error(conn, "another command is already in progress");
+ return false;
+ }
+
+ if (conn->pipelineStatus != PQ_PIPELINE_OFF)
+ {
+ /*
+ * When enqueuing commands we don't change much of the connection
+ * state since it's already in use for the current command. The
+ * connection state will get updated when pqPipelineProcessQueue()
+ * advances to start processing the queued message.
+ *
+ * Just make sure we can safely enqueue given the current connection
+ * state. We can enqueue behind another queue item, or behind a
+ * non-queue command (one that sends its own sync), but we can't
+ * enqueue if the connection is in a copy state.
+ */
+ switch (conn->asyncStatus)
+ {
+ case PGASYNC_IDLE:
+ case PGASYNC_PIPELINE_IDLE:
+ case PGASYNC_READY:
+ case PGASYNC_READY_MORE:
+ case PGASYNC_BUSY:
+ /* ok to queue */
+ break;
+
+ case PGASYNC_COPY_IN:
+ case PGASYNC_COPY_OUT:
+ case PGASYNC_COPY_BOTH:
+ libpq_append_conn_error(conn, "cannot queue commands during COPY");
+ return false;
+ }
+ }
+ else
+ {
+ /*
+ * This command's results will come in immediately. Initialize async
+ * result-accumulation state
+ */
+ pqClearAsyncResult(conn);
+
+ /* reset single-row processing mode */
+ conn->singleRowMode = false;
+ }
+
+ /* ready to send command message */
+ return true;
+}
+
+/*
+ * PQsendQueryGuts
+ * Common code for sending a query with extended query protocol
+ * PQsendQueryStart should be done already
+ *
+ * command may be NULL to indicate we use an already-prepared statement
+ */
+static int
+PQsendQueryGuts(PGconn *conn,
+ const char *command,
+ const char *stmtName,
+ int nParams,
+ const Oid *paramTypes,
+ const char *const *paramValues,
+ const int *paramLengths,
+ const int *paramFormats,
+ int resultFormat)
+{
+ int i;
+ PGcmdQueueEntry *entry;
+
+ entry = pqAllocCmdQueueEntry(conn);
+ if (entry == NULL)
+ return 0; /* error msg already set */
+
+ /*
+ * We will send Parse (if needed), Bind, Describe Portal, Execute, Sync
+ * (if not in pipeline mode), using specified statement name and the
+ * unnamed portal.
+ */
+
+ if (command)
+ {
+ /* construct the Parse message */
+ if (pqPutMsgStart('P', conn) < 0 ||
+ pqPuts(stmtName, conn) < 0 ||
+ pqPuts(command, conn) < 0)
+ goto sendFailed;
+ if (nParams > 0 && paramTypes)
+ {
+ if (pqPutInt(nParams, 2, conn) < 0)
+ goto sendFailed;
+ for (i = 0; i < nParams; i++)
+ {
+ if (pqPutInt(paramTypes[i], 4, conn) < 0)
+ goto sendFailed;
+ }
+ }
+ else
+ {
+ if (pqPutInt(0, 2, conn) < 0)
+ goto sendFailed;
+ }
+ if (pqPutMsgEnd(conn) < 0)
+ goto sendFailed;
+ }
+
+ /* Construct the Bind message */
+ if (pqPutMsgStart('B', conn) < 0 ||
+ pqPuts("", conn) < 0 ||
+ pqPuts(stmtName, conn) < 0)
+ goto sendFailed;
+
+ /* Send parameter formats */
+ if (nParams > 0 && paramFormats)
+ {
+ if (pqPutInt(nParams, 2, conn) < 0)
+ goto sendFailed;
+ for (i = 0; i < nParams; i++)
+ {
+ if (pqPutInt(paramFormats[i], 2, conn) < 0)
+ goto sendFailed;
+ }
+ }
+ else
+ {
+ if (pqPutInt(0, 2, conn) < 0)
+ goto sendFailed;
+ }
+
+ if (pqPutInt(nParams, 2, conn) < 0)
+ goto sendFailed;
+
+ /* Send parameters */
+ for (i = 0; i < nParams; i++)
+ {
+ if (paramValues && paramValues[i])
+ {
+ int nbytes;
+
+ if (paramFormats && paramFormats[i] != 0)
+ {
+ /* binary parameter */
+ if (paramLengths)
+ nbytes = paramLengths[i];
+ else
+ {
+ libpq_append_conn_error(conn, "length must be given for binary parameter");
+ goto sendFailed;
+ }
+ }
+ else
+ {
+ /* text parameter, do not use paramLengths */
+ nbytes = strlen(paramValues[i]);
+ }
+ if (pqPutInt(nbytes, 4, conn) < 0 ||
+ pqPutnchar(paramValues[i], nbytes, conn) < 0)
+ goto sendFailed;
+ }
+ else
+ {
+ /* take the param as NULL */
+ if (pqPutInt(-1, 4, conn) < 0)
+ goto sendFailed;
+ }
+ }
+ if (pqPutInt(1, 2, conn) < 0 ||
+ pqPutInt(resultFormat, 2, conn))
+ goto sendFailed;
+ if (pqPutMsgEnd(conn) < 0)
+ goto sendFailed;
+
+ /* construct the Describe Portal message */
+ if (pqPutMsgStart('D', conn) < 0 ||
+ pqPutc('P', conn) < 0 ||
+ pqPuts("", conn) < 0 ||
+ pqPutMsgEnd(conn) < 0)
+ goto sendFailed;
+
+ /* construct the Execute message */
+ if (pqPutMsgStart('E', conn) < 0 ||
+ pqPuts("", conn) < 0 ||
+ pqPutInt(0, 4, conn) < 0 ||
+ pqPutMsgEnd(conn) < 0)
+ goto sendFailed;
+
+ /* construct the Sync message if not in pipeline mode */
+ if (conn->pipelineStatus == PQ_PIPELINE_OFF)
+ {
+ if (pqPutMsgStart('S', conn) < 0 ||
+ pqPutMsgEnd(conn) < 0)
+ goto sendFailed;
+ }
+
+ /* remember we are using extended query protocol */
+ entry->queryclass = PGQUERY_EXTENDED;
+
+ /* and remember the query text too, if possible */
+ /* if insufficient memory, query just winds up NULL */
+ if (command)
+ entry->query = strdup(command);
+
+ /*
+ * Give the data a push (in pipeline mode, only if we're past the size
+ * threshold). In nonblock mode, don't complain if we're unable to send
+ * it all; PQgetResult() will do any additional flushing needed.
+ */
+ if (pqPipelineFlush(conn) < 0)
+ goto sendFailed;
+
+ /* OK, it's launched! */
+ pqAppendCmdQueueEntry(conn, entry);
+
+ return 1;
+
+sendFailed:
+ pqRecycleCmdQueueEntry(conn, entry);
+ /* error message should be set up already */
+ return 0;
+}
+
+/*
+ * Select row-by-row processing mode
+ */
+int
+PQsetSingleRowMode(PGconn *conn)
+{
+ /*
+ * Only allow setting the flag when we have launched a query and not yet
+ * received any results.
+ */
+ if (!conn)
+ return 0;
+ if (conn->asyncStatus != PGASYNC_BUSY)
+ return 0;
+ if (!conn->cmd_queue_head ||
+ (conn->cmd_queue_head->queryclass != PGQUERY_SIMPLE &&
+ conn->cmd_queue_head->queryclass != PGQUERY_EXTENDED))
+ return 0;
+ if (pgHavePendingResult(conn))
+ return 0;
+
+ /* OK, set flag */
+ conn->singleRowMode = true;
+ return 1;
+}
+
+/*
+ * Consume any available input from the backend
+ * 0 return: some kind of trouble
+ * 1 return: no problem
+ */
+int
+PQconsumeInput(PGconn *conn)
+{
+ if (!conn)
+ return 0;
+
+ /*
+ * for non-blocking connections try to flush the send-queue, otherwise we
+ * may never get a response for something that may not have already been
+ * sent because it's in our write buffer!
+ */
+ if (pqIsnonblocking(conn))
+ {
+ if (pqFlush(conn) < 0)
+ return 0;
+ }
+
+ /*
+ * Load more data, if available. We do this no matter what state we are
+ * in, since we are probably getting called because the application wants
+ * to get rid of a read-select condition. Note that we will NOT block
+ * waiting for more input.
+ */
+ if (pqReadData(conn) < 0)
+ return 0;
+
+ /* Parsing of the data waits till later. */
+ return 1;
+}
+
+
+/*
+ * parseInput: if appropriate, parse input data from backend
+ * until input is exhausted or a stopping state is reached.
+ * Note that this function will NOT attempt to read more data from the backend.
+ */
+static void
+parseInput(PGconn *conn)
+{
+ pqParseInput3(conn);
+}
+
+/*
+ * PQisBusy
+ * Return true if PQgetResult would block waiting for input.
+ */
+
+int
+PQisBusy(PGconn *conn)
+{
+ if (!conn)
+ return false;
+
+ /* Parse any available data, if our state permits. */
+ parseInput(conn);
+
+ /*
+ * PQgetResult will return immediately in all states except BUSY. Also,
+ * if we've detected read EOF and dropped the connection, we can expect
+ * that PQgetResult will fail immediately. Note that we do *not* check
+ * conn->write_failed here --- once that's become set, we know we have
+ * trouble, but we need to keep trying to read until we have a complete
+ * server message or detect read EOF.
+ */
+ return conn->asyncStatus == PGASYNC_BUSY && conn->status != CONNECTION_BAD;
+}
+
+/*
+ * PQgetResult
+ * Get the next PGresult produced by a query. Returns NULL if no
+ * query work remains or an error has occurred (e.g. out of
+ * memory).
+ *
+ * In pipeline mode, once all the result of a query have been returned,
+ * PQgetResult returns NULL to let the user know that the next
+ * query is being processed. At the end of the pipeline, returns a
+ * result with PQresultStatus(result) == PGRES_PIPELINE_SYNC.
+ */
+PGresult *
+PQgetResult(PGconn *conn)
+{
+ PGresult *res;
+
+ if (!conn)
+ return NULL;
+
+ /* Parse any available data, if our state permits. */
+ parseInput(conn);
+
+ /* If not ready to return something, block until we are. */
+ while (conn->asyncStatus == PGASYNC_BUSY)
+ {
+ int flushResult;
+
+ /*
+ * If data remains unsent, send it. Else we might be waiting for the
+ * result of a command the backend hasn't even got yet.
+ */
+ while ((flushResult = pqFlush(conn)) > 0)
+ {
+ if (pqWait(false, true, conn))
+ {
+ flushResult = -1;
+ break;
+ }
+ }
+
+ /*
+ * Wait for some more data, and load it. (Note: if the connection has
+ * been lost, pqWait should return immediately because the socket
+ * should be read-ready, either with the last server data or with an
+ * EOF indication. We expect therefore that this won't result in any
+ * undue delay in reporting a previous write failure.)
+ */
+ if (flushResult ||
+ pqWait(true, false, conn) ||
+ pqReadData(conn) < 0)
+ {
+ /* Report the error saved by pqWait or pqReadData */
+ pqSaveErrorResult(conn);
+ conn->asyncStatus = PGASYNC_IDLE;
+ return pqPrepareAsyncResult(conn);
+ }
+
+ /* Parse it. */
+ parseInput(conn);
+
+ /*
+ * If we had a write error, but nothing above obtained a query result
+ * or detected a read error, report the write error.
+ */
+ if (conn->write_failed && conn->asyncStatus == PGASYNC_BUSY)
+ {
+ pqSaveWriteError(conn);
+ conn->asyncStatus = PGASYNC_IDLE;
+ return pqPrepareAsyncResult(conn);
+ }
+ }
+
+ /* Return the appropriate thing. */
+ switch (conn->asyncStatus)
+ {
+ case PGASYNC_IDLE:
+ res = NULL; /* query is complete */
+ break;
+ case PGASYNC_PIPELINE_IDLE:
+ Assert(conn->pipelineStatus != PQ_PIPELINE_OFF);
+
+ /*
+ * We're about to return the NULL that terminates the round of
+ * results from the current query; prepare to send the results of
+ * the next query, if any, when we're called next. If there's no
+ * next element in the command queue, this gets us in IDLE state.
+ */
+ pqPipelineProcessQueue(conn);
+ res = NULL; /* query is complete */
+ break;
+
+ case PGASYNC_READY:
+
+ /*
+ * For any query type other than simple query protocol, we advance
+ * the command queue here. This is because for simple query
+ * protocol we can get the READY state multiple times before the
+ * command is actually complete, since the command string can
+ * contain many queries. In simple query protocol, the queue
+ * advance is done by fe-protocol3 when it receives ReadyForQuery.
+ */
+ if (conn->cmd_queue_head &&
+ conn->cmd_queue_head->queryclass != PGQUERY_SIMPLE)
+ pqCommandQueueAdvance(conn);
+ res = pqPrepareAsyncResult(conn);
+ if (conn->pipelineStatus != PQ_PIPELINE_OFF)
+ {
+ /*
+ * We're about to send the results of the current query. Set
+ * us idle now, and ...
+ */
+ conn->asyncStatus = PGASYNC_PIPELINE_IDLE;
+
+ /*
+ * ... in cases when we're sending a pipeline-sync result,
+ * move queue processing forwards immediately, so that next
+ * time we're called, we're prepared to return the next result
+ * received from the server. In all other cases, leave the
+ * queue state change for next time, so that a terminating
+ * NULL result is sent.
+ *
+ * (In other words: we don't return a NULL after a pipeline
+ * sync.)
+ */
+ if (res && res->resultStatus == PGRES_PIPELINE_SYNC)
+ pqPipelineProcessQueue(conn);
+ }
+ else
+ {
+ /* Set the state back to BUSY, allowing parsing to proceed. */
+ conn->asyncStatus = PGASYNC_BUSY;
+ }
+ break;
+ case PGASYNC_READY_MORE:
+ res = pqPrepareAsyncResult(conn);
+ /* Set the state back to BUSY, allowing parsing to proceed. */
+ conn->asyncStatus = PGASYNC_BUSY;
+ break;
+ case PGASYNC_COPY_IN:
+ res = getCopyResult(conn, PGRES_COPY_IN);
+ break;
+ case PGASYNC_COPY_OUT:
+ res = getCopyResult(conn, PGRES_COPY_OUT);
+ break;
+ case PGASYNC_COPY_BOTH:
+ res = getCopyResult(conn, PGRES_COPY_BOTH);
+ break;
+ default:
+ libpq_append_conn_error(conn, "unexpected asyncStatus: %d", (int) conn->asyncStatus);
+ pqSaveErrorResult(conn);
+ conn->asyncStatus = PGASYNC_IDLE; /* try to restore valid state */
+ res = pqPrepareAsyncResult(conn);
+ break;
+ }
+
+ /* Time to fire PGEVT_RESULTCREATE events, if there are any */
+ if (res && res->nEvents > 0)
+ (void) PQfireResultCreateEvents(conn, res);
+
+ return res;
+}
+
+/*
+ * getCopyResult
+ * Helper for PQgetResult: generate result for COPY-in-progress cases
+ */
+static PGresult *
+getCopyResult(PGconn *conn, ExecStatusType copytype)
+{
+ /*
+ * If the server connection has been lost, don't pretend everything is
+ * hunky-dory; instead return a PGRES_FATAL_ERROR result, and reset the
+ * asyncStatus to idle (corresponding to what we'd do if we'd detected I/O
+ * error in the earlier steps in PQgetResult). The text returned in the
+ * result is whatever is in conn->errorMessage; we hope that was filled
+ * with something relevant when the lost connection was detected.
+ */
+ if (conn->status != CONNECTION_OK)
+ {
+ pqSaveErrorResult(conn);
+ conn->asyncStatus = PGASYNC_IDLE;
+ return pqPrepareAsyncResult(conn);
+ }
+
+ /* If we have an async result for the COPY, return that */
+ if (conn->result && conn->result->resultStatus == copytype)
+ return pqPrepareAsyncResult(conn);
+
+ /* Otherwise, invent a suitable PGresult */
+ return PQmakeEmptyPGresult(conn, copytype);
+}
+
+
+/*
+ * PQexec
+ * send a query to the backend and package up the result in a PGresult
+ *
+ * If the query was not even sent, return NULL; conn->errorMessage is set to
+ * a relevant message.
+ * If the query was sent, a new PGresult is returned (which could indicate
+ * either success or failure).
+ * The user is responsible for freeing the PGresult via PQclear()
+ * when done with it.
+ */
+PGresult *
+PQexec(PGconn *conn, const char *query)
+{
+ if (!PQexecStart(conn))
+ return NULL;
+ if (!PQsendQuery(conn, query))
+ return NULL;
+ return PQexecFinish(conn);
+}
+
+/*
+ * PQexecParams
+ * Like PQexec, but use extended query protocol so we can pass parameters
+ */
+PGresult *
+PQexecParams(PGconn *conn,
+ const char *command,
+ int nParams,
+ const Oid *paramTypes,
+ const char *const *paramValues,
+ const int *paramLengths,
+ const int *paramFormats,
+ int resultFormat)
+{
+ if (!PQexecStart(conn))
+ return NULL;
+ if (!PQsendQueryParams(conn, command,
+ nParams, paramTypes, paramValues, paramLengths,
+ paramFormats, resultFormat))
+ return NULL;
+ return PQexecFinish(conn);
+}
+
+/*
+ * PQprepare
+ * Creates a prepared statement by issuing a Parse message.
+ *
+ * If the query was not even sent, return NULL; conn->errorMessage is set to
+ * a relevant message.
+ * If the query was sent, a new PGresult is returned (which could indicate
+ * either success or failure).
+ * The user is responsible for freeing the PGresult via PQclear()
+ * when done with it.
+ */
+PGresult *
+PQprepare(PGconn *conn,
+ const char *stmtName, const char *query,
+ int nParams, const Oid *paramTypes)
+{
+ if (!PQexecStart(conn))
+ return NULL;
+ if (!PQsendPrepare(conn, stmtName, query, nParams, paramTypes))
+ return NULL;
+ return PQexecFinish(conn);
+}
+
+/*
+ * PQexecPrepared
+ * Like PQexec, but execute a previously prepared statement,
+ * using extended query protocol so we can pass parameters
+ */
+PGresult *
+PQexecPrepared(PGconn *conn,
+ const char *stmtName,
+ int nParams,
+ const char *const *paramValues,
+ const int *paramLengths,
+ const int *paramFormats,
+ int resultFormat)
+{
+ if (!PQexecStart(conn))
+ return NULL;
+ if (!PQsendQueryPrepared(conn, stmtName,
+ nParams, paramValues, paramLengths,
+ paramFormats, resultFormat))
+ return NULL;
+ return PQexecFinish(conn);
+}
+
+/*
+ * Common code for PQexec and sibling routines: prepare to send command
+ */
+static bool
+PQexecStart(PGconn *conn)
+{
+ PGresult *result;
+
+ if (!conn)
+ return false;
+
+ /*
+ * Since this is the beginning of a query cycle, reset the error state.
+ * However, in pipeline mode with something already queued, the error
+ * buffer belongs to that command and we shouldn't clear it.
+ */
+ if (conn->cmd_queue_head == NULL)
+ pqClearConnErrorState(conn);
+
+ if (conn->pipelineStatus != PQ_PIPELINE_OFF)
+ {
+ libpq_append_conn_error(conn, "synchronous command execution functions are not allowed in pipeline mode");
+ return false;
+ }
+
+ /*
+ * Silently discard any prior query result that application didn't eat.
+ * This is probably poor design, but it's here for backward compatibility.
+ */
+ while ((result = PQgetResult(conn)) != NULL)
+ {
+ ExecStatusType resultStatus = result->resultStatus;
+
+ PQclear(result); /* only need its status */
+ if (resultStatus == PGRES_COPY_IN)
+ {
+ /* get out of a COPY IN state */
+ if (PQputCopyEnd(conn,
+ libpq_gettext("COPY terminated by new PQexec")) < 0)
+ return false;
+ /* keep waiting to swallow the copy's failure message */
+ }
+ else if (resultStatus == PGRES_COPY_OUT)
+ {
+ /*
+ * Get out of a COPY OUT state: we just switch back to BUSY and
+ * allow the remaining COPY data to be dropped on the floor.
+ */
+ conn->asyncStatus = PGASYNC_BUSY;
+ /* keep waiting to swallow the copy's completion message */
+ }
+ else if (resultStatus == PGRES_COPY_BOTH)
+ {
+ /* We don't allow PQexec during COPY BOTH */
+ libpq_append_conn_error(conn, "PQexec not allowed during COPY BOTH");
+ return false;
+ }
+ /* check for loss of connection, too */
+ if (conn->status == CONNECTION_BAD)
+ return false;
+ }
+
+ /* OK to send a command */
+ return true;
+}
+
+/*
+ * Common code for PQexec and sibling routines: wait for command result
+ */
+static PGresult *
+PQexecFinish(PGconn *conn)
+{
+ PGresult *result;
+ PGresult *lastResult;
+
+ /*
+ * For backwards compatibility, return the last result if there are more
+ * than one. (We used to have logic here to concatenate successive error
+ * messages, but now that happens automatically, since conn->errorMessage
+ * will continue to accumulate errors throughout this loop.)
+ *
+ * We have to stop if we see copy in/out/both, however. We will resume
+ * parsing after application performs the data transfer.
+ *
+ * Also stop if the connection is lost (else we'll loop infinitely).
+ */
+ lastResult = NULL;
+ while ((result = PQgetResult(conn)) != NULL)
+ {
+ /* The CONNECTION_BAD status could have been triggered by a previous query error */
+ if (conn->status == CONNECTION_BAD && lastResult && lastResult->resultStatus == PGRES_FATAL_ERROR) {
+ PQclear(result);
+ break;
+ }
+ PQclear(lastResult);
+ lastResult = result;
+ if (result->resultStatus == PGRES_COPY_IN ||
+ result->resultStatus == PGRES_COPY_OUT ||
+ result->resultStatus == PGRES_COPY_BOTH ||
+ conn->status == CONNECTION_BAD)
+ break;
+ }
+
+ return lastResult;
+}
+
+/*
+ * PQdescribePrepared
+ * Obtain information about a previously prepared statement
+ *
+ * If the query was not even sent, return NULL; conn->errorMessage is set to
+ * a relevant message.
+ * If the query was sent, a new PGresult is returned (which could indicate
+ * either success or failure). On success, the PGresult contains status
+ * PGRES_COMMAND_OK, and its parameter and column-heading fields describe
+ * the statement's inputs and outputs respectively.
+ * The user is responsible for freeing the PGresult via PQclear()
+ * when done with it.
+ */
+PGresult *
+PQdescribePrepared(PGconn *conn, const char *stmt)
+{
+ if (!PQexecStart(conn))
+ return NULL;
+ if (!PQsendDescribe(conn, 'S', stmt))
+ return NULL;
+ return PQexecFinish(conn);
+}
+
+/*
+ * PQdescribePortal
+ * Obtain information about a previously created portal
+ *
+ * This is much like PQdescribePrepared, except that no parameter info is
+ * returned. Note that at the moment, libpq doesn't really expose portals
+ * to the client; but this can be used with a portal created by a SQL
+ * DECLARE CURSOR command.
+ */
+PGresult *
+PQdescribePortal(PGconn *conn, const char *portal)
+{
+ if (!PQexecStart(conn))
+ return NULL;
+ if (!PQsendDescribe(conn, 'P', portal))
+ return NULL;
+ return PQexecFinish(conn);
+}
+
+/*
+ * PQsendDescribePrepared
+ * Submit a Describe Statement command, but don't wait for it to finish
+ *
+ * Returns: 1 if successfully submitted
+ * 0 if error (conn->errorMessage is set)
+ */
+int
+PQsendDescribePrepared(PGconn *conn, const char *stmt)
+{
+ return PQsendDescribe(conn, 'S', stmt);
+}
+
+/*
+ * PQsendDescribePortal
+ * Submit a Describe Portal command, but don't wait for it to finish
+ *
+ * Returns: 1 if successfully submitted
+ * 0 if error (conn->errorMessage is set)
+ */
+int
+PQsendDescribePortal(PGconn *conn, const char *portal)
+{
+ return PQsendDescribe(conn, 'P', portal);
+}
+
+/*
+ * PQsendDescribe
+ * Common code to send a Describe command
+ *
+ * Available options for desc_type are
+ * 'S' to describe a prepared statement; or
+ * 'P' to describe a portal.
+ * Returns 1 on success and 0 on failure.
+ */
+static int
+PQsendDescribe(PGconn *conn, char desc_type, const char *desc_target)
+{
+ PGcmdQueueEntry *entry = NULL;
+
+ /* Treat null desc_target as empty string */
+ if (!desc_target)
+ desc_target = "";
+
+ if (!PQsendQueryStart(conn, true))
+ return 0;
+
+ entry = pqAllocCmdQueueEntry(conn);
+ if (entry == NULL)
+ return 0; /* error msg already set */
+
+ /* construct the Describe message */
+ if (pqPutMsgStart('D', conn) < 0 ||
+ pqPutc(desc_type, conn) < 0 ||
+ pqPuts(desc_target, conn) < 0 ||
+ pqPutMsgEnd(conn) < 0)
+ goto sendFailed;
+
+ /* construct the Sync message */
+ if (conn->pipelineStatus == PQ_PIPELINE_OFF)
+ {
+ if (pqPutMsgStart('S', conn) < 0 ||
+ pqPutMsgEnd(conn) < 0)
+ goto sendFailed;
+ }
+
+ /* remember we are doing a Describe */
+ entry->queryclass = PGQUERY_DESCRIBE;
+
+ /*
+ * Give the data a push (in pipeline mode, only if we're past the size
+ * threshold). In nonblock mode, don't complain if we're unable to send
+ * it all; PQgetResult() will do any additional flushing needed.
+ */
+ if (pqPipelineFlush(conn) < 0)
+ goto sendFailed;
+
+ /* OK, it's launched! */
+ pqAppendCmdQueueEntry(conn, entry);
+
+ return 1;
+
+sendFailed:
+ pqRecycleCmdQueueEntry(conn, entry);
+ /* error message should be set up already */
+ return 0;
+}
+
+/*
+ * PQnotifies
+ * returns a PGnotify* structure of the latest async notification
+ * that has not yet been handled
+ *
+ * returns NULL, if there is currently
+ * no unhandled async notification from the backend
+ *
+ * the CALLER is responsible for FREE'ing the structure returned
+ *
+ * Note that this function does not read any new data from the socket;
+ * so usually, caller should call PQconsumeInput() first.
+ */
+PGnotify *
+PQnotifies(PGconn *conn)
+{
+ PGnotify *event;
+
+ if (!conn)
+ return NULL;
+
+ /* Parse any available data to see if we can extract NOTIFY messages. */
+ parseInput(conn);
+
+ event = conn->notifyHead;
+ if (event)
+ {
+ conn->notifyHead = event->next;
+ if (!conn->notifyHead)
+ conn->notifyTail = NULL;
+ event->next = NULL; /* don't let app see the internal state */
+ }
+ return event;
+}
+
+/*
+ * PQputCopyData - send some data to the backend during COPY IN or COPY BOTH
+ *
+ * Returns 1 if successful, 0 if data could not be sent (only possible
+ * in nonblock mode), or -1 if an error occurs.
+ */
+int
+PQputCopyData(PGconn *conn, const char *buffer, int nbytes)
+{
+ if (!conn)
+ return -1;
+ if (conn->asyncStatus != PGASYNC_COPY_IN &&
+ conn->asyncStatus != PGASYNC_COPY_BOTH)
+ {
+ libpq_append_conn_error(conn, "no COPY in progress");
+ return -1;
+ }
+
+ /*
+ * Process any NOTICE or NOTIFY messages that might be pending in the
+ * input buffer. Since the server might generate many notices during the
+ * COPY, we want to clean those out reasonably promptly to prevent
+ * indefinite expansion of the input buffer. (Note: the actual read of
+ * input data into the input buffer happens down inside pqSendSome, but
+ * it's not authorized to get rid of the data again.)
+ */
+ parseInput(conn);
+
+ if (nbytes > 0)
+ {
+ /*
+ * Try to flush any previously sent data in preference to growing the
+ * output buffer. If we can't enlarge the buffer enough to hold the
+ * data, return 0 in the nonblock case, else hard error. (For
+ * simplicity, always assume 5 bytes of overhead.)
+ */
+ if ((conn->outBufSize - conn->outCount - 5) < nbytes)
+ {
+ if (pqFlush(conn) < 0)
+ return -1;
+ if (pqCheckOutBufferSpace(conn->outCount + 5 + (size_t) nbytes,
+ conn))
+ return pqIsnonblocking(conn) ? 0 : -1;
+ }
+ /* Send the data (too simple to delegate to fe-protocol files) */
+ if (pqPutMsgStart('d', conn) < 0 ||
+ pqPutnchar(buffer, nbytes, conn) < 0 ||
+ pqPutMsgEnd(conn) < 0)
+ return -1;
+ }
+ return 1;
+}
+
+/*
+ * PQputCopyEnd - send EOF indication to the backend during COPY IN
+ *
+ * After calling this, use PQgetResult() to check command completion status.
+ *
+ * Returns 1 if successful, 0 if data could not be sent (only possible
+ * in nonblock mode), or -1 if an error occurs.
+ */
+int
+PQputCopyEnd(PGconn *conn, const char *errormsg)
+{
+ if (!conn)
+ return -1;
+ if (conn->asyncStatus != PGASYNC_COPY_IN &&
+ conn->asyncStatus != PGASYNC_COPY_BOTH)
+ {
+ libpq_append_conn_error(conn, "no COPY in progress");
+ return -1;
+ }
+
+ /*
+ * Send the COPY END indicator. This is simple enough that we don't
+ * bother delegating it to the fe-protocol files.
+ */
+ if (errormsg)
+ {
+ /* Send COPY FAIL */
+ if (pqPutMsgStart('f', conn) < 0 ||
+ pqPuts(errormsg, conn) < 0 ||
+ pqPutMsgEnd(conn) < 0)
+ return -1;
+ }
+ else
+ {
+ /* Send COPY DONE */
+ if (pqPutMsgStart('c', conn) < 0 ||
+ pqPutMsgEnd(conn) < 0)
+ return -1;
+ }
+
+ /*
+ * If we sent the COPY command in extended-query mode, we must issue a
+ * Sync as well.
+ */
+ if (conn->cmd_queue_head &&
+ conn->cmd_queue_head->queryclass != PGQUERY_SIMPLE)
+ {
+ if (pqPutMsgStart('S', conn) < 0 ||
+ pqPutMsgEnd(conn) < 0)
+ return -1;
+ }
+
+ /* Return to active duty */
+ if (conn->asyncStatus == PGASYNC_COPY_BOTH)
+ conn->asyncStatus = PGASYNC_COPY_OUT;
+ else
+ conn->asyncStatus = PGASYNC_BUSY;
+
+ /* Try to flush data */
+ if (pqFlush(conn) < 0)
+ return -1;
+
+ return 1;
+}
+
+/*
+ * PQgetCopyData - read a row of data from the backend during COPY OUT
+ * or COPY BOTH
+ *
+ * If successful, sets *buffer to point to a malloc'd row of data, and
+ * returns row length (always > 0) as result.
+ * Returns 0 if no row available yet (only possible if async is true),
+ * -1 if end of copy (consult PQgetResult), or -2 if error (consult
+ * PQerrorMessage).
+ */
+int
+PQgetCopyData(PGconn *conn, char **buffer, int async)
+{
+ *buffer = NULL; /* for all failure cases */
+ if (!conn)
+ return -2;
+ if (conn->asyncStatus != PGASYNC_COPY_OUT &&
+ conn->asyncStatus != PGASYNC_COPY_BOTH)
+ {
+ libpq_append_conn_error(conn, "no COPY in progress");
+ return -2;
+ }
+ return pqGetCopyData3(conn, buffer, async);
+}
+
+/*
+ * PQgetline - gets a newline-terminated string from the backend.
+ *
+ * Chiefly here so that applications can use "COPY <rel> to stdout"
+ * and read the output string. Returns a null-terminated string in `buffer`.
+ *
+ * XXX this routine is now deprecated, because it can't handle binary data.
+ * If called during a COPY BINARY we return EOF.
+ *
+ * PQgetline reads up to `length`-1 characters (like fgets(3)) but strips
+ * the terminating \n (like gets(3)).
+ *
+ * CAUTION: the caller is responsible for detecting the end-of-copy signal
+ * (a line containing just "\.") when using this routine.
+ *
+ * RETURNS:
+ * EOF if error (eg, invalid arguments are given)
+ * 0 if EOL is reached (i.e., \n has been read)
+ * (this is required for backward-compatibility -- this
+ * routine used to always return EOF or 0, assuming that
+ * the line ended within `length` bytes.)
+ * 1 in other cases (i.e., the buffer was filled before \n is reached)
+ */
+int
+PQgetline(PGconn *conn, char *buffer, int length)
+{
+ if (!buffer || length <= 0)
+ return EOF;
+ *buffer = '\0';
+ /* length must be at least 3 to hold the \. terminator! */
+ if (length < 3)
+ return EOF;
+
+ if (!conn)
+ return EOF;
+
+ return pqGetline3(conn, buffer, length);
+}
+
+/*
+ * PQgetlineAsync - gets a COPY data row without blocking.
+ *
+ * This routine is for applications that want to do "COPY <rel> to stdout"
+ * asynchronously, that is without blocking. Having issued the COPY command
+ * and gotten a PGRES_COPY_OUT response, the app should call PQconsumeInput
+ * and this routine until the end-of-data signal is detected. Unlike
+ * PQgetline, this routine takes responsibility for detecting end-of-data.
+ *
+ * On each call, PQgetlineAsync will return data if a complete data row
+ * is available in libpq's input buffer. Otherwise, no data is returned
+ * until the rest of the row arrives.
+ *
+ * If -1 is returned, the end-of-data signal has been recognized (and removed
+ * from libpq's input buffer). The caller *must* next call PQendcopy and
+ * then return to normal processing.
+ *
+ * RETURNS:
+ * -1 if the end-of-copy-data marker has been recognized
+ * 0 if no data is available
+ * >0 the number of bytes returned.
+ *
+ * The data returned will not extend beyond a data-row boundary. If possible
+ * a whole row will be returned at one time. But if the buffer offered by
+ * the caller is too small to hold a row sent by the backend, then a partial
+ * data row will be returned. In text mode this can be detected by testing
+ * whether the last returned byte is '\n' or not.
+ *
+ * The returned data is *not* null-terminated.
+ */
+
+int
+PQgetlineAsync(PGconn *conn, char *buffer, int bufsize)
+{
+ if (!conn)
+ return -1;
+
+ return pqGetlineAsync3(conn, buffer, bufsize);
+}
+
+/*
+ * PQputline -- sends a string to the backend during COPY IN.
+ * Returns 0 if OK, EOF if not.
+ *
+ * This is deprecated primarily because the return convention doesn't allow
+ * caller to tell the difference between a hard error and a nonblock-mode
+ * send failure.
+ */
+int
+PQputline(PGconn *conn, const char *string)
+{
+ return PQputnbytes(conn, string, strlen(string));
+}
+
+/*
+ * PQputnbytes -- like PQputline, but buffer need not be null-terminated.
+ * Returns 0 if OK, EOF if not.
+ */
+int
+PQputnbytes(PGconn *conn, const char *buffer, int nbytes)
+{
+ if (PQputCopyData(conn, buffer, nbytes) > 0)
+ return 0;
+ else
+ return EOF;
+}
+
+/*
+ * PQendcopy
+ * After completing the data transfer portion of a copy in/out,
+ * the application must call this routine to finish the command protocol.
+ *
+ * This is deprecated; it's cleaner to use PQgetResult to get the transfer
+ * status.
+ *
+ * RETURNS:
+ * 0 on success
+ * 1 on failure
+ */
+int
+PQendcopy(PGconn *conn)
+{
+ if (!conn)
+ return 0;
+
+ return pqEndcopy3(conn);
+}
+
+
+/* ----------------
+ * PQfn - Send a function call to the POSTGRES backend.
+ *
+ * conn : backend connection
+ * fnid : OID of function to be called
+ * result_buf : pointer to result buffer
+ * result_len : actual length of result is returned here
+ * result_is_int : If the result is an integer, this must be 1,
+ * otherwise this should be 0
+ * args : pointer to an array of function arguments
+ * (each has length, if integer, and value/pointer)
+ * nargs : # of arguments in args array.
+ *
+ * RETURNS
+ * PGresult with status = PGRES_COMMAND_OK if successful.
+ * *result_len is > 0 if there is a return value, 0 if not.
+ * PGresult with status = PGRES_FATAL_ERROR if backend returns an error.
+ * NULL on communications failure. conn->errorMessage will be set.
+ * ----------------
+ */
+
+PGresult *
+PQfn(PGconn *conn,
+ int fnid,
+ int *result_buf,
+ int *result_len,
+ int result_is_int,
+ const PQArgBlock *args,
+ int nargs)
+{
+ *result_len = 0;
+
+ if (!conn)
+ return NULL;
+
+ /*
+ * Since this is the beginning of a query cycle, reset the error state.
+ * However, in pipeline mode with something already queued, the error
+ * buffer belongs to that command and we shouldn't clear it.
+ */
+ if (conn->cmd_queue_head == NULL)
+ pqClearConnErrorState(conn);
+
+ if (conn->pipelineStatus != PQ_PIPELINE_OFF)
+ {
+ libpq_append_conn_error(conn, "%s not allowed in pipeline mode", "PQfn");
+ return NULL;
+ }
+
+ if (conn->sock == PGINVALID_SOCKET || conn->asyncStatus != PGASYNC_IDLE ||
+ pgHavePendingResult(conn))
+ {
+ libpq_append_conn_error(conn, "connection in wrong state");
+ return NULL;
+ }
+
+ return pqFunctionCall3(conn, fnid,
+ result_buf, result_len,
+ result_is_int,
+ args, nargs);
+}
+
+/* ====== Pipeline mode support ======== */
+
+/*
+ * PQenterPipelineMode
+ * Put an idle connection in pipeline mode.
+ *
+ * Returns 1 on success. On failure, errorMessage is set and 0 is returned.
+ *
+ * Commands submitted after this can be pipelined on the connection;
+ * there's no requirement to wait for one to finish before the next is
+ * dispatched.
+ *
+ * Queuing of a new query or syncing during COPY is not allowed.
+ *
+ * A set of commands is terminated by a PQpipelineSync. Multiple sync
+ * points can be established while in pipeline mode. Pipeline mode can
+ * be exited by calling PQexitPipelineMode() once all results are processed.
+ *
+ * This doesn't actually send anything on the wire, it just puts libpq
+ * into a state where it can pipeline work.
+ */
+int
+PQenterPipelineMode(PGconn *conn)
+{
+ if (!conn)
+ return 0;
+
+ /* succeed with no action if already in pipeline mode */
+ if (conn->pipelineStatus != PQ_PIPELINE_OFF)
+ return 1;
+
+ if (conn->asyncStatus != PGASYNC_IDLE)
+ {
+ libpq_append_conn_error(conn, "cannot enter pipeline mode, connection not idle");
+ return 0;
+ }
+
+ conn->pipelineStatus = PQ_PIPELINE_ON;
+
+ return 1;
+}
+
+/*
+ * PQexitPipelineMode
+ * End pipeline mode and return to normal command mode.
+ *
+ * Returns 1 in success (pipeline mode successfully ended, or not in pipeline
+ * mode).
+ *
+ * Returns 0 if in pipeline mode and cannot be ended yet. Error message will
+ * be set.
+ */
+int
+PQexitPipelineMode(PGconn *conn)
+{
+ if (!conn)
+ return 0;
+
+ if (conn->pipelineStatus == PQ_PIPELINE_OFF &&
+ (conn->asyncStatus == PGASYNC_IDLE ||
+ conn->asyncStatus == PGASYNC_PIPELINE_IDLE) &&
+ conn->cmd_queue_head == NULL)
+ return 1;
+
+ switch (conn->asyncStatus)
+ {
+ case PGASYNC_READY:
+ case PGASYNC_READY_MORE:
+ /* there are some uncollected results */
+ libpq_append_conn_error(conn, "cannot exit pipeline mode with uncollected results");
+ return 0;
+
+ case PGASYNC_BUSY:
+ libpq_append_conn_error(conn, "cannot exit pipeline mode while busy");
+ return 0;
+
+ case PGASYNC_IDLE:
+ case PGASYNC_PIPELINE_IDLE:
+ /* OK */
+ break;
+
+ case PGASYNC_COPY_IN:
+ case PGASYNC_COPY_OUT:
+ case PGASYNC_COPY_BOTH:
+ libpq_append_conn_error(conn, "cannot exit pipeline mode while in COPY");
+ }
+
+ /* still work to process */
+ if (conn->cmd_queue_head != NULL)
+ {
+ libpq_append_conn_error(conn, "cannot exit pipeline mode with uncollected results");
+ return 0;
+ }
+
+ conn->pipelineStatus = PQ_PIPELINE_OFF;
+ conn->asyncStatus = PGASYNC_IDLE;
+
+ /* Flush any pending data in out buffer */
+ if (pqFlush(conn) < 0)
+ return 0; /* error message is setup already */
+ return 1;
+}
+
+/*
+ * pqCommandQueueAdvance
+ * Remove one query from the command queue, when we receive
+ * all results from the server that pertain to it.
+ */
+void
+pqCommandQueueAdvance(PGconn *conn)
+{
+ PGcmdQueueEntry *prevquery;
+
+ if (conn->cmd_queue_head == NULL)
+ return;
+
+ /* delink from queue */
+ prevquery = conn->cmd_queue_head;
+ conn->cmd_queue_head = conn->cmd_queue_head->next;
+
+ /* If the queue is now empty, reset the tail too */
+ if (conn->cmd_queue_head == NULL)
+ conn->cmd_queue_tail = NULL;
+
+ /* and make it recyclable */
+ prevquery->next = NULL;
+ pqRecycleCmdQueueEntry(conn, prevquery);
+}
+
+/*
+ * pqPipelineProcessQueue: subroutine for PQgetResult
+ * In pipeline mode, start processing the results of the next query in the queue.
+ */
+static void
+pqPipelineProcessQueue(PGconn *conn)
+{
+ switch (conn->asyncStatus)
+ {
+ case PGASYNC_COPY_IN:
+ case PGASYNC_COPY_OUT:
+ case PGASYNC_COPY_BOTH:
+ case PGASYNC_READY:
+ case PGASYNC_READY_MORE:
+ case PGASYNC_BUSY:
+ /* client still has to process current query or results */
+ return;
+
+ case PGASYNC_IDLE:
+
+ /*
+ * If we're in IDLE mode and there's some command in the queue,
+ * get us into PIPELINE_IDLE mode and process normally. Otherwise
+ * there's nothing for us to do.
+ */
+ if (conn->cmd_queue_head != NULL)
+ {
+ conn->asyncStatus = PGASYNC_PIPELINE_IDLE;
+ break;
+ }
+ return;
+
+ case PGASYNC_PIPELINE_IDLE:
+ Assert(conn->pipelineStatus != PQ_PIPELINE_OFF);
+ /* next query please */
+ break;
+ }
+
+ /*
+ * Reset single-row processing mode. (Client has to set it up for each
+ * query, if desired.)
+ */
+ conn->singleRowMode = false;
+
+ /*
+ * If there are no further commands to process in the queue, get us in
+ * "real idle" mode now.
+ */
+ if (conn->cmd_queue_head == NULL)
+ {
+ conn->asyncStatus = PGASYNC_IDLE;
+ return;
+ }
+
+ /*
+ * Reset the error state. This and the next couple of steps correspond to
+ * what PQsendQueryStart didn't do for this query.
+ */
+ pqClearConnErrorState(conn);
+
+ /* Initialize async result-accumulation state */
+ pqClearAsyncResult(conn);
+
+ if (conn->pipelineStatus == PQ_PIPELINE_ABORTED &&
+ conn->cmd_queue_head->queryclass != PGQUERY_SYNC)
+ {
+ /*
+ * In an aborted pipeline we don't get anything from the server for
+ * each result; we're just discarding commands from the queue until we
+ * get to the next sync from the server.
+ *
+ * The PGRES_PIPELINE_ABORTED results tell the client that its queries
+ * got aborted.
+ */
+ conn->result = PQmakeEmptyPGresult(conn, PGRES_PIPELINE_ABORTED);
+ if (!conn->result)
+ {
+ libpq_append_conn_error(conn, "out of memory");
+ pqSaveErrorResult(conn);
+ return;
+ }
+ conn->asyncStatus = PGASYNC_READY;
+ }
+ else
+ {
+ /* allow parsing to continue */
+ conn->asyncStatus = PGASYNC_BUSY;
+ }
+}
+
+/*
+ * PQpipelineSync
+ * Send a Sync message as part of a pipeline, and flush to server
+ *
+ * It's legal to start submitting more commands in the pipeline immediately,
+ * without waiting for the results of the current pipeline. There's no need to
+ * end pipeline mode and start it again.
+ *
+ * If a command in a pipeline fails, every subsequent command up to and including
+ * the result to the Sync message sent by PQpipelineSync gets set to
+ * PGRES_PIPELINE_ABORTED state. If the whole pipeline is processed without
+ * error, a PGresult with PGRES_PIPELINE_SYNC is produced.
+ *
+ * Queries can already have been sent before PQpipelineSync is called, but
+ * PQpipelineSync need to be called before retrieving command results.
+ *
+ * The connection will remain in pipeline mode and unavailable for new
+ * synchronous command execution functions until all results from the pipeline
+ * are processed by the client.
+ */
+int
+PQpipelineSync(PGconn *conn)
+{
+ PGcmdQueueEntry *entry;
+
+ if (!conn)
+ return 0;
+
+ if (conn->pipelineStatus == PQ_PIPELINE_OFF)
+ {
+ libpq_append_conn_error(conn, "cannot send pipeline when not in pipeline mode");
+ return 0;
+ }
+
+ switch (conn->asyncStatus)
+ {
+ case PGASYNC_COPY_IN:
+ case PGASYNC_COPY_OUT:
+ case PGASYNC_COPY_BOTH:
+ /* should be unreachable */
+ appendPQExpBufferStr(&conn->errorMessage,
+ "internal error: cannot send pipeline while in COPY\n");
+ return 0;
+ case PGASYNC_READY:
+ case PGASYNC_READY_MORE:
+ case PGASYNC_BUSY:
+ case PGASYNC_IDLE:
+ case PGASYNC_PIPELINE_IDLE:
+ /* OK to send sync */
+ break;
+ }
+
+ entry = pqAllocCmdQueueEntry(conn);
+ if (entry == NULL)
+ return 0; /* error msg already set */
+
+ entry->queryclass = PGQUERY_SYNC;
+ entry->query = NULL;
+
+ /* construct the Sync message */
+ if (pqPutMsgStart('S', conn) < 0 ||
+ pqPutMsgEnd(conn) < 0)
+ goto sendFailed;
+
+ /*
+ * Give the data a push. In nonblock mode, don't complain if we're unable
+ * to send it all; PQgetResult() will do any additional flushing needed.
+ */
+ if (PQflush(conn) < 0)
+ goto sendFailed;
+
+ /* OK, it's launched! */
+ pqAppendCmdQueueEntry(conn, entry);
+
+ return 1;
+
+sendFailed:
+ pqRecycleCmdQueueEntry(conn, entry);
+ /* error message should be set up already */
+ return 0;
+}
+
+/*
+ * PQsendFlushRequest
+ * Send request for server to flush its buffer. Useful in pipeline
+ * mode when a sync point is not desired.
+ */
+int
+PQsendFlushRequest(PGconn *conn)
+{
+ if (!conn)
+ return 0;
+
+ /* Don't try to send if we know there's no live connection. */
+ if (conn->status != CONNECTION_OK)
+ {
+ libpq_append_conn_error(conn, "no connection to the server");
+ return 0;
+ }
+
+ /* Can't send while already busy, either, unless enqueuing for later */
+ if (conn->asyncStatus != PGASYNC_IDLE &&
+ conn->pipelineStatus == PQ_PIPELINE_OFF)
+ {
+ libpq_append_conn_error(conn, "another command is already in progress");
+ return 0;
+ }
+
+ if (pqPutMsgStart('H', conn) < 0 ||
+ pqPutMsgEnd(conn) < 0)
+ {
+ return 0;
+ }
+
+ return 1;
+}
+
+/* ====== accessor funcs for PGresult ======== */
+
+ExecStatusType
+PQresultStatus(const PGresult *res)
+{
+ if (!res)
+ return PGRES_FATAL_ERROR;
+ return res->resultStatus;
+}
+
+char *
+PQresStatus(ExecStatusType status)
+{
+ if ((unsigned int) status >= lengthof(pgresStatus))
+ return libpq_gettext("invalid ExecStatusType code");
+ return pgresStatus[status];
+}
+
+char *
+PQresultErrorMessage(const PGresult *res)
+{
+ if (!res || !res->errMsg)
+ return "";
+ return res->errMsg;
+}
+
+char *
+PQresultVerboseErrorMessage(const PGresult *res,
+ PGVerbosity verbosity,
+ PGContextVisibility show_context)
+{
+ PQExpBufferData workBuf;
+
+ /*
+ * Because the caller is expected to free the result string, we must
+ * strdup any constant result. We use plain strdup and document that
+ * callers should expect NULL if out-of-memory.
+ */
+ if (!res ||
+ (res->resultStatus != PGRES_FATAL_ERROR &&
+ res->resultStatus != PGRES_NONFATAL_ERROR))
+ return strdup(libpq_gettext("PGresult is not an error result\n"));
+
+ initPQExpBuffer(&workBuf);
+
+ pqBuildErrorMessage3(&workBuf, res, verbosity, show_context);
+
+ /* If insufficient memory to format the message, fail cleanly */
+ if (PQExpBufferDataBroken(workBuf))
+ {
+ termPQExpBuffer(&workBuf);
+ return strdup(libpq_gettext("out of memory\n"));
+ }
+
+ return workBuf.data;
+}
+
+char *
+PQresultErrorField(const PGresult *res, int fieldcode)
+{
+ PGMessageField *pfield;
+
+ if (!res)
+ return NULL;
+ for (pfield = res->errFields; pfield != NULL; pfield = pfield->next)
+ {
+ if (pfield->code == fieldcode)
+ return pfield->contents;
+ }
+ return NULL;
+}
+
+int
+PQntuples(const PGresult *res)
+{
+ if (!res)
+ return 0;
+ return res->ntups;
+}
+
+int
+PQnfields(const PGresult *res)
+{
+ if (!res)
+ return 0;
+ return res->numAttributes;
+}
+
+int
+PQbinaryTuples(const PGresult *res)
+{
+ if (!res)
+ return 0;
+ return res->binary;
+}
+
+/*
+ * Helper routines to range-check field numbers and tuple numbers.
+ * Return true if OK, false if not
+ */
+
+static int
+check_field_number(const PGresult *res, int field_num)
+{
+ if (!res)
+ return false; /* no way to display error message... */
+ if (field_num < 0 || field_num >= res->numAttributes)
+ {
+ pqInternalNotice(&res->noticeHooks,
+ "column number %d is out of range 0..%d",
+ field_num, res->numAttributes - 1);
+ return false;
+ }
+ return true;
+}
+
+static int
+check_tuple_field_number(const PGresult *res,
+ int tup_num, int field_num)
+{
+ if (!res)
+ return false; /* no way to display error message... */
+ if (tup_num < 0 || tup_num >= res->ntups)
+ {
+ pqInternalNotice(&res->noticeHooks,
+ "row number %d is out of range 0..%d",
+ tup_num, res->ntups - 1);
+ return false;
+ }
+ if (field_num < 0 || field_num >= res->numAttributes)
+ {
+ pqInternalNotice(&res->noticeHooks,
+ "column number %d is out of range 0..%d",
+ field_num, res->numAttributes - 1);
+ return false;
+ }
+ return true;
+}
+
+static int
+check_param_number(const PGresult *res, int param_num)
+{
+ if (!res)
+ return false; /* no way to display error message... */
+ if (param_num < 0 || param_num >= res->numParameters)
+ {
+ pqInternalNotice(&res->noticeHooks,
+ "parameter number %d is out of range 0..%d",
+ param_num, res->numParameters - 1);
+ return false;
+ }
+
+ return true;
+}
+
+/*
+ * returns NULL if the field_num is invalid
+ */
+char *
+PQfname(const PGresult *res, int field_num)
+{
+ if (!check_field_number(res, field_num))
+ return NULL;
+ if (res->attDescs)
+ return res->attDescs[field_num].name;
+ else
+ return NULL;
+}
+
+/*
+ * PQfnumber: find column number given column name
+ *
+ * The column name is parsed as if it were in a SQL statement, including
+ * case-folding and double-quote processing. But note a possible gotcha:
+ * downcasing in the frontend might follow different locale rules than
+ * downcasing in the backend...
+ *
+ * Returns -1 if no match. In the present backend it is also possible
+ * to have multiple matches, in which case the first one is found.
+ */
+int
+PQfnumber(const PGresult *res, const char *field_name)
+{
+ char *field_case;
+ bool in_quotes;
+ bool all_lower = true;
+ const char *iptr;
+ char *optr;
+ int i;
+
+ if (!res)
+ return -1;
+
+ /*
+ * Note: it is correct to reject a zero-length input string; the proper
+ * input to match a zero-length field name would be "".
+ */
+ if (field_name == NULL ||
+ field_name[0] == '\0' ||
+ res->attDescs == NULL)
+ return -1;
+
+ /*
+ * Check if we can avoid the strdup() and related work because the
+ * passed-in string wouldn't be changed before we do the check anyway.
+ */
+ for (iptr = field_name; *iptr; iptr++)
+ {
+ char c = *iptr;
+
+ if (c == '"' || c != pg_tolower((unsigned char) c))
+ {
+ all_lower = false;
+ break;
+ }
+ }
+
+ if (all_lower)
+ for (i = 0; i < res->numAttributes; i++)
+ if (strcmp(field_name, res->attDescs[i].name) == 0)
+ return i;
+
+ /* Fall through to the normal check if that didn't work out. */
+
+ /*
+ * Note: this code will not reject partially quoted strings, eg
+ * foo"BAR"foo will become fooBARfoo when it probably ought to be an error
+ * condition.
+ */
+ field_case = strdup(field_name);
+ if (field_case == NULL)
+ return -1; /* grotty */
+
+ in_quotes = false;
+ optr = field_case;
+ for (iptr = field_case; *iptr; iptr++)
+ {
+ char c = *iptr;
+
+ if (in_quotes)
+ {
+ if (c == '"')
+ {
+ if (iptr[1] == '"')
+ {
+ /* doubled quotes become a single quote */
+ *optr++ = '"';
+ iptr++;
+ }
+ else
+ in_quotes = false;
+ }
+ else
+ *optr++ = c;
+ }
+ else if (c == '"')
+ in_quotes = true;
+ else
+ {
+ c = pg_tolower((unsigned char) c);
+ *optr++ = c;
+ }
+ }
+ *optr = '\0';
+
+ for (i = 0; i < res->numAttributes; i++)
+ {
+ if (strcmp(field_case, res->attDescs[i].name) == 0)
+ {
+ free(field_case);
+ return i;
+ }
+ }
+ free(field_case);
+ return -1;
+}
+
+Oid
+PQftable(const PGresult *res, int field_num)
+{
+ if (!check_field_number(res, field_num))
+ return InvalidOid;
+ if (res->attDescs)
+ return res->attDescs[field_num].tableid;
+ else
+ return InvalidOid;
+}
+
+int
+PQftablecol(const PGresult *res, int field_num)
+{
+ if (!check_field_number(res, field_num))
+ return 0;
+ if (res->attDescs)
+ return res->attDescs[field_num].columnid;
+ else
+ return 0;
+}
+
+int
+PQfformat(const PGresult *res, int field_num)
+{
+ if (!check_field_number(res, field_num))
+ return 0;
+ if (res->attDescs)
+ return res->attDescs[field_num].format;
+ else
+ return 0;
+}
+
+Oid
+PQftype(const PGresult *res, int field_num)
+{
+ if (!check_field_number(res, field_num))
+ return InvalidOid;
+ if (res->attDescs)
+ return res->attDescs[field_num].typid;
+ else
+ return InvalidOid;
+}
+
+int
+PQfsize(const PGresult *res, int field_num)
+{
+ if (!check_field_number(res, field_num))
+ return 0;
+ if (res->attDescs)
+ return res->attDescs[field_num].typlen;
+ else
+ return 0;
+}
+
+int
+PQfmod(const PGresult *res, int field_num)
+{
+ if (!check_field_number(res, field_num))
+ return 0;
+ if (res->attDescs)
+ return res->attDescs[field_num].atttypmod;
+ else
+ return 0;
+}
+
+char *
+PQcmdStatus(PGresult *res)
+{
+ if (!res)
+ return NULL;
+ return res->cmdStatus;
+}
+
+/*
+ * PQoidStatus -
+ * if the last command was an INSERT, return the oid string
+ * if not, return ""
+ */
+char *
+PQoidStatus(const PGresult *res)
+{
+ /*
+ * This must be enough to hold the result. Don't laugh, this is better
+ * than what this function used to do.
+ */
+ static char buf[24];
+
+ size_t len;
+
+ if (!res || strncmp(res->cmdStatus, "INSERT ", 7) != 0)
+ return "";
+
+ len = strspn(res->cmdStatus + 7, "0123456789");
+ if (len > sizeof(buf) - 1)
+ len = sizeof(buf) - 1;
+ memcpy(buf, res->cmdStatus + 7, len);
+ buf[len] = '\0';
+
+ return buf;
+}
+
+/*
+ * PQoidValue -
+ * a perhaps preferable form of the above which just returns
+ * an Oid type
+ */
+Oid
+PQoidValue(const PGresult *res)
+{
+ char *endptr = NULL;
+ unsigned long result;
+
+ if (!res ||
+ strncmp(res->cmdStatus, "INSERT ", 7) != 0 ||
+ res->cmdStatus[7] < '0' ||
+ res->cmdStatus[7] > '9')
+ return InvalidOid;
+
+ result = strtoul(res->cmdStatus + 7, &endptr, 10);
+
+ if (!endptr || (*endptr != ' ' && *endptr != '\0'))
+ return InvalidOid;
+ else
+ return (Oid) result;
+}
+
+
+/*
+ * PQcmdTuples -
+ * If the last command was INSERT/UPDATE/DELETE/MERGE/MOVE/FETCH/COPY,
+ * return a string containing the number of inserted/affected tuples.
+ * If not, return "".
+ *
+ * XXX: this should probably return an int
+ */
+char *
+PQcmdTuples(PGresult *res)
+{
+ char *p,
+ *c;
+
+ if (!res)
+ return "";
+
+ if (strncmp(res->cmdStatus, "INSERT ", 7) == 0)
+ {
+ p = res->cmdStatus + 7;
+ /* INSERT: skip oid and space */
+ while (*p && *p != ' ')
+ p++;
+ if (*p == 0)
+ goto interpret_error; /* no space? */
+ p++;
+ }
+ else if (strncmp(res->cmdStatus, "SELECT ", 7) == 0 ||
+ strncmp(res->cmdStatus, "DELETE ", 7) == 0 ||
+ strncmp(res->cmdStatus, "UPDATE ", 7) == 0)
+ p = res->cmdStatus + 7;
+ else if (strncmp(res->cmdStatus, "FETCH ", 6) == 0 ||
+ strncmp(res->cmdStatus, "MERGE ", 6) == 0)
+ p = res->cmdStatus + 6;
+ else if (strncmp(res->cmdStatus, "MOVE ", 5) == 0 ||
+ strncmp(res->cmdStatus, "COPY ", 5) == 0)
+ p = res->cmdStatus + 5;
+ else
+ return "";
+
+ /* check that we have an integer (at least one digit, nothing else) */
+ for (c = p; *c; c++)
+ {
+ if (!isdigit((unsigned char) *c))
+ goto interpret_error;
+ }
+ if (c == p)
+ goto interpret_error;
+
+ return p;
+
+interpret_error:
+ pqInternalNotice(&res->noticeHooks,
+ "could not interpret result from server: %s",
+ res->cmdStatus);
+ return "";
+}
+
+/*
+ * PQgetvalue:
+ * return the value of field 'field_num' of row 'tup_num'
+ */
+char *
+PQgetvalue(const PGresult *res, int tup_num, int field_num)
+{
+ if (!check_tuple_field_number(res, tup_num, field_num))
+ return NULL;
+ return res->tuples[tup_num][field_num].value;
+}
+
+/* PQgetlength:
+ * returns the actual length of a field value in bytes.
+ */
+int
+PQgetlength(const PGresult *res, int tup_num, int field_num)
+{
+ if (!check_tuple_field_number(res, tup_num, field_num))
+ return 0;
+ if (res->tuples[tup_num][field_num].len != NULL_LEN)
+ return res->tuples[tup_num][field_num].len;
+ else
+ return 0;
+}
+
+/* PQgetisnull:
+ * returns the null status of a field value.
+ */
+int
+PQgetisnull(const PGresult *res, int tup_num, int field_num)
+{
+ if (!check_tuple_field_number(res, tup_num, field_num))
+ return 1; /* pretend it is null */
+ if (res->tuples[tup_num][field_num].len == NULL_LEN)
+ return 1;
+ else
+ return 0;
+}
+
+/* PQnparams:
+ * returns the number of input parameters of a prepared statement.
+ */
+int
+PQnparams(const PGresult *res)
+{
+ if (!res)
+ return 0;
+ return res->numParameters;
+}
+
+/* PQparamtype:
+ * returns type Oid of the specified statement parameter.
+ */
+Oid
+PQparamtype(const PGresult *res, int param_num)
+{
+ if (!check_param_number(res, param_num))
+ return InvalidOid;
+ if (res->paramDescs)
+ return res->paramDescs[param_num].typid;
+ else
+ return InvalidOid;
+}
+
+
+/* PQsetnonblocking:
+ * sets the PGconn's database connection non-blocking if the arg is true
+ * or makes it blocking if the arg is false, this will not protect
+ * you from PQexec(), you'll only be safe when using the non-blocking API.
+ * Needs to be called only on a connected database connection.
+ */
+int
+PQsetnonblocking(PGconn *conn, int arg)
+{
+ bool barg;
+
+ if (!conn || conn->status == CONNECTION_BAD)
+ return -1;
+
+ barg = (arg ? true : false);
+
+ /* early out if the socket is already in the state requested */
+ if (barg == conn->nonblocking)
+ return 0;
+
+ /*
+ * to guarantee constancy for flushing/query/result-polling behavior we
+ * need to flush the send queue at this point in order to guarantee proper
+ * behavior. this is ok because either they are making a transition _from_
+ * or _to_ blocking mode, either way we can block them.
+ *
+ * Clear error state in case pqFlush adds to it, unless we're actively
+ * pipelining, in which case it seems best not to.
+ */
+ if (conn->cmd_queue_head == NULL)
+ pqClearConnErrorState(conn);
+
+ /* if we are going from blocking to non-blocking flush here */
+ if (pqFlush(conn))
+ return -1;
+
+ conn->nonblocking = barg;
+
+ return 0;
+}
+
+/*
+ * return the blocking status of the database connection
+ * true == nonblocking, false == blocking
+ */
+int
+PQisnonblocking(const PGconn *conn)
+{
+ if (!conn || conn->status == CONNECTION_BAD)
+ return false;
+ return pqIsnonblocking(conn);
+}
+
+/* libpq is thread-safe? */
+int
+PQisthreadsafe(void)
+{
+#ifdef ENABLE_THREAD_SAFETY
+ return true;
+#else
+ return false;
+#endif
+}
+
+
+/* try to force data out, really only useful for non-blocking users */
+int
+PQflush(PGconn *conn)
+{
+ if (!conn || conn->status == CONNECTION_BAD)
+ return -1;
+ return pqFlush(conn);
+}
+
+/*
+ * pqPipelineFlush
+ *
+ * In pipeline mode, data will be flushed only when the out buffer reaches the
+ * threshold value. In non-pipeline mode, it behaves as stock pqFlush.
+ *
+ * Returns 0 on success.
+ */
+static int
+pqPipelineFlush(PGconn *conn)
+{
+ if ((conn->pipelineStatus != PQ_PIPELINE_ON) ||
+ (conn->outCount >= OUTBUFFER_THRESHOLD))
+ return pqFlush(conn);
+ return 0;
+}
+
+
+/*
+ * PQfreemem - safely frees memory allocated
+ *
+ * Needed mostly by Win32, unless multithreaded DLL (/MD in VC6)
+ * Used for freeing memory from PQescapeBytea()/PQunescapeBytea()
+ */
+void
+PQfreemem(void *ptr)
+{
+ free(ptr);
+}
+
+/*
+ * PQfreeNotify - free's the memory associated with a PGnotify
+ *
+ * This function is here only for binary backward compatibility.
+ * New code should use PQfreemem(). A macro will automatically map
+ * calls to PQfreemem. It should be removed in the future. bjm 2003-03-24
+ */
+
+#undef PQfreeNotify
+void PQfreeNotify(PGnotify *notify);
+
+void
+PQfreeNotify(PGnotify *notify)
+{
+ PQfreemem(notify);
+}
+
+
+/*
+ * Escaping arbitrary strings to get valid SQL literal strings.
+ *
+ * Replaces "'" with "''", and if not std_strings, replaces "\" with "\\".
+ *
+ * length is the length of the source string. (Note: if a terminating NUL
+ * is encountered sooner, PQescapeString stops short of "length"; the behavior
+ * is thus rather like strncpy.)
+ *
+ * For safety the buffer at "to" must be at least 2*length + 1 bytes long.
+ * A terminating NUL character is added to the output string, whether the
+ * input is NUL-terminated or not.
+ *
+ * Returns the actual length of the output (not counting the terminating NUL).
+ */
+static size_t
+PQescapeStringInternal(PGconn *conn,
+ char *to, const char *from, size_t length,
+ int *error,
+ int encoding, bool std_strings)
+{
+ const char *source = from;
+ char *target = to;
+ size_t remaining = length;
+
+ if (error)
+ *error = 0;
+
+ while (remaining > 0 && *source != '\0')
+ {
+ char c = *source;
+ int len;
+ int i;
+
+ /* Fast path for plain ASCII */
+ if (!IS_HIGHBIT_SET(c))
+ {
+ /* Apply quoting if needed */
+ if (SQL_STR_DOUBLE(c, !std_strings))
+ *target++ = c;
+ /* Copy the character */
+ *target++ = c;
+ source++;
+ remaining--;
+ continue;
+ }
+
+ /* Slow path for possible multibyte characters */
+ len = pg_encoding_mblen(encoding, source);
+
+ /* Copy the character */
+ for (i = 0; i < len; i++)
+ {
+ if (remaining == 0 || *source == '\0')
+ break;
+ *target++ = *source++;
+ remaining--;
+ }
+
+ /*
+ * If we hit premature end of string (ie, incomplete multibyte
+ * character), try to pad out to the correct length with spaces. We
+ * may not be able to pad completely, but we will always be able to
+ * insert at least one pad space (since we'd not have quoted a
+ * multibyte character). This should be enough to make a string that
+ * the server will error out on.
+ */
+ if (i < len)
+ {
+ if (error)
+ *error = 1;
+ if (conn)
+ libpq_append_conn_error(conn, "incomplete multibyte character");
+ for (; i < len; i++)
+ {
+ if (((size_t) (target - to)) / 2 >= length)
+ break;
+ *target++ = ' ';
+ }
+ break;
+ }
+ }
+
+ /* Write the terminating NUL character. */
+ *target = '\0';
+
+ return target - to;
+}
+
+size_t
+PQescapeStringConn(PGconn *conn,
+ char *to, const char *from, size_t length,
+ int *error)
+{
+ if (!conn)
+ {
+ /* force empty-string result */
+ *to = '\0';
+ if (error)
+ *error = 1;
+ return 0;
+ }
+
+ if (conn->cmd_queue_head == NULL)
+ pqClearConnErrorState(conn);
+
+ return PQescapeStringInternal(conn, to, from, length, error,
+ conn->client_encoding,
+ conn->std_strings);
+}
+
+size_t
+PQescapeString(char *to, const char *from, size_t length)
+{
+ return PQescapeStringInternal(NULL, to, from, length, NULL,
+ static_client_encoding,
+ static_std_strings);
+}
+
+
+/*
+ * Escape arbitrary strings. If as_ident is true, we escape the result
+ * as an identifier; if false, as a literal. The result is returned in
+ * a newly allocated buffer. If we fail due to an encoding violation or out
+ * of memory condition, we return NULL, storing an error message into conn.
+ */
+static char *
+PQescapeInternal(PGconn *conn, const char *str, size_t len, bool as_ident)
+{
+ const char *s;
+ char *result;
+ char *rp;
+ int num_quotes = 0; /* single or double, depending on as_ident */
+ int num_backslashes = 0;
+ int input_len;
+ int result_size;
+ char quote_char = as_ident ? '"' : '\'';
+
+ /* We must have a connection, else fail immediately. */
+ if (!conn)
+ return NULL;
+
+ if (conn->cmd_queue_head == NULL)
+ pqClearConnErrorState(conn);
+
+ /* Scan the string for characters that must be escaped. */
+ for (s = str; (s - str) < len && *s != '\0'; ++s)
+ {
+ if (*s == quote_char)
+ ++num_quotes;
+ else if (*s == '\\')
+ ++num_backslashes;
+ else if (IS_HIGHBIT_SET(*s))
+ {
+ int charlen;
+
+ /* Slow path for possible multibyte characters */
+ charlen = pg_encoding_mblen(conn->client_encoding, s);
+
+ /* Multibyte character overruns allowable length. */
+ if ((s - str) + charlen > len || memchr(s, 0, charlen) != NULL)
+ {
+ libpq_append_conn_error(conn, "incomplete multibyte character");
+ return NULL;
+ }
+
+ /* Adjust s, bearing in mind that for loop will increment it. */
+ s += charlen - 1;
+ }
+ }
+
+ /* Allocate output buffer. */
+ input_len = s - str;
+ result_size = input_len + num_quotes + 3; /* two quotes, plus a NUL */
+ if (!as_ident && num_backslashes > 0)
+ result_size += num_backslashes + 2;
+ result = rp = (char *) malloc(result_size);
+ if (rp == NULL)
+ {
+ libpq_append_conn_error(conn, "out of memory");
+ return NULL;
+ }
+
+ /*
+ * If we are escaping a literal that contains backslashes, we use the
+ * escape string syntax so that the result is correct under either value
+ * of standard_conforming_strings. We also emit a leading space in this
+ * case, to guard against the possibility that the result might be
+ * interpolated immediately following an identifier.
+ */
+ if (!as_ident && num_backslashes > 0)
+ {
+ *rp++ = ' ';
+ *rp++ = 'E';
+ }
+
+ /* Opening quote. */
+ *rp++ = quote_char;
+
+ /*
+ * Use fast path if possible.
+ *
+ * We've already verified that the input string is well-formed in the
+ * current encoding. If it contains no quotes and, in the case of
+ * literal-escaping, no backslashes, then we can just copy it directly to
+ * the output buffer, adding the necessary quotes.
+ *
+ * If not, we must rescan the input and process each character
+ * individually.
+ */
+ if (num_quotes == 0 && (num_backslashes == 0 || as_ident))
+ {
+ memcpy(rp, str, input_len);
+ rp += input_len;
+ }
+ else
+ {
+ for (s = str; s - str < input_len; ++s)
+ {
+ if (*s == quote_char || (!as_ident && *s == '\\'))
+ {
+ *rp++ = *s;
+ *rp++ = *s;
+ }
+ else if (!IS_HIGHBIT_SET(*s))
+ *rp++ = *s;
+ else
+ {
+ int i = pg_encoding_mblen(conn->client_encoding, s);
+
+ while (1)
+ {
+ *rp++ = *s;
+ if (--i == 0)
+ break;
+ ++s; /* for loop will provide the final increment */
+ }
+ }
+ }
+ }
+
+ /* Closing quote and terminating NUL. */
+ *rp++ = quote_char;
+ *rp = '\0';
+
+ return result;
+}
+
+char *
+PQescapeLiteral(PGconn *conn, const char *str, size_t len)
+{
+ return PQescapeInternal(conn, str, len, false);
+}
+
+char *
+PQescapeIdentifier(PGconn *conn, const char *str, size_t len)
+{
+ return PQescapeInternal(conn, str, len, true);
+}
+
+/* HEX encoding support for bytea */
+static const char hextbl[] = "0123456789abcdef";
+
+static const int8 hexlookup[128] = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
+ -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+};
+
+static inline char
+get_hex(char c)
+{
+ int res = -1;
+
+ if (c > 0 && c < 127)
+ res = hexlookup[(unsigned char) c];
+
+ return (char) res;
+}
+
+
+/*
+ * PQescapeBytea - converts from binary string to the
+ * minimal encoding necessary to include the string in an SQL
+ * INSERT statement with a bytea type column as the target.
+ *
+ * We can use either hex or escape (traditional) encoding.
+ * In escape mode, the following transformations are applied:
+ * '\0' == ASCII 0 == \000
+ * '\'' == ASCII 39 == ''
+ * '\\' == ASCII 92 == \\
+ * anything < 0x20, or > 0x7e ---> \ooo
+ * (where ooo is an octal expression)
+ *
+ * If not std_strings, all backslashes sent to the output are doubled.
+ */
+static unsigned char *
+PQescapeByteaInternal(PGconn *conn,
+ const unsigned char *from, size_t from_length,
+ size_t *to_length, bool std_strings, bool use_hex)
+{
+ const unsigned char *vp;
+ unsigned char *rp;
+ unsigned char *result;
+ size_t i;
+ size_t len;
+ size_t bslash_len = (std_strings ? 1 : 2);
+
+ /*
+ * empty string has 1 char ('\0')
+ */
+ len = 1;
+
+ if (use_hex)
+ {
+ len += bslash_len + 1 + 2 * from_length;
+ }
+ else
+ {
+ vp = from;
+ for (i = from_length; i > 0; i--, vp++)
+ {
+ if (*vp < 0x20 || *vp > 0x7e)
+ len += bslash_len + 3;
+ else if (*vp == '\'')
+ len += 2;
+ else if (*vp == '\\')
+ len += bslash_len + bslash_len;
+ else
+ len++;
+ }
+ }
+
+ *to_length = len;
+ rp = result = (unsigned char *) malloc(len);
+ if (rp == NULL)
+ {
+ if (conn)
+ libpq_append_conn_error(conn, "out of memory");
+ return NULL;
+ }
+
+ if (use_hex)
+ {
+ if (!std_strings)
+ *rp++ = '\\';
+ *rp++ = '\\';
+ *rp++ = 'x';
+ }
+
+ vp = from;
+ for (i = from_length; i > 0; i--, vp++)
+ {
+ unsigned char c = *vp;
+
+ if (use_hex)
+ {
+ *rp++ = hextbl[(c >> 4) & 0xF];
+ *rp++ = hextbl[c & 0xF];
+ }
+ else if (c < 0x20 || c > 0x7e)
+ {
+ if (!std_strings)
+ *rp++ = '\\';
+ *rp++ = '\\';
+ *rp++ = (c >> 6) + '0';
+ *rp++ = ((c >> 3) & 07) + '0';
+ *rp++ = (c & 07) + '0';
+ }
+ else if (c == '\'')
+ {
+ *rp++ = '\'';
+ *rp++ = '\'';
+ }
+ else if (c == '\\')
+ {
+ if (!std_strings)
+ {
+ *rp++ = '\\';
+ *rp++ = '\\';
+ }
+ *rp++ = '\\';
+ *rp++ = '\\';
+ }
+ else
+ *rp++ = c;
+ }
+ *rp = '\0';
+
+ return result;
+}
+
+unsigned char *
+PQescapeByteaConn(PGconn *conn,
+ const unsigned char *from, size_t from_length,
+ size_t *to_length)
+{
+ if (!conn)
+ return NULL;
+
+ if (conn->cmd_queue_head == NULL)
+ pqClearConnErrorState(conn);
+
+ return PQescapeByteaInternal(conn, from, from_length, to_length,
+ conn->std_strings,
+ (conn->sversion >= 90000));
+}
+
+unsigned char *
+PQescapeBytea(const unsigned char *from, size_t from_length, size_t *to_length)
+{
+ return PQescapeByteaInternal(NULL, from, from_length, to_length,
+ static_std_strings,
+ false /* can't use hex */ );
+}
+
+
+#define ISFIRSTOCTDIGIT(CH) ((CH) >= '0' && (CH) <= '3')
+#define ISOCTDIGIT(CH) ((CH) >= '0' && (CH) <= '7')
+#define OCTVAL(CH) ((CH) - '0')
+
+/*
+ * PQunescapeBytea - converts the null terminated string representation
+ * of a bytea, strtext, into binary, filling a buffer. It returns a
+ * pointer to the buffer (or NULL on error), and the size of the
+ * buffer in retbuflen. The pointer may subsequently be used as an
+ * argument to the function PQfreemem.
+ *
+ * The following transformations are made:
+ * \\ == ASCII 92 == \
+ * \ooo == a byte whose value = ooo (ooo is an octal number)
+ * \x == x (x is any character not matched by the above transformations)
+ */
+unsigned char *
+PQunescapeBytea(const unsigned char *strtext, size_t *retbuflen)
+{
+ size_t strtextlen,
+ buflen;
+ unsigned char *buffer,
+ *tmpbuf;
+ size_t i,
+ j;
+
+ if (strtext == NULL)
+ return NULL;
+
+ strtextlen = strlen((const char *) strtext);
+
+ if (strtext[0] == '\\' && strtext[1] == 'x')
+ {
+ const unsigned char *s;
+ unsigned char *p;
+
+ buflen = (strtextlen - 2) / 2;
+ /* Avoid unportable malloc(0) */
+ buffer = (unsigned char *) malloc(buflen > 0 ? buflen : 1);
+ if (buffer == NULL)
+ return NULL;
+
+ s = strtext + 2;
+ p = buffer;
+ while (*s)
+ {
+ char v1,
+ v2;
+
+ /*
+ * Bad input is silently ignored. Note that this includes
+ * whitespace between hex pairs, which is allowed by byteain.
+ */
+ v1 = get_hex(*s++);
+ if (!*s || v1 == (char) -1)
+ continue;
+ v2 = get_hex(*s++);
+ if (v2 != (char) -1)
+ *p++ = (v1 << 4) | v2;
+ }
+
+ buflen = p - buffer;
+ }
+ else
+ {
+ /*
+ * Length of input is max length of output, but add one to avoid
+ * unportable malloc(0) if input is zero-length.
+ */
+ buffer = (unsigned char *) malloc(strtextlen + 1);
+ if (buffer == NULL)
+ return NULL;
+
+ for (i = j = 0; i < strtextlen;)
+ {
+ switch (strtext[i])
+ {
+ case '\\':
+ i++;
+ if (strtext[i] == '\\')
+ buffer[j++] = strtext[i++];
+ else
+ {
+ if ((ISFIRSTOCTDIGIT(strtext[i])) &&
+ (ISOCTDIGIT(strtext[i + 1])) &&
+ (ISOCTDIGIT(strtext[i + 2])))
+ {
+ int byte;
+
+ byte = OCTVAL(strtext[i++]);
+ byte = (byte << 3) + OCTVAL(strtext[i++]);
+ byte = (byte << 3) + OCTVAL(strtext[i++]);
+ buffer[j++] = byte;
+ }
+ }
+
+ /*
+ * Note: if we see '\' followed by something that isn't a
+ * recognized escape sequence, we loop around having done
+ * nothing except advance i. Therefore the something will
+ * be emitted as ordinary data on the next cycle. Corner
+ * case: '\' at end of string will just be discarded.
+ */
+ break;
+
+ default:
+ buffer[j++] = strtext[i++];
+ break;
+ }
+ }
+ buflen = j; /* buflen is the length of the dequoted data */
+ }
+
+ /* Shrink the buffer to be no larger than necessary */
+ /* +1 avoids unportable behavior when buflen==0 */
+ tmpbuf = realloc(buffer, buflen + 1);
+
+ /* It would only be a very brain-dead realloc that could fail, but... */
+ if (!tmpbuf)
+ {
+ free(buffer);
+ return NULL;
+ }
+
+ *retbuflen = buflen;
+ return tmpbuf;
+}
diff --git a/contrib/libs/libpq/src/interfaces/libpq/fe-lobj.c b/contrib/libs/libpq/src/interfaces/libpq/fe-lobj.c
new file mode 100644
index 0000000000..206266fd04
--- /dev/null
+++ b/contrib/libs/libpq/src/interfaces/libpq/fe-lobj.c
@@ -0,0 +1,1064 @@
+/*-------------------------------------------------------------------------
+ *
+ * fe-lobj.c
+ * Front-end large object interface
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/interfaces/libpq/fe-lobj.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifdef WIN32
+/*
+ * As unlink/rename are #define'd in port.h (via postgres_fe.h), io.h
+ * must be included first on MS C. Might as well do it for all WIN32's
+ * here.
+ */
+#include <io.h>
+#endif
+
+#include "postgres_fe.h"
+
+#ifdef WIN32
+#include "win32.h"
+#else
+#include <unistd.h>
+#endif
+
+#include <fcntl.h>
+#include <limits.h>
+#include <sys/stat.h>
+
+#include "libpq-fe.h"
+#include "libpq-int.h"
+#include "libpq/libpq-fs.h" /* must come after sys/stat.h */
+#include "port/pg_bswap.h"
+
+#define LO_BUFSIZE 8192
+
+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);
+
+/*
+ * lo_open
+ * opens an existing large object
+ *
+ * returns the file descriptor for use in later lo_* calls
+ * return -1 upon failure.
+ */
+int
+lo_open(PGconn *conn, Oid lobjId, int mode)
+{
+ int fd;
+ int result_len;
+ PQArgBlock argv[2];
+ PGresult *res;
+
+ if (lo_initialize(conn) < 0)
+ return -1;
+
+ argv[0].isint = 1;
+ argv[0].len = 4;
+ argv[0].u.integer = lobjId;
+
+ argv[1].isint = 1;
+ argv[1].len = 4;
+ argv[1].u.integer = mode;
+
+ res = PQfn(conn, conn->lobjfuncs->fn_lo_open, &fd, &result_len, 1, argv, 2);
+ if (PQresultStatus(res) == PGRES_COMMAND_OK)
+ {
+ PQclear(res);
+ return fd;
+ }
+ else
+ {
+ PQclear(res);
+ return -1;
+ }
+}
+
+/*
+ * lo_close
+ * closes an existing large object
+ *
+ * returns 0 upon success
+ * returns -1 upon failure.
+ */
+int
+lo_close(PGconn *conn, int fd)
+{
+ PQArgBlock argv[1];
+ PGresult *res;
+ int retval;
+ int result_len;
+
+ if (lo_initialize(conn) < 0)
+ return -1;
+
+ argv[0].isint = 1;
+ argv[0].len = 4;
+ argv[0].u.integer = fd;
+ res = PQfn(conn, conn->lobjfuncs->fn_lo_close,
+ &retval, &result_len, 1, argv, 1);
+ if (PQresultStatus(res) == PGRES_COMMAND_OK)
+ {
+ PQclear(res);
+ return retval;
+ }
+ else
+ {
+ PQclear(res);
+ return -1;
+ }
+}
+
+/*
+ * lo_truncate
+ * truncates an existing large object to the given size
+ *
+ * returns 0 upon success
+ * returns -1 upon failure
+ */
+int
+lo_truncate(PGconn *conn, int fd, size_t len)
+{
+ PQArgBlock argv[2];
+ PGresult *res;
+ int retval;
+ int result_len;
+
+ if (lo_initialize(conn) < 0)
+ return -1;
+
+ /* Must check this on-the-fly because it's not there pre-8.3 */
+ if (conn->lobjfuncs->fn_lo_truncate == 0)
+ {
+ libpq_append_conn_error(conn, "cannot determine OID of function %s",
+ "lo_truncate");
+ return -1;
+ }
+
+ /*
+ * Long ago, somebody thought it'd be a good idea to declare this function
+ * as taking size_t ... but the underlying backend function only accepts a
+ * signed int32 length. So throw error if the given value overflows
+ * int32. (A possible alternative is to automatically redirect the call
+ * to lo_truncate64; but if the caller wanted to rely on that backend
+ * function being available, he could have called lo_truncate64 for
+ * himself.)
+ */
+ if (len > (size_t) INT_MAX)
+ {
+ libpq_append_conn_error(conn, "argument of lo_truncate exceeds integer range");
+ return -1;
+ }
+
+ argv[0].isint = 1;
+ argv[0].len = 4;
+ argv[0].u.integer = fd;
+
+ argv[1].isint = 1;
+ argv[1].len = 4;
+ argv[1].u.integer = (int) len;
+
+ res = PQfn(conn, conn->lobjfuncs->fn_lo_truncate,
+ &retval, &result_len, 1, argv, 2);
+
+ if (PQresultStatus(res) == PGRES_COMMAND_OK)
+ {
+ PQclear(res);
+ return retval;
+ }
+ else
+ {
+ PQclear(res);
+ return -1;
+ }
+}
+
+/*
+ * lo_truncate64
+ * truncates an existing large object to the given size
+ *
+ * returns 0 upon success
+ * returns -1 upon failure
+ */
+int
+lo_truncate64(PGconn *conn, int fd, pg_int64 len)
+{
+ PQArgBlock argv[2];
+ PGresult *res;
+ int retval;
+ int result_len;
+
+ if (lo_initialize(conn) < 0)
+ return -1;
+
+ if (conn->lobjfuncs->fn_lo_truncate64 == 0)
+ {
+ libpq_append_conn_error(conn, "cannot determine OID of function %s",
+ "lo_truncate64");
+ return -1;
+ }
+
+ argv[0].isint = 1;
+ argv[0].len = 4;
+ argv[0].u.integer = fd;
+
+ len = lo_hton64(len);
+ argv[1].isint = 0;
+ argv[1].len = 8;
+ argv[1].u.ptr = (int *) &len;
+
+ res = PQfn(conn, conn->lobjfuncs->fn_lo_truncate64,
+ &retval, &result_len, 1, argv, 2);
+
+ if (PQresultStatus(res) == PGRES_COMMAND_OK)
+ {
+ PQclear(res);
+ return retval;
+ }
+ else
+ {
+ PQclear(res);
+ return -1;
+ }
+}
+
+/*
+ * lo_read
+ * read len bytes of the large object into buf
+ *
+ * returns the number of bytes read, or -1 on failure.
+ * the CALLER must have allocated enough space to hold the result returned
+ */
+
+int
+lo_read(PGconn *conn, int fd, char *buf, size_t len)
+{
+ PQArgBlock argv[2];
+ PGresult *res;
+ int result_len;
+
+ if (lo_initialize(conn) < 0)
+ return -1;
+
+ /*
+ * Long ago, somebody thought it'd be a good idea to declare this function
+ * as taking size_t ... but the underlying backend function only accepts a
+ * signed int32 length. So throw error if the given value overflows
+ * int32.
+ */
+ if (len > (size_t) INT_MAX)
+ {
+ libpq_append_conn_error(conn, "argument of lo_read exceeds integer range");
+ return -1;
+ }
+
+ argv[0].isint = 1;
+ argv[0].len = 4;
+ argv[0].u.integer = fd;
+
+ argv[1].isint = 1;
+ argv[1].len = 4;
+ argv[1].u.integer = (int) len;
+
+ res = PQfn(conn, conn->lobjfuncs->fn_lo_read,
+ (void *) buf, &result_len, 0, argv, 2);
+ if (PQresultStatus(res) == PGRES_COMMAND_OK)
+ {
+ PQclear(res);
+ return result_len;
+ }
+ else
+ {
+ PQclear(res);
+ return -1;
+ }
+}
+
+/*
+ * lo_write
+ * write len bytes of buf into the large object fd
+ *
+ * returns the number of bytes written, or -1 on failure.
+ */
+int
+lo_write(PGconn *conn, int fd, const char *buf, size_t len)
+{
+ PQArgBlock argv[2];
+ PGresult *res;
+ int result_len;
+ int retval;
+
+ if (lo_initialize(conn) < 0)
+ return -1;
+
+ /*
+ * Long ago, somebody thought it'd be a good idea to declare this function
+ * as taking size_t ... but the underlying backend function only accepts a
+ * signed int32 length. So throw error if the given value overflows
+ * int32.
+ */
+ if (len > (size_t) INT_MAX)
+ {
+ libpq_append_conn_error(conn, "argument of lo_write exceeds integer range");
+ return -1;
+ }
+
+ argv[0].isint = 1;
+ argv[0].len = 4;
+ argv[0].u.integer = fd;
+
+ argv[1].isint = 0;
+ argv[1].len = (int) len;
+ argv[1].u.ptr = (int *) unconstify(char *, buf);
+
+ res = PQfn(conn, conn->lobjfuncs->fn_lo_write,
+ &retval, &result_len, 1, argv, 2);
+ if (PQresultStatus(res) == PGRES_COMMAND_OK)
+ {
+ PQclear(res);
+ return retval;
+ }
+ else
+ {
+ PQclear(res);
+ return -1;
+ }
+}
+
+/*
+ * lo_lseek
+ * change the current read or write location on a large object
+ */
+int
+lo_lseek(PGconn *conn, int fd, int offset, int whence)
+{
+ PQArgBlock argv[3];
+ PGresult *res;
+ int retval;
+ int result_len;
+
+ if (lo_initialize(conn) < 0)
+ return -1;
+
+ argv[0].isint = 1;
+ argv[0].len = 4;
+ argv[0].u.integer = fd;
+
+ argv[1].isint = 1;
+ argv[1].len = 4;
+ argv[1].u.integer = offset;
+
+ argv[2].isint = 1;
+ argv[2].len = 4;
+ argv[2].u.integer = whence;
+
+ res = PQfn(conn, conn->lobjfuncs->fn_lo_lseek,
+ &retval, &result_len, 1, argv, 3);
+ if (PQresultStatus(res) == PGRES_COMMAND_OK)
+ {
+ PQclear(res);
+ return retval;
+ }
+ else
+ {
+ PQclear(res);
+ return -1;
+ }
+}
+
+/*
+ * 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)
+{
+ PQArgBlock argv[3];
+ PGresult *res;
+ pg_int64 retval;
+ int result_len;
+
+ if (lo_initialize(conn) < 0)
+ return -1;
+
+ if (conn->lobjfuncs->fn_lo_lseek64 == 0)
+ {
+ libpq_append_conn_error(conn, "cannot determine OID of function %s",
+ "lo_lseek64");
+ return -1;
+ }
+
+ argv[0].isint = 1;
+ argv[0].len = 4;
+ argv[0].u.integer = fd;
+
+ offset = lo_hton64(offset);
+ argv[1].isint = 0;
+ argv[1].len = 8;
+ argv[1].u.ptr = (int *) &offset;
+
+ argv[2].isint = 1;
+ argv[2].len = 4;
+ argv[2].u.integer = whence;
+
+ res = PQfn(conn, conn->lobjfuncs->fn_lo_lseek64,
+ (void *) &retval, &result_len, 0, argv, 3);
+ if (PQresultStatus(res) == PGRES_COMMAND_OK && result_len == 8)
+ {
+ PQclear(res);
+ return lo_ntoh64(retval);
+ }
+ else
+ {
+ PQclear(res);
+ return -1;
+ }
+}
+
+/*
+ * lo_creat
+ * create a new large object
+ * the mode is ignored (once upon a time it had a use)
+ *
+ * returns the oid of the large object created or
+ * InvalidOid upon failure
+ */
+Oid
+lo_creat(PGconn *conn, int mode)
+{
+ PQArgBlock argv[1];
+ PGresult *res;
+ int retval;
+ int result_len;
+
+ if (lo_initialize(conn) < 0)
+ return InvalidOid;
+
+ argv[0].isint = 1;
+ argv[0].len = 4;
+ argv[0].u.integer = mode;
+ res = PQfn(conn, conn->lobjfuncs->fn_lo_creat,
+ &retval, &result_len, 1, argv, 1);
+ if (PQresultStatus(res) == PGRES_COMMAND_OK)
+ {
+ PQclear(res);
+ return (Oid) retval;
+ }
+ else
+ {
+ PQclear(res);
+ return InvalidOid;
+ }
+}
+
+/*
+ * lo_create
+ * create a new large object
+ * if lobjId isn't InvalidOid, it specifies the OID to (attempt to) create
+ *
+ * returns the oid of the large object created or
+ * InvalidOid upon failure
+ */
+Oid
+lo_create(PGconn *conn, Oid lobjId)
+{
+ PQArgBlock argv[1];
+ PGresult *res;
+ int retval;
+ int result_len;
+
+ if (lo_initialize(conn) < 0)
+ return InvalidOid;
+
+ /* Must check this on-the-fly because it's not there pre-8.1 */
+ if (conn->lobjfuncs->fn_lo_create == 0)
+ {
+ libpq_append_conn_error(conn, "cannot determine OID of function %s",
+ "lo_create");
+ return InvalidOid;
+ }
+
+ argv[0].isint = 1;
+ argv[0].len = 4;
+ argv[0].u.integer = lobjId;
+ res = PQfn(conn, conn->lobjfuncs->fn_lo_create,
+ &retval, &result_len, 1, argv, 1);
+ if (PQresultStatus(res) == PGRES_COMMAND_OK)
+ {
+ PQclear(res);
+ return (Oid) retval;
+ }
+ else
+ {
+ PQclear(res);
+ return InvalidOid;
+ }
+}
+
+
+/*
+ * lo_tell
+ * returns the current seek location of the large object
+ */
+int
+lo_tell(PGconn *conn, int fd)
+{
+ int retval;
+ PQArgBlock argv[1];
+ PGresult *res;
+ int result_len;
+
+ if (lo_initialize(conn) < 0)
+ return -1;
+
+ argv[0].isint = 1;
+ argv[0].len = 4;
+ argv[0].u.integer = fd;
+
+ res = PQfn(conn, conn->lobjfuncs->fn_lo_tell,
+ &retval, &result_len, 1, argv, 1);
+ if (PQresultStatus(res) == PGRES_COMMAND_OK)
+ {
+ PQclear(res);
+ return retval;
+ }
+ else
+ {
+ PQclear(res);
+ return -1;
+ }
+}
+
+/*
+ * lo_tell64
+ * returns the current seek location of the large object
+ */
+pg_int64
+lo_tell64(PGconn *conn, int fd)
+{
+ pg_int64 retval;
+ PQArgBlock argv[1];
+ PGresult *res;
+ int result_len;
+
+ if (lo_initialize(conn) < 0)
+ return -1;
+
+ if (conn->lobjfuncs->fn_lo_tell64 == 0)
+ {
+ libpq_append_conn_error(conn, "cannot determine OID of function %s",
+ "lo_tell64");
+ return -1;
+ }
+
+ argv[0].isint = 1;
+ argv[0].len = 4;
+ argv[0].u.integer = fd;
+
+ res = PQfn(conn, conn->lobjfuncs->fn_lo_tell64,
+ (void *) &retval, &result_len, 0, argv, 1);
+ if (PQresultStatus(res) == PGRES_COMMAND_OK && result_len == 8)
+ {
+ PQclear(res);
+ return lo_ntoh64(retval);
+ }
+ else
+ {
+ PQclear(res);
+ return -1;
+ }
+}
+
+/*
+ * lo_unlink
+ * delete a file
+ */
+
+int
+lo_unlink(PGconn *conn, Oid lobjId)
+{
+ PQArgBlock argv[1];
+ PGresult *res;
+ int result_len;
+ int retval;
+
+ if (lo_initialize(conn) < 0)
+ return -1;
+
+ argv[0].isint = 1;
+ argv[0].len = 4;
+ argv[0].u.integer = lobjId;
+
+ res = PQfn(conn, conn->lobjfuncs->fn_lo_unlink,
+ &retval, &result_len, 1, argv, 1);
+ if (PQresultStatus(res) == PGRES_COMMAND_OK)
+ {
+ PQclear(res);
+ return retval;
+ }
+ else
+ {
+ PQclear(res);
+ return -1;
+ }
+}
+
+/*
+ * lo_import -
+ * imports a file as an (inversion) large object.
+ *
+ * returns the oid of that object upon success,
+ * returns InvalidOid upon failure
+ */
+
+Oid
+lo_import(PGconn *conn, const char *filename)
+{
+ return lo_import_internal(conn, filename, InvalidOid);
+}
+
+/*
+ * lo_import_with_oid -
+ * imports a file as an (inversion) large object.
+ * large object id can be specified.
+ *
+ * returns the oid of that object upon success,
+ * returns InvalidOid upon failure
+ */
+
+Oid
+lo_import_with_oid(PGconn *conn, const char *filename, Oid lobjId)
+{
+ return lo_import_internal(conn, filename, lobjId);
+}
+
+static Oid
+lo_import_internal(PGconn *conn, const char *filename, Oid oid)
+{
+ int fd;
+ int nbytes,
+ tmp;
+ char buf[LO_BUFSIZE];
+ Oid lobjOid;
+ int lobj;
+ char sebuf[PG_STRERROR_R_BUFLEN];
+
+ if (conn == NULL)
+ return InvalidOid;
+
+ /* Since this is the beginning of a query cycle, reset the error state */
+ pqClearConnErrorState(conn);
+
+ /*
+ * open the file to be read in
+ */
+ fd = open(filename, O_RDONLY | PG_BINARY, 0666);
+ if (fd < 0)
+ { /* error */
+ libpq_append_conn_error(conn, "could not open file \"%s\": %s",
+ filename, strerror_r(errno, sebuf, sizeof(sebuf)));
+ return InvalidOid;
+ }
+
+ /*
+ * create an inversion object
+ */
+ if (oid == InvalidOid)
+ lobjOid = lo_creat(conn, INV_READ | INV_WRITE);
+ else
+ lobjOid = lo_create(conn, oid);
+
+ if (lobjOid == InvalidOid)
+ {
+ /* we assume lo_create() already set a suitable error message */
+ (void) close(fd);
+ return InvalidOid;
+ }
+
+ lobj = lo_open(conn, lobjOid, INV_WRITE);
+ if (lobj == -1)
+ {
+ /* we assume lo_open() already set a suitable error message */
+ (void) close(fd);
+ return InvalidOid;
+ }
+
+ /*
+ * read in from the file and write to the large object
+ */
+ while ((nbytes = read(fd, buf, LO_BUFSIZE)) > 0)
+ {
+ tmp = lo_write(conn, lobj, buf, nbytes);
+ if (tmp != nbytes)
+ {
+ /*
+ * If lo_write() failed, we are now in an aborted transaction so
+ * there's no need for lo_close(); furthermore, if we tried it
+ * we'd overwrite the useful error result with a useless one. So
+ * just nail the doors shut and get out of town.
+ */
+ (void) close(fd);
+ return InvalidOid;
+ }
+ }
+
+ if (nbytes < 0)
+ {
+ /* We must do lo_close before setting the errorMessage */
+ int save_errno = errno;
+
+ (void) lo_close(conn, lobj);
+ (void) close(fd);
+ /* deliberately overwrite any error from lo_close */
+ pqClearConnErrorState(conn);
+ libpq_append_conn_error(conn, "could not read from file \"%s\": %s",
+ filename,
+ strerror_r(save_errno, sebuf, sizeof(sebuf)));
+ return InvalidOid;
+ }
+
+ (void) close(fd);
+
+ if (lo_close(conn, lobj) != 0)
+ {
+ /* we assume lo_close() already set a suitable error message */
+ return InvalidOid;
+ }
+
+ return lobjOid;
+}
+
+/*
+ * lo_export -
+ * exports an (inversion) large object.
+ * returns -1 upon failure, 1 if OK
+ */
+int
+lo_export(PGconn *conn, Oid lobjId, const char *filename)
+{
+ int result = 1;
+ int fd;
+ int nbytes,
+ tmp;
+ char buf[LO_BUFSIZE];
+ int lobj;
+ char sebuf[PG_STRERROR_R_BUFLEN];
+
+ /*
+ * open the large object.
+ */
+ lobj = lo_open(conn, lobjId, INV_READ);
+ if (lobj == -1)
+ {
+ /* we assume lo_open() already set a suitable error message */
+ return -1;
+ }
+
+ /*
+ * create the file to be written to
+ */
+ fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC | PG_BINARY, 0666);
+ if (fd < 0)
+ {
+ /* We must do lo_close before setting the errorMessage */
+ int save_errno = errno;
+
+ (void) lo_close(conn, lobj);
+ /* deliberately overwrite any error from lo_close */
+ pqClearConnErrorState(conn);
+ libpq_append_conn_error(conn, "could not open file \"%s\": %s",
+ filename,
+ strerror_r(save_errno, sebuf, sizeof(sebuf)));
+ return -1;
+ }
+
+ /*
+ * read in from the large object and write to the file
+ */
+ while ((nbytes = lo_read(conn, lobj, buf, LO_BUFSIZE)) > 0)
+ {
+ tmp = write(fd, buf, nbytes);
+ if (tmp != nbytes)
+ {
+ /* We must do lo_close before setting the errorMessage */
+ int save_errno = errno;
+
+ (void) lo_close(conn, lobj);
+ (void) close(fd);
+ /* deliberately overwrite any error from lo_close */
+ pqClearConnErrorState(conn);
+ libpq_append_conn_error(conn, "could not write to file \"%s\": %s",
+ filename,
+ strerror_r(save_errno, sebuf, sizeof(sebuf)));
+ return -1;
+ }
+ }
+
+ /*
+ * If lo_read() failed, we are now in an aborted transaction so there's no
+ * need for lo_close(); furthermore, if we tried it we'd overwrite the
+ * useful error result with a useless one. So skip lo_close() if we got a
+ * failure result.
+ */
+ if (nbytes < 0 ||
+ lo_close(conn, lobj) != 0)
+ {
+ /* assume lo_read() or lo_close() left a suitable error message */
+ result = -1;
+ }
+
+ /* if we already failed, don't overwrite that msg with a close error */
+ if (close(fd) != 0 && result >= 0)
+ {
+ libpq_append_conn_error(conn, "could not write to file \"%s\": %s",
+ filename, strerror_r(errno, sebuf, sizeof(sebuf)));
+ result = -1;
+ }
+
+ return result;
+}
+
+
+/*
+ * lo_initialize
+ *
+ * Initialize for a new large-object operation on an existing connection.
+ * Return 0 if OK, -1 on failure.
+ *
+ * If we haven't previously done so, we collect the function OIDs from
+ * pg_proc for all functions that are required for large object operations.
+ */
+static int
+lo_initialize(PGconn *conn)
+{
+ PGresult *res;
+ PGlobjfuncs *lobjfuncs;
+ int n;
+ const char *query;
+ const char *fname;
+ Oid foid;
+
+ /* Nothing we can do with no connection */
+ if (conn == NULL)
+ return -1;
+
+ /* Since this is the beginning of a query cycle, reset the error state */
+ pqClearConnErrorState(conn);
+
+ /* Nothing else to do if we already collected info */
+ if (conn->lobjfuncs != NULL)
+ return 0;
+
+ /*
+ * Allocate the structure to hold the function OIDs. We don't store it
+ * into the PGconn until it's successfully filled.
+ */
+ lobjfuncs = (PGlobjfuncs *) malloc(sizeof(PGlobjfuncs));
+ if (lobjfuncs == NULL)
+ {
+ libpq_append_conn_error(conn, "out of memory");
+ return -1;
+ }
+ MemSet((char *) lobjfuncs, 0, sizeof(PGlobjfuncs));
+
+ /*
+ * Execute the query to get all the functions at once. (Not all of them
+ * may exist in older server versions.)
+ */
+ query = "select proname, oid from pg_catalog.pg_proc "
+ "where proname in ("
+ "'lo_open', "
+ "'lo_close', "
+ "'lo_creat', "
+ "'lo_create', "
+ "'lo_unlink', "
+ "'lo_lseek', "
+ "'lo_lseek64', "
+ "'lo_tell', "
+ "'lo_tell64', "
+ "'lo_truncate', "
+ "'lo_truncate64', "
+ "'loread', "
+ "'lowrite') "
+ "and pronamespace = (select oid from pg_catalog.pg_namespace "
+ "where nspname = 'pg_catalog')";
+
+ res = PQexec(conn, query);
+ if (res == NULL)
+ {
+ free(lobjfuncs);
+ return -1;
+ }
+
+ if (res->resultStatus != PGRES_TUPLES_OK)
+ {
+ free(lobjfuncs);
+ PQclear(res);
+ libpq_append_conn_error(conn, "query to initialize large object functions did not return data");
+ return -1;
+ }
+
+ /*
+ * Examine the result and put the OID's into the struct
+ */
+ for (n = 0; n < PQntuples(res); n++)
+ {
+ fname = PQgetvalue(res, n, 0);
+ foid = (Oid) atoi(PQgetvalue(res, n, 1));
+ if (strcmp(fname, "lo_open") == 0)
+ lobjfuncs->fn_lo_open = foid;
+ else if (strcmp(fname, "lo_close") == 0)
+ lobjfuncs->fn_lo_close = foid;
+ else if (strcmp(fname, "lo_creat") == 0)
+ lobjfuncs->fn_lo_creat = foid;
+ else if (strcmp(fname, "lo_create") == 0)
+ lobjfuncs->fn_lo_create = foid;
+ else if (strcmp(fname, "lo_unlink") == 0)
+ lobjfuncs->fn_lo_unlink = foid;
+ else if (strcmp(fname, "lo_lseek") == 0)
+ lobjfuncs->fn_lo_lseek = foid;
+ else if (strcmp(fname, "lo_lseek64") == 0)
+ lobjfuncs->fn_lo_lseek64 = foid;
+ else if (strcmp(fname, "lo_tell") == 0)
+ lobjfuncs->fn_lo_tell = foid;
+ else if (strcmp(fname, "lo_tell64") == 0)
+ lobjfuncs->fn_lo_tell64 = foid;
+ else if (strcmp(fname, "lo_truncate") == 0)
+ lobjfuncs->fn_lo_truncate = foid;
+ else if (strcmp(fname, "lo_truncate64") == 0)
+ lobjfuncs->fn_lo_truncate64 = foid;
+ else if (strcmp(fname, "loread") == 0)
+ lobjfuncs->fn_lo_read = foid;
+ else if (strcmp(fname, "lowrite") == 0)
+ lobjfuncs->fn_lo_write = foid;
+ }
+
+ PQclear(res);
+
+ /*
+ * Finally check that we got all required large object interface functions
+ * (ones that have been added later than the stone age are instead checked
+ * only if used)
+ */
+ if (lobjfuncs->fn_lo_open == 0)
+ {
+ libpq_append_conn_error(conn, "cannot determine OID of function %s",
+ "lo_open");
+ free(lobjfuncs);
+ return -1;
+ }
+ if (lobjfuncs->fn_lo_close == 0)
+ {
+ libpq_append_conn_error(conn, "cannot determine OID of function %s",
+ "lo_close");
+ free(lobjfuncs);
+ return -1;
+ }
+ if (lobjfuncs->fn_lo_creat == 0)
+ {
+ libpq_append_conn_error(conn, "cannot determine OID of function %s",
+ "lo_creat");
+ free(lobjfuncs);
+ return -1;
+ }
+ if (lobjfuncs->fn_lo_unlink == 0)
+ {
+ libpq_append_conn_error(conn, "cannot determine OID of function %s",
+ "lo_unlink");
+ free(lobjfuncs);
+ return -1;
+ }
+ if (lobjfuncs->fn_lo_lseek == 0)
+ {
+ libpq_append_conn_error(conn, "cannot determine OID of function %s",
+ "lo_lseek");
+ free(lobjfuncs);
+ return -1;
+ }
+ if (lobjfuncs->fn_lo_tell == 0)
+ {
+ libpq_append_conn_error(conn, "cannot determine OID of function %s",
+ "lo_tell");
+ free(lobjfuncs);
+ return -1;
+ }
+ if (lobjfuncs->fn_lo_read == 0)
+ {
+ libpq_append_conn_error(conn, "cannot determine OID of function %s",
+ "loread");
+ free(lobjfuncs);
+ return -1;
+ }
+ if (lobjfuncs->fn_lo_write == 0)
+ {
+ libpq_append_conn_error(conn, "cannot determine OID of function %s",
+ "lowrite");
+ free(lobjfuncs);
+ return -1;
+ }
+
+ /*
+ * Put the structure into the connection control
+ */
+ conn->lobjfuncs = lobjfuncs;
+ return 0;
+}
+
+/*
+ * lo_hton64
+ * converts a 64-bit integer from host byte order to network byte order
+ */
+static pg_int64
+lo_hton64(pg_int64 host64)
+{
+ union
+ {
+ pg_int64 i64;
+ uint32 i32[2];
+ } swap;
+ uint32 t;
+
+ /* High order half first, since we're doing MSB-first */
+ t = (uint32) (host64 >> 32);
+ swap.i32[0] = pg_hton32(t);
+
+ /* Now the low order half */
+ t = (uint32) host64;
+ swap.i32[1] = pg_hton32(t);
+
+ return swap.i64;
+}
+
+/*
+ * lo_ntoh64
+ * converts a 64-bit integer from network byte order to host byte order
+ */
+static pg_int64
+lo_ntoh64(pg_int64 net64)
+{
+ union
+ {
+ pg_int64 i64;
+ uint32 i32[2];
+ } swap;
+ pg_int64 result;
+
+ swap.i64 = net64;
+
+ result = (uint32) pg_ntoh32(swap.i32[0]);
+ result <<= 32;
+ result |= (uint32) pg_ntoh32(swap.i32[1]);
+
+ return result;
+}
diff --git a/contrib/libs/libpq/src/interfaces/libpq/fe-misc.c b/contrib/libs/libpq/src/interfaces/libpq/fe-misc.c
new file mode 100644
index 0000000000..660cdec93c
--- /dev/null
+++ b/contrib/libs/libpq/src/interfaces/libpq/fe-misc.c
@@ -0,0 +1,1333 @@
+/*-------------------------------------------------------------------------
+ *
+ * FILE
+ * fe-misc.c
+ *
+ * DESCRIPTION
+ * miscellaneous useful functions
+ *
+ * The communication routines here are analogous to the ones in
+ * backend/libpq/pqcomm.c and backend/libpq/pqformat.c, but operate
+ * in the considerably different environment of the frontend libpq.
+ * In particular, we work with a bare nonblock-mode socket, rather than
+ * a stdio stream, so that we can avoid unwanted blocking of the application.
+ *
+ * XXX: MOVE DEBUG PRINTOUT TO HIGHER LEVEL. As is, block and restart
+ * will cause repeat printouts.
+ *
+ * We must speak the same transmitted data representations as the backend
+ * routines.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/interfaces/libpq/fe-misc.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres_fe.h"
+
+#include <signal.h>
+#include <time.h>
+
+#ifdef WIN32
+#include "win32.h"
+#else
+#include <unistd.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#endif
+
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#endif
+
+#include "libpq-fe.h"
+#include "libpq-int.h"
+#include "mb/pg_wchar.h"
+#include "pg_config_paths.h"
+#include "port/pg_bswap.h"
+
+static int pqPutMsgBytes(const void *buf, size_t len, PGconn *conn);
+static int pqSendSome(PGconn *conn, int len);
+static int pqSocketCheck(PGconn *conn, int forRead, int forWrite,
+ time_t end_time);
+static int pqSocketPoll(int sock, int forRead, int forWrite, time_t end_time);
+
+/*
+ * PQlibVersion: return the libpq version number
+ */
+int
+PQlibVersion(void)
+{
+ return PG_VERSION_NUM;
+}
+
+
+/*
+ * pqGetc: get 1 character from the connection
+ *
+ * All these routines return 0 on success, EOF on error.
+ * Note that for the Get routines, EOF only means there is not enough
+ * data in the buffer, not that there is necessarily a hard error.
+ */
+int
+pqGetc(char *result, PGconn *conn)
+{
+ if (conn->inCursor >= conn->inEnd)
+ return EOF;
+
+ *result = conn->inBuffer[conn->inCursor++];
+
+ return 0;
+}
+
+
+/*
+ * pqPutc: write 1 char to the current message
+ */
+int
+pqPutc(char c, PGconn *conn)
+{
+ if (pqPutMsgBytes(&c, 1, conn))
+ return EOF;
+
+ return 0;
+}
+
+
+/*
+ * pqGets[_append]:
+ * get a null-terminated string from the connection,
+ * and store it in an expansible PQExpBuffer.
+ * If we run out of memory, all of the string is still read,
+ * but the excess characters are silently discarded.
+ */
+static int
+pqGets_internal(PQExpBuffer buf, PGconn *conn, bool resetbuffer)
+{
+ /* Copy conn data to locals for faster search loop */
+ char *inBuffer = conn->inBuffer;
+ int inCursor = conn->inCursor;
+ int inEnd = conn->inEnd;
+ int slen;
+
+ while (inCursor < inEnd && inBuffer[inCursor])
+ inCursor++;
+
+ if (inCursor >= inEnd)
+ return EOF;
+
+ slen = inCursor - conn->inCursor;
+
+ if (resetbuffer)
+ resetPQExpBuffer(buf);
+
+ appendBinaryPQExpBuffer(buf, inBuffer + conn->inCursor, slen);
+
+ conn->inCursor = ++inCursor;
+
+ return 0;
+}
+
+int
+pqGets(PQExpBuffer buf, PGconn *conn)
+{
+ return pqGets_internal(buf, conn, true);
+}
+
+int
+pqGets_append(PQExpBuffer buf, PGconn *conn)
+{
+ return pqGets_internal(buf, conn, false);
+}
+
+
+/*
+ * pqPuts: write a null-terminated string to the current message
+ */
+int
+pqPuts(const char *s, PGconn *conn)
+{
+ if (pqPutMsgBytes(s, strlen(s) + 1, conn))
+ return EOF;
+
+ return 0;
+}
+
+/*
+ * pqGetnchar:
+ * get a string of exactly len bytes in buffer s, no null termination
+ */
+int
+pqGetnchar(char *s, size_t len, PGconn *conn)
+{
+ if (len > (size_t) (conn->inEnd - conn->inCursor))
+ return EOF;
+
+ memcpy(s, conn->inBuffer + conn->inCursor, len);
+ /* no terminating null */
+
+ conn->inCursor += len;
+
+ return 0;
+}
+
+/*
+ * pqSkipnchar:
+ * skip over len bytes in input buffer.
+ *
+ * Note: this is primarily useful for its debug output, which should
+ * be exactly the same as for pqGetnchar. We assume the data in question
+ * will actually be used, but just isn't getting copied anywhere as yet.
+ */
+int
+pqSkipnchar(size_t len, PGconn *conn)
+{
+ if (len > (size_t) (conn->inEnd - conn->inCursor))
+ return EOF;
+
+ conn->inCursor += len;
+
+ return 0;
+}
+
+/*
+ * pqPutnchar:
+ * write exactly len bytes to the current message
+ */
+int
+pqPutnchar(const char *s, size_t len, PGconn *conn)
+{
+ if (pqPutMsgBytes(s, len, conn))
+ return EOF;
+
+ return 0;
+}
+
+/*
+ * pqGetInt
+ * read a 2 or 4 byte integer and convert from network byte order
+ * to local byte order
+ */
+int
+pqGetInt(int *result, size_t bytes, PGconn *conn)
+{
+ uint16 tmp2;
+ uint32 tmp4;
+
+ switch (bytes)
+ {
+ case 2:
+ if (conn->inCursor + 2 > conn->inEnd)
+ return EOF;
+ memcpy(&tmp2, conn->inBuffer + conn->inCursor, 2);
+ conn->inCursor += 2;
+ *result = (int) pg_ntoh16(tmp2);
+ break;
+ case 4:
+ if (conn->inCursor + 4 > conn->inEnd)
+ return EOF;
+ memcpy(&tmp4, conn->inBuffer + conn->inCursor, 4);
+ conn->inCursor += 4;
+ *result = (int) pg_ntoh32(tmp4);
+ break;
+ default:
+ pqInternalNotice(&conn->noticeHooks,
+ "integer of size %lu not supported by pqGetInt",
+ (unsigned long) bytes);
+ return EOF;
+ }
+
+ return 0;
+}
+
+/*
+ * pqPutInt
+ * write an integer of 2 or 4 bytes, converting from host byte order
+ * to network byte order.
+ */
+int
+pqPutInt(int value, size_t bytes, PGconn *conn)
+{
+ uint16 tmp2;
+ uint32 tmp4;
+
+ switch (bytes)
+ {
+ case 2:
+ tmp2 = pg_hton16((uint16) value);
+ if (pqPutMsgBytes((const char *) &tmp2, 2, conn))
+ return EOF;
+ break;
+ case 4:
+ tmp4 = pg_hton32((uint32) value);
+ if (pqPutMsgBytes((const char *) &tmp4, 4, conn))
+ return EOF;
+ break;
+ default:
+ pqInternalNotice(&conn->noticeHooks,
+ "integer of size %lu not supported by pqPutInt",
+ (unsigned long) bytes);
+ return EOF;
+ }
+
+ return 0;
+}
+
+/*
+ * Make sure conn's output buffer can hold bytes_needed bytes (caller must
+ * include already-stored data into the value!)
+ *
+ * Returns 0 on success, EOF if failed to enlarge buffer
+ */
+int
+pqCheckOutBufferSpace(size_t bytes_needed, PGconn *conn)
+{
+ int newsize = conn->outBufSize;
+ char *newbuf;
+
+ /* Quick exit if we have enough space */
+ if (bytes_needed <= (size_t) newsize)
+ return 0;
+
+ /*
+ * If we need to enlarge the buffer, we first try to double it in size; if
+ * that doesn't work, enlarge in multiples of 8K. This avoids thrashing
+ * the malloc pool by repeated small enlargements.
+ *
+ * Note: tests for newsize > 0 are to catch integer overflow.
+ */
+ do
+ {
+ newsize *= 2;
+ } while (newsize > 0 && bytes_needed > (size_t) newsize);
+
+ if (newsize > 0 && bytes_needed <= (size_t) newsize)
+ {
+ newbuf = realloc(conn->outBuffer, newsize);
+ if (newbuf)
+ {
+ /* realloc succeeded */
+ conn->outBuffer = newbuf;
+ conn->outBufSize = newsize;
+ return 0;
+ }
+ }
+
+ newsize = conn->outBufSize;
+ do
+ {
+ newsize += 8192;
+ } while (newsize > 0 && bytes_needed > (size_t) newsize);
+
+ if (newsize > 0 && bytes_needed <= (size_t) newsize)
+ {
+ newbuf = realloc(conn->outBuffer, newsize);
+ if (newbuf)
+ {
+ /* realloc succeeded */
+ conn->outBuffer = newbuf;
+ conn->outBufSize = newsize;
+ return 0;
+ }
+ }
+
+ /* realloc failed. Probably out of memory */
+ appendPQExpBufferStr(&conn->errorMessage,
+ "cannot allocate memory for output buffer\n");
+ return EOF;
+}
+
+/*
+ * Make sure conn's input buffer can hold bytes_needed bytes (caller must
+ * include already-stored data into the value!)
+ *
+ * Returns 0 on success, EOF if failed to enlarge buffer
+ */
+int
+pqCheckInBufferSpace(size_t bytes_needed, PGconn *conn)
+{
+ int newsize = conn->inBufSize;
+ char *newbuf;
+
+ /* Quick exit if we have enough space */
+ if (bytes_needed <= (size_t) newsize)
+ return 0;
+
+ /*
+ * Before concluding that we need to enlarge the buffer, left-justify
+ * whatever is in it and recheck. The caller's value of bytes_needed
+ * includes any data to the left of inStart, but we can delete that in
+ * preference to enlarging the buffer. It's slightly ugly to have this
+ * function do this, but it's better than making callers worry about it.
+ */
+ bytes_needed -= conn->inStart;
+
+ if (conn->inStart < conn->inEnd)
+ {
+ if (conn->inStart > 0)
+ {
+ memmove(conn->inBuffer, conn->inBuffer + conn->inStart,
+ conn->inEnd - conn->inStart);
+ conn->inEnd -= conn->inStart;
+ conn->inCursor -= conn->inStart;
+ conn->inStart = 0;
+ }
+ }
+ else
+ {
+ /* buffer is logically empty, reset it */
+ conn->inStart = conn->inCursor = conn->inEnd = 0;
+ }
+
+ /* Recheck whether we have enough space */
+ if (bytes_needed <= (size_t) newsize)
+ return 0;
+
+ /*
+ * If we need to enlarge the buffer, we first try to double it in size; if
+ * that doesn't work, enlarge in multiples of 8K. This avoids thrashing
+ * the malloc pool by repeated small enlargements.
+ *
+ * Note: tests for newsize > 0 are to catch integer overflow.
+ */
+ do
+ {
+ newsize *= 2;
+ } while (newsize > 0 && bytes_needed > (size_t) newsize);
+
+ if (newsize > 0 && bytes_needed <= (size_t) newsize)
+ {
+ newbuf = realloc(conn->inBuffer, newsize);
+ if (newbuf)
+ {
+ /* realloc succeeded */
+ conn->inBuffer = newbuf;
+ conn->inBufSize = newsize;
+ return 0;
+ }
+ }
+
+ newsize = conn->inBufSize;
+ do
+ {
+ newsize += 8192;
+ } while (newsize > 0 && bytes_needed > (size_t) newsize);
+
+ if (newsize > 0 && bytes_needed <= (size_t) newsize)
+ {
+ newbuf = realloc(conn->inBuffer, newsize);
+ if (newbuf)
+ {
+ /* realloc succeeded */
+ conn->inBuffer = newbuf;
+ conn->inBufSize = newsize;
+ return 0;
+ }
+ }
+
+ /* realloc failed. Probably out of memory */
+ appendPQExpBufferStr(&conn->errorMessage,
+ "cannot allocate memory for input buffer\n");
+ return EOF;
+}
+
+/*
+ * pqPutMsgStart: begin construction of a message to the server
+ *
+ * msg_type is the message type byte, or 0 for a message without type byte
+ * (only startup messages have no type byte)
+ *
+ * Returns 0 on success, EOF on error
+ *
+ * The idea here is that we construct the message in conn->outBuffer,
+ * beginning just past any data already in outBuffer (ie, at
+ * outBuffer+outCount). We enlarge the buffer as needed to hold the message.
+ * When the message is complete, we fill in the length word (if needed) and
+ * then advance outCount past the message, making it eligible to send.
+ *
+ * The state variable conn->outMsgStart points to the incomplete message's
+ * length word: it is either outCount or outCount+1 depending on whether
+ * there is a type byte. The state variable conn->outMsgEnd is the end of
+ * the data collected so far.
+ */
+int
+pqPutMsgStart(char msg_type, PGconn *conn)
+{
+ int lenPos;
+ int endPos;
+
+ /* allow room for message type byte */
+ if (msg_type)
+ endPos = conn->outCount + 1;
+ else
+ endPos = conn->outCount;
+
+ /* do we want a length word? */
+ lenPos = endPos;
+ /* allow room for message length */
+ endPos += 4;
+
+ /* make sure there is room for message header */
+ if (pqCheckOutBufferSpace(endPos, conn))
+ return EOF;
+ /* okay, save the message type byte if any */
+ if (msg_type)
+ conn->outBuffer[conn->outCount] = msg_type;
+ /* set up the message pointers */
+ conn->outMsgStart = lenPos;
+ conn->outMsgEnd = endPos;
+ /* length word, if needed, will be filled in by pqPutMsgEnd */
+
+ return 0;
+}
+
+/*
+ * pqPutMsgBytes: add bytes to a partially-constructed message
+ *
+ * Returns 0 on success, EOF on error
+ */
+static int
+pqPutMsgBytes(const void *buf, size_t len, PGconn *conn)
+{
+ /* make sure there is room for it */
+ if (pqCheckOutBufferSpace(conn->outMsgEnd + len, conn))
+ return EOF;
+ /* okay, save the data */
+ memcpy(conn->outBuffer + conn->outMsgEnd, buf, len);
+ conn->outMsgEnd += len;
+ /* no Pfdebug call here, caller should do it */
+ return 0;
+}
+
+/*
+ * pqPutMsgEnd: finish constructing a message and possibly send it
+ *
+ * Returns 0 on success, EOF on error
+ *
+ * We don't actually send anything here unless we've accumulated at least
+ * 8K worth of data (the typical size of a pipe buffer on Unix systems).
+ * This avoids sending small partial packets. The caller must use pqFlush
+ * when it's important to flush all the data out to the server.
+ */
+int
+pqPutMsgEnd(PGconn *conn)
+{
+ /* Fill in length word if needed */
+ if (conn->outMsgStart >= 0)
+ {
+ uint32 msgLen = conn->outMsgEnd - conn->outMsgStart;
+
+ msgLen = pg_hton32(msgLen);
+ memcpy(conn->outBuffer + conn->outMsgStart, &msgLen, 4);
+ }
+
+ /* trace client-to-server message */
+ if (conn->Pfdebug)
+ {
+ if (conn->outCount < conn->outMsgStart)
+ pqTraceOutputMessage(conn, conn->outBuffer + conn->outCount, true);
+ else
+ pqTraceOutputNoTypeByteMessage(conn,
+ conn->outBuffer + conn->outMsgStart);
+ }
+
+ /* Make message eligible to send */
+ conn->outCount = conn->outMsgEnd;
+
+ if (conn->outCount >= 8192)
+ {
+ int toSend = conn->outCount - (conn->outCount % 8192);
+
+ if (pqSendSome(conn, toSend) < 0)
+ return EOF;
+ /* in nonblock mode, don't complain if unable to send it all */
+ }
+
+ return 0;
+}
+
+/* ----------
+ * pqReadData: read more data, if any is available
+ * Possible return values:
+ * 1: successfully loaded at least one more byte
+ * 0: no data is presently available, but no error detected
+ * -1: error detected (including EOF = connection closure);
+ * conn->errorMessage set
+ * NOTE: callers must not assume that pointers or indexes into conn->inBuffer
+ * remain valid across this call!
+ * ----------
+ */
+int
+pqReadData(PGconn *conn)
+{
+ int someread = 0;
+ int nread;
+
+ if (conn->sock == PGINVALID_SOCKET)
+ {
+ libpq_append_conn_error(conn, "connection not open");
+ return -1;
+ }
+
+ /* Left-justify any data in the buffer to make room */
+ if (conn->inStart < conn->inEnd)
+ {
+ if (conn->inStart > 0)
+ {
+ memmove(conn->inBuffer, conn->inBuffer + conn->inStart,
+ conn->inEnd - conn->inStart);
+ conn->inEnd -= conn->inStart;
+ conn->inCursor -= conn->inStart;
+ conn->inStart = 0;
+ }
+ }
+ else
+ {
+ /* buffer is logically empty, reset it */
+ conn->inStart = conn->inCursor = conn->inEnd = 0;
+ }
+
+ /*
+ * If the buffer is fairly full, enlarge it. We need to be able to enlarge
+ * the buffer in case a single message exceeds the initial buffer size. We
+ * enlarge before filling the buffer entirely so as to avoid asking the
+ * kernel for a partial packet. The magic constant here should be large
+ * enough for a TCP packet or Unix pipe bufferload. 8K is the usual pipe
+ * buffer size, so...
+ */
+ if (conn->inBufSize - conn->inEnd < 8192)
+ {
+ if (pqCheckInBufferSpace(conn->inEnd + (size_t) 8192, conn))
+ {
+ /*
+ * We don't insist that the enlarge worked, but we need some room
+ */
+ if (conn->inBufSize - conn->inEnd < 100)
+ return -1; /* errorMessage already set */
+ }
+ }
+
+ /* OK, try to read some data */
+retry3:
+ nread = pqsecure_read(conn, conn->inBuffer + conn->inEnd,
+ conn->inBufSize - conn->inEnd);
+ if (nread < 0)
+ {
+ switch (SOCK_ERRNO)
+ {
+ case EINTR:
+ goto retry3;
+
+ /* Some systems return EAGAIN/EWOULDBLOCK for no data */
+#ifdef EAGAIN
+ case EAGAIN:
+ return someread;
+#endif
+#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
+ case EWOULDBLOCK:
+ return someread;
+#endif
+
+ /* We might get ECONNRESET etc here if connection failed */
+ case ALL_CONNECTION_FAILURE_ERRNOS:
+ goto definitelyFailed;
+
+ default:
+ /* pqsecure_read set the error message for us */
+ return -1;
+ }
+ }
+ if (nread > 0)
+ {
+ conn->inEnd += nread;
+
+ /*
+ * Hack to deal with the fact that some kernels will only give us back
+ * 1 packet per recv() call, even if we asked for more and there is
+ * more available. If it looks like we are reading a long message,
+ * loop back to recv() again immediately, until we run out of data or
+ * buffer space. Without this, the block-and-restart behavior of
+ * libpq's higher levels leads to O(N^2) performance on long messages.
+ *
+ * Since we left-justified the data above, conn->inEnd gives the
+ * amount of data already read in the current message. We consider
+ * the message "long" once we have acquired 32k ...
+ */
+ if (conn->inEnd > 32768 &&
+ (conn->inBufSize - conn->inEnd) >= 8192)
+ {
+ someread = 1;
+ goto retry3;
+ }
+ return 1;
+ }
+
+ if (someread)
+ return 1; /* got a zero read after successful tries */
+
+ /*
+ * A return value of 0 could mean just that no data is now available, or
+ * it could mean EOF --- that is, the server has closed the connection.
+ * Since we have the socket in nonblock mode, the only way to tell the
+ * difference is to see if select() is saying that the file is ready.
+ * Grumble. Fortunately, we don't expect this path to be taken much,
+ * since in normal practice we should not be trying to read data unless
+ * the file selected for reading already.
+ *
+ * In SSL mode it's even worse: SSL_read() could say WANT_READ and then
+ * data could arrive before we make the pqReadReady() test, but the second
+ * SSL_read() could still say WANT_READ because the data received was not
+ * a complete SSL record. So we must play dumb and assume there is more
+ * data, relying on the SSL layer to detect true EOF.
+ */
+
+#ifdef USE_SSL
+ if (conn->ssl_in_use)
+ return 0;
+#endif
+
+ switch (pqReadReady(conn))
+ {
+ case 0:
+ /* definitely no data available */
+ return 0;
+ case 1:
+ /* ready for read */
+ break;
+ default:
+ /* we override pqReadReady's message with something more useful */
+ goto definitelyEOF;
+ }
+
+ /*
+ * Still not sure that it's EOF, because some data could have just
+ * arrived.
+ */
+retry4:
+ nread = pqsecure_read(conn, conn->inBuffer + conn->inEnd,
+ conn->inBufSize - conn->inEnd);
+ if (nread < 0)
+ {
+ switch (SOCK_ERRNO)
+ {
+ case EINTR:
+ goto retry4;
+
+ /* Some systems return EAGAIN/EWOULDBLOCK for no data */
+#ifdef EAGAIN
+ case EAGAIN:
+ return 0;
+#endif
+#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
+ case EWOULDBLOCK:
+ return 0;
+#endif
+
+ /* We might get ECONNRESET etc here if connection failed */
+ case ALL_CONNECTION_FAILURE_ERRNOS:
+ goto definitelyFailed;
+
+ default:
+ /* pqsecure_read set the error message for us */
+ return -1;
+ }
+ }
+ if (nread > 0)
+ {
+ conn->inEnd += nread;
+ return 1;
+ }
+
+ /*
+ * OK, we are getting a zero read even though select() says ready. This
+ * means the connection has been closed. Cope.
+ */
+definitelyEOF:
+ libpq_append_conn_error(conn, "server closed the connection unexpectedly\n"
+ "\tThis probably means the server terminated abnormally\n"
+ "\tbefore or while processing the request.");
+
+ /* Come here if lower-level code already set a suitable errorMessage */
+definitelyFailed:
+ /* Do *not* drop any already-read data; caller still wants it */
+ pqDropConnection(conn, false);
+ conn->status = CONNECTION_BAD; /* No more connection to backend */
+ return -1;
+}
+
+/*
+ * pqSendSome: send data waiting in the output buffer.
+ *
+ * len is how much to try to send (typically equal to outCount, but may
+ * be less).
+ *
+ * Return 0 on success, -1 on failure and 1 when not all data could be sent
+ * because the socket would block and the connection is non-blocking.
+ *
+ * Note that this is also responsible for consuming data from the socket
+ * (putting it in conn->inBuffer) in any situation where we can't send
+ * all the specified data immediately.
+ *
+ * If a socket-level write failure occurs, conn->write_failed is set and the
+ * error message is saved in conn->write_err_msg, but we clear the output
+ * buffer and return zero anyway; this is because callers should soldier on
+ * until we have read what we can from the server and checked for an error
+ * message. write_err_msg should be reported only when we are unable to
+ * obtain a server error first. Much of that behavior is implemented at
+ * lower levels, but this function deals with some edge cases.
+ */
+static int
+pqSendSome(PGconn *conn, int len)
+{
+ char *ptr = conn->outBuffer;
+ int remaining = conn->outCount;
+ int result = 0;
+
+ /*
+ * If we already had a write failure, we will never again try to send data
+ * on that connection. Even if the kernel would let us, we've probably
+ * lost message boundary sync with the server. conn->write_failed
+ * therefore persists until the connection is reset, and we just discard
+ * all data presented to be written. However, as long as we still have a
+ * valid socket, we should continue to absorb data from the backend, so
+ * that we can collect any final error messages.
+ */
+ if (conn->write_failed)
+ {
+ /* conn->write_err_msg should be set up already */
+ conn->outCount = 0;
+ /* Absorb input data if any, and detect socket closure */
+ if (conn->sock != PGINVALID_SOCKET)
+ {
+ if (pqReadData(conn) < 0)
+ return -1;
+ }
+ return 0;
+ }
+
+ if (conn->sock == PGINVALID_SOCKET)
+ {
+ conn->write_failed = true;
+ /* Store error message in conn->write_err_msg, if possible */
+ /* (strdup failure is OK, we'll cope later) */
+ conn->write_err_msg = strdup(libpq_gettext("connection not open\n"));
+ /* Discard queued data; no chance it'll ever be sent */
+ conn->outCount = 0;
+ return 0;
+ }
+
+ /* while there's still data to send */
+ while (len > 0)
+ {
+ int sent;
+
+#ifndef WIN32
+ sent = pqsecure_write(conn, ptr, len);
+#else
+
+ /*
+ * Windows can fail on large sends, per KB article Q201213. The
+ * failure-point appears to be different in different versions of
+ * Windows, but 64k should always be safe.
+ */
+ sent = pqsecure_write(conn, ptr, Min(len, 65536));
+#endif
+
+ if (sent < 0)
+ {
+ /* Anything except EAGAIN/EWOULDBLOCK/EINTR is trouble */
+ switch (SOCK_ERRNO)
+ {
+#ifdef EAGAIN
+ case EAGAIN:
+ break;
+#endif
+#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
+ case EWOULDBLOCK:
+ break;
+#endif
+ case EINTR:
+ continue;
+
+ default:
+ /* Discard queued data; no chance it'll ever be sent */
+ conn->outCount = 0;
+
+ /* Absorb input data if any, and detect socket closure */
+ if (conn->sock != PGINVALID_SOCKET)
+ {
+ if (pqReadData(conn) < 0)
+ return -1;
+ }
+
+ /*
+ * Lower-level code should already have filled
+ * conn->write_err_msg (and set conn->write_failed) or
+ * conn->errorMessage. In the former case, we pretend
+ * there's no problem; the write_failed condition will be
+ * dealt with later. Otherwise, report the error now.
+ */
+ if (conn->write_failed)
+ return 0;
+ else
+ return -1;
+ }
+ }
+ else
+ {
+ ptr += sent;
+ len -= sent;
+ remaining -= sent;
+ }
+
+ if (len > 0)
+ {
+ /*
+ * We didn't send it all, wait till we can send more.
+ *
+ * There are scenarios in which we can't send data because the
+ * communications channel is full, but we cannot expect the server
+ * to clear the channel eventually because it's blocked trying to
+ * send data to us. (This can happen when we are sending a large
+ * amount of COPY data, and the server has generated lots of
+ * NOTICE responses.) To avoid a deadlock situation, we must be
+ * prepared to accept and buffer incoming data before we try
+ * again. Furthermore, it is possible that such incoming data
+ * might not arrive until after we've gone to sleep. Therefore,
+ * we wait for either read ready or write ready.
+ *
+ * In non-blocking mode, we don't wait here directly, but return 1
+ * to indicate that data is still pending. The caller should wait
+ * for both read and write ready conditions, and call
+ * PQconsumeInput() on read ready, but just in case it doesn't, we
+ * call pqReadData() ourselves before returning. That's not
+ * enough if the data has not arrived yet, but it's the best we
+ * can do, and works pretty well in practice. (The documentation
+ * used to say that you only need to wait for write-ready, so
+ * there are still plenty of applications like that out there.)
+ *
+ * Note that errors here don't result in write_failed becoming
+ * set.
+ */
+ if (pqReadData(conn) < 0)
+ {
+ result = -1; /* error message already set up */
+ break;
+ }
+
+ if (pqIsnonblocking(conn))
+ {
+ result = 1;
+ break;
+ }
+
+ if (pqWait(true, true, conn))
+ {
+ result = -1;
+ break;
+ }
+ }
+ }
+
+ /* shift the remaining contents of the buffer */
+ if (remaining > 0)
+ memmove(conn->outBuffer, ptr, remaining);
+ conn->outCount = remaining;
+
+ return result;
+}
+
+
+/*
+ * pqFlush: send any data waiting in the output buffer
+ *
+ * Return 0 on success, -1 on failure and 1 when not all data could be sent
+ * because the socket would block and the connection is non-blocking.
+ * (See pqSendSome comments about how failure should be handled.)
+ */
+int
+pqFlush(PGconn *conn)
+{
+ if (conn->outCount > 0)
+ {
+ if (conn->Pfdebug)
+ fflush(conn->Pfdebug);
+
+ return pqSendSome(conn, conn->outCount);
+ }
+
+ return 0;
+}
+
+
+/*
+ * pqWait: wait until we can read or write the connection socket
+ *
+ * JAB: If SSL enabled and used and forRead, buffered bytes short-circuit the
+ * call to select().
+ *
+ * We also stop waiting and return if the kernel flags an exception condition
+ * on the socket. The actual error condition will be detected and reported
+ * when the caller tries to read or write the socket.
+ */
+int
+pqWait(int forRead, int forWrite, PGconn *conn)
+{
+ return pqWaitTimed(forRead, forWrite, conn, (time_t) -1);
+}
+
+/*
+ * pqWaitTimed: wait, but not past finish_time.
+ *
+ * finish_time = ((time_t) -1) disables the wait limit.
+ *
+ * Returns -1 on failure, 0 if the socket is readable/writable, 1 if it timed out.
+ */
+int
+pqWaitTimed(int forRead, int forWrite, PGconn *conn, time_t finish_time)
+{
+ int result;
+
+ result = pqSocketCheck(conn, forRead, forWrite, finish_time);
+
+ if (result < 0)
+ return -1; /* errorMessage is already set */
+
+ if (result == 0)
+ {
+ libpq_append_conn_error(conn, "timeout expired");
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * pqReadReady: is select() saying the file is ready to read?
+ * Returns -1 on failure, 0 if not ready, 1 if ready.
+ */
+int
+pqReadReady(PGconn *conn)
+{
+ return pqSocketCheck(conn, 1, 0, (time_t) 0);
+}
+
+/*
+ * pqWriteReady: is select() saying the file is ready to write?
+ * Returns -1 on failure, 0 if not ready, 1 if ready.
+ */
+int
+pqWriteReady(PGconn *conn)
+{
+ return pqSocketCheck(conn, 0, 1, (time_t) 0);
+}
+
+/*
+ * Checks a socket, using poll or select, for data to be read, written,
+ * or both. Returns >0 if one or more conditions are met, 0 if it timed
+ * out, -1 if an error occurred.
+ *
+ * If SSL is in use, the SSL buffer is checked prior to checking the socket
+ * for read data directly.
+ */
+static int
+pqSocketCheck(PGconn *conn, int forRead, int forWrite, time_t end_time)
+{
+ int result;
+
+ if (!conn)
+ return -1;
+ if (conn->sock == PGINVALID_SOCKET)
+ {
+ libpq_append_conn_error(conn, "invalid socket");
+ return -1;
+ }
+
+#ifdef USE_SSL
+ /* Check for SSL library buffering read bytes */
+ if (forRead && conn->ssl_in_use && pgtls_read_pending(conn))
+ {
+ /* short-circuit the select */
+ return 1;
+ }
+#endif
+
+ /* We will retry as long as we get EINTR */
+ do
+ result = pqSocketPoll(conn->sock, forRead, forWrite, end_time);
+ while (result < 0 && SOCK_ERRNO == EINTR);
+
+ if (result < 0)
+ {
+ char sebuf[PG_STRERROR_R_BUFLEN];
+
+ libpq_append_conn_error(conn, "%s() failed: %s", "select",
+ SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
+ }
+
+ return result;
+}
+
+
+/*
+ * Check a file descriptor for read and/or write data, possibly waiting.
+ * If neither forRead nor forWrite are set, immediately return a timeout
+ * condition (without waiting). Return >0 if condition is met, 0
+ * if a timeout occurred, -1 if an error or interrupt occurred.
+ *
+ * Timeout is infinite if end_time is -1. Timeout is immediate (no blocking)
+ * if end_time is 0 (or indeed, any time before now).
+ */
+static int
+pqSocketPoll(int sock, int forRead, int forWrite, time_t end_time)
+{
+ /* We use poll(2) if available, otherwise select(2) */
+#ifdef HAVE_POLL
+ struct pollfd input_fd;
+ int timeout_ms;
+
+ if (!forRead && !forWrite)
+ return 0;
+
+ input_fd.fd = sock;
+ input_fd.events = POLLERR;
+ input_fd.revents = 0;
+
+ if (forRead)
+ input_fd.events |= POLLIN;
+ if (forWrite)
+ input_fd.events |= POLLOUT;
+
+ /* Compute appropriate timeout interval */
+ if (end_time == ((time_t) -1))
+ timeout_ms = -1;
+ else
+ {
+ time_t now = time(NULL);
+
+ if (end_time > now)
+ timeout_ms = (end_time - now) * 1000;
+ else
+ timeout_ms = 0;
+ }
+
+ return poll(&input_fd, 1, timeout_ms);
+#else /* !HAVE_POLL */
+
+ fd_set input_mask;
+ fd_set output_mask;
+ fd_set except_mask;
+ struct timeval timeout;
+ struct timeval *ptr_timeout;
+
+ if (!forRead && !forWrite)
+ return 0;
+
+ FD_ZERO(&input_mask);
+ FD_ZERO(&output_mask);
+ FD_ZERO(&except_mask);
+ if (forRead)
+ FD_SET(sock, &input_mask);
+
+ if (forWrite)
+ FD_SET(sock, &output_mask);
+ FD_SET(sock, &except_mask);
+
+ /* Compute appropriate timeout interval */
+ if (end_time == ((time_t) -1))
+ ptr_timeout = NULL;
+ else
+ {
+ time_t now = time(NULL);
+
+ if (end_time > now)
+ timeout.tv_sec = end_time - now;
+ else
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 0;
+ ptr_timeout = &timeout;
+ }
+
+ return select(sock + 1, &input_mask, &output_mask,
+ &except_mask, ptr_timeout);
+#endif /* HAVE_POLL */
+}
+
+
+/*
+ * A couple of "miscellaneous" multibyte related functions. They used
+ * to be in fe-print.c but that file is doomed.
+ */
+
+/*
+ * Returns the byte length of the character beginning at s, using the
+ * specified encoding.
+ *
+ * Caution: when dealing with text that is not certainly valid in the
+ * specified encoding, the result may exceed the actual remaining
+ * string length. Callers that are not prepared to deal with that
+ * should use PQmblenBounded() instead.
+ */
+int
+PQmblen(const char *s, int encoding)
+{
+ return pg_encoding_mblen(encoding, s);
+}
+
+/*
+ * Returns the byte length of the character beginning at s, using the
+ * specified encoding; but not more than the distance to end of string.
+ */
+int
+PQmblenBounded(const char *s, int encoding)
+{
+ return strnlen(s, pg_encoding_mblen(encoding, s));
+}
+
+/*
+ * Returns the display length of the character beginning at s, using the
+ * specified encoding.
+ */
+int
+PQdsplen(const char *s, int encoding)
+{
+ return pg_encoding_dsplen(encoding, s);
+}
+
+/*
+ * Get encoding id from environment variable PGCLIENTENCODING.
+ */
+int
+PQenv2encoding(void)
+{
+ char *str;
+ int encoding = PG_SQL_ASCII;
+
+ str = getenv("PGCLIENTENCODING");
+ if (str && *str != '\0')
+ {
+ encoding = pg_char_to_encoding(str);
+ if (encoding < 0)
+ encoding = PG_SQL_ASCII;
+ }
+ return encoding;
+}
+
+
+#ifdef ENABLE_NLS
+
+static void
+libpq_binddomain(void)
+{
+ /*
+ * If multiple threads come through here at about the same time, it's okay
+ * for more than one of them to call bindtextdomain(). But it's not okay
+ * for any of them to return to caller before bindtextdomain() is
+ * complete, so don't set the flag till that's done. Use "volatile" just
+ * to be sure the compiler doesn't try to get cute.
+ */
+ static volatile bool already_bound = false;
+
+ if (!already_bound)
+ {
+ /* bindtextdomain() does not preserve errno */
+#ifdef WIN32
+ int save_errno = GetLastError();
+#else
+ int save_errno = errno;
+#endif
+ const char *ldir;
+
+ /* No relocatable lookup here because the binary could be anywhere */
+ ldir = getenv("PGLOCALEDIR");
+ if (!ldir)
+ ldir = LOCALEDIR;
+ bindtextdomain(PG_TEXTDOMAIN("libpq"), ldir);
+ already_bound = true;
+#ifdef WIN32
+ SetLastError(save_errno);
+#else
+ errno = save_errno;
+#endif
+ }
+}
+
+char *
+libpq_gettext(const char *msgid)
+{
+ libpq_binddomain();
+ return dgettext(PG_TEXTDOMAIN("libpq"), msgid);
+}
+
+char *
+libpq_ngettext(const char *msgid, const char *msgid_plural, unsigned long n)
+{
+ libpq_binddomain();
+ return dngettext(PG_TEXTDOMAIN("libpq"), msgid, msgid_plural, n);
+}
+
+#endif /* ENABLE_NLS */
+
+
+/*
+ * Append a formatted string to the given buffer, after translating it. A
+ * newline is automatically appended; the format should not end with a
+ * newline.
+ */
+void
+libpq_append_error(PQExpBuffer errorMessage, const char *fmt,...)
+{
+ int save_errno = errno;
+ bool done;
+ va_list args;
+
+ Assert(fmt[strlen(fmt) - 1] != '\n');
+
+ if (PQExpBufferBroken(errorMessage))
+ return; /* already failed */
+
+ /* Loop in case we have to retry after enlarging the buffer. */
+ do
+ {
+ errno = save_errno;
+ va_start(args, fmt);
+ done = appendPQExpBufferVA(errorMessage, libpq_gettext(fmt), args);
+ va_end(args);
+ } while (!done);
+
+ appendPQExpBufferChar(errorMessage, '\n');
+}
+
+/*
+ * Append a formatted string to the error message buffer of the given
+ * connection, after translating it. A newline is automatically appended; the
+ * format should not end with a newline.
+ */
+void
+libpq_append_conn_error(PGconn *conn, const char *fmt,...)
+{
+ int save_errno = errno;
+ bool done;
+ va_list args;
+
+ Assert(fmt[strlen(fmt) - 1] != '\n');
+
+ if (PQExpBufferBroken(&conn->errorMessage))
+ return; /* already failed */
+
+ /* Loop in case we have to retry after enlarging the buffer. */
+ do
+ {
+ errno = save_errno;
+ va_start(args, fmt);
+ done = appendPQExpBufferVA(&conn->errorMessage, libpq_gettext(fmt), args);
+ va_end(args);
+ } while (!done);
+
+ appendPQExpBufferChar(&conn->errorMessage, '\n');
+}
diff --git a/contrib/libs/libpq/src/interfaces/libpq/fe-print.c b/contrib/libs/libpq/src/interfaces/libpq/fe-print.c
new file mode 100644
index 0000000000..40620b47e9
--- /dev/null
+++ b/contrib/libs/libpq/src/interfaces/libpq/fe-print.c
@@ -0,0 +1,773 @@
+/*-------------------------------------------------------------------------
+ *
+ * fe-print.c
+ * functions for pretty-printing query results
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * These functions were formerly part of fe-exec.c, but they
+ * didn't really belong there.
+ *
+ * IDENTIFICATION
+ * src/interfaces/libpq/fe-print.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres_fe.h"
+
+#include <signal.h>
+
+#ifdef WIN32
+#include "win32.h"
+#else
+#include <unistd.h>
+#include <sys/ioctl.h>
+#endif
+
+#ifdef HAVE_TERMIOS_H
+#include <termios.h>
+#else
+#ifndef WIN32
+#include <sys/termios.h>
+#endif
+#endif
+
+#include "libpq-fe.h"
+#include "libpq-int.h"
+
+
+static bool do_field(const PQprintOpt *po, const PGresult *res,
+ const int i, const int j, const int fs_len,
+ char **fields,
+ const int nFields, const char **fieldNames,
+ unsigned char *fieldNotNum, int *fieldMax,
+ const int fieldMaxLen, FILE *fout);
+static char *do_header(FILE *fout, const PQprintOpt *po, const int nFields,
+ int *fieldMax, const char **fieldNames, unsigned char *fieldNotNum,
+ const int fs_len, const PGresult *res);
+static void output_row(FILE *fout, const PQprintOpt *po, const int nFields, char **fields,
+ unsigned char *fieldNotNum, int *fieldMax, char *border,
+ const int row_index);
+static void fill(int length, int max, char filler, FILE *fp);
+
+/*
+ * PQprint()
+ *
+ * Format results of a query for printing.
+ *
+ * PQprintOpt is a typedef (structure) that contains
+ * various flags and options. consult libpq-fe.h for
+ * details
+ *
+ * This function should probably be removed sometime since psql
+ * doesn't use it anymore. It is unclear to what extent this is used
+ * by external clients, however.
+ */
+void
+PQprint(FILE *fout, const PGresult *res, const PQprintOpt *po)
+{
+ int nFields;
+
+ nFields = PQnfields(res);
+
+ if (nFields > 0)
+ { /* only print rows with at least 1 field. */
+ int i,
+ j;
+ int nTups;
+ int *fieldMax = NULL; /* in case we don't use them */
+ unsigned char *fieldNotNum = NULL;
+ char *border = NULL;
+ char **fields = NULL;
+ const char **fieldNames = NULL;
+ int fieldMaxLen = 0;
+ int numFieldName;
+ int fs_len = strlen(po->fieldSep);
+ int total_line_length = 0;
+ bool usePipe = false;
+ char *pagerenv;
+
+#if defined(ENABLE_THREAD_SAFETY) && !defined(WIN32)
+ sigset_t osigset;
+ bool sigpipe_masked = false;
+ bool sigpipe_pending;
+#endif
+#if !defined(ENABLE_THREAD_SAFETY) && !defined(WIN32)
+ pqsigfunc oldsigpipehandler = NULL;
+#endif
+
+#ifdef TIOCGWINSZ
+ struct winsize screen_size;
+#else
+ struct winsize
+ {
+ int ws_row;
+ int ws_col;
+ } screen_size;
+#endif
+
+ nTups = PQntuples(res);
+ fieldNames = (const char **) calloc(nFields, sizeof(char *));
+ fieldNotNum = (unsigned char *) calloc(nFields, 1);
+ fieldMax = (int *) calloc(nFields, sizeof(int));
+ if (!fieldNames || !fieldNotNum || !fieldMax)
+ {
+ fprintf(stderr, libpq_gettext("out of memory\n"));
+ goto exit;
+ }
+ for (numFieldName = 0;
+ po->fieldName && po->fieldName[numFieldName];
+ numFieldName++)
+ ;
+ for (j = 0; j < nFields; j++)
+ {
+ int len;
+ const char *s = (j < numFieldName && po->fieldName[j][0]) ?
+ po->fieldName[j] : PQfname(res, j);
+
+ fieldNames[j] = s;
+ len = s ? strlen(s) : 0;
+ fieldMax[j] = len;
+ len += fs_len;
+ if (len > fieldMaxLen)
+ fieldMaxLen = len;
+ total_line_length += len;
+ }
+
+ total_line_length += nFields * strlen(po->fieldSep) + 1;
+
+ if (fout == NULL)
+ fout = stdout;
+ if (po->pager && fout == stdout && isatty(fileno(stdin)) &&
+ isatty(fileno(stdout)))
+ {
+ /*
+ * If we think there'll be more than one screen of output, try to
+ * pipe to the pager program.
+ */
+#ifdef TIOCGWINSZ
+ if (ioctl(fileno(stdout), TIOCGWINSZ, &screen_size) == -1 ||
+ screen_size.ws_col == 0 ||
+ screen_size.ws_row == 0)
+ {
+ screen_size.ws_row = 24;
+ screen_size.ws_col = 80;
+ }
+#else
+ screen_size.ws_row = 24;
+ screen_size.ws_col = 80;
+#endif
+
+ /*
+ * Since this function is no longer used by psql, we don't examine
+ * PSQL_PAGER. It's possible that the hypothetical external users
+ * of the function would like that to happen, but in the name of
+ * backwards compatibility, we'll stick to just examining PAGER.
+ */
+ pagerenv = getenv("PAGER");
+ /* if PAGER is unset, empty or all-white-space, don't use pager */
+ if (pagerenv != NULL &&
+ strspn(pagerenv, " \t\r\n") != strlen(pagerenv) &&
+ !po->html3 &&
+ ((po->expanded &&
+ nTups * (nFields + 1) >= screen_size.ws_row) ||
+ (!po->expanded &&
+ nTups * (total_line_length / screen_size.ws_col + 1) *
+ (1 + (po->standard != 0)) >= screen_size.ws_row -
+ (po->header != 0) *
+ (total_line_length / screen_size.ws_col + 1) * 2
+ - (po->header != 0) * 2 /* row count and newline */
+ )))
+ {
+ fflush(NULL);
+ fout = popen(pagerenv, "w");
+ if (fout)
+ {
+ usePipe = true;
+#ifndef WIN32
+#ifdef ENABLE_THREAD_SAFETY
+ if (pq_block_sigpipe(&osigset, &sigpipe_pending) == 0)
+ sigpipe_masked = true;
+#else
+ oldsigpipehandler = pqsignal(SIGPIPE, SIG_IGN);
+#endif /* ENABLE_THREAD_SAFETY */
+#endif /* WIN32 */
+ }
+ else
+ fout = stdout;
+ }
+ }
+
+ if (!po->expanded && (po->align || po->html3))
+ {
+ fields = (char **) calloc((size_t) nTups + 1,
+ nFields * sizeof(char *));
+ if (!fields)
+ {
+ fprintf(stderr, libpq_gettext("out of memory\n"));
+ goto exit;
+ }
+ }
+ else if (po->header && !po->html3)
+ {
+ if (po->expanded)
+ {
+ if (po->align)
+ fprintf(fout, libpq_gettext("%-*s%s Value\n"),
+ fieldMaxLen - fs_len, libpq_gettext("Field"), po->fieldSep);
+ else
+ fprintf(fout, libpq_gettext("%s%sValue\n"), libpq_gettext("Field"), po->fieldSep);
+ }
+ else
+ {
+ int len = 0;
+
+ for (j = 0; j < nFields; j++)
+ {
+ const char *s = fieldNames[j];
+
+ fputs(s, fout);
+ len += strlen(s) + fs_len;
+ if ((j + 1) < nFields)
+ fputs(po->fieldSep, fout);
+ }
+ fputc('\n', fout);
+ for (len -= fs_len; len--; fputc('-', fout));
+ fputc('\n', fout);
+ }
+ }
+ if (po->expanded && po->html3)
+ {
+ if (po->caption)
+ fprintf(fout, "<center><h2>%s</h2></center>\n", po->caption);
+ else
+ fprintf(fout,
+ "<center><h2>"
+ "Query retrieved %d rows * %d fields"
+ "</h2></center>\n",
+ nTups, nFields);
+ }
+ for (i = 0; i < nTups; i++)
+ {
+ if (po->expanded)
+ {
+ if (po->html3)
+ fprintf(fout,
+ "<table %s><caption align=\"top\">%d</caption>\n",
+ po->tableOpt ? po->tableOpt : "", i);
+ else
+ fprintf(fout, libpq_gettext("-- RECORD %d --\n"), i);
+ }
+ for (j = 0; j < nFields; j++)
+ {
+ if (!do_field(po, res, i, j, fs_len, fields, nFields,
+ fieldNames, fieldNotNum,
+ fieldMax, fieldMaxLen, fout))
+ goto exit;
+ }
+ if (po->html3 && po->expanded)
+ fputs("</table>\n", fout);
+ }
+ if (!po->expanded && (po->align || po->html3))
+ {
+ if (po->html3)
+ {
+ if (po->header)
+ {
+ if (po->caption)
+ fprintf(fout,
+ "<table %s><caption align=\"top\">%s</caption>\n",
+ po->tableOpt ? po->tableOpt : "",
+ po->caption);
+ else
+ fprintf(fout,
+ "<table %s><caption align=\"top\">"
+ "Retrieved %d rows * %d fields"
+ "</caption>\n",
+ po->tableOpt ? po->tableOpt : "", nTups, nFields);
+ }
+ else
+ fprintf(fout, "<table %s>", po->tableOpt ? po->tableOpt : "");
+ }
+ if (po->header)
+ border = do_header(fout, po, nFields, fieldMax, fieldNames,
+ fieldNotNum, fs_len, res);
+ for (i = 0; i < nTups; i++)
+ output_row(fout, po, nFields, fields,
+ fieldNotNum, fieldMax, border, i);
+ }
+ if (po->header && !po->html3)
+ fprintf(fout, "(%d row%s)\n\n", PQntuples(res),
+ (PQntuples(res) == 1) ? "" : "s");
+ if (po->html3 && !po->expanded)
+ fputs("</table>\n", fout);
+
+exit:
+ free(fieldMax);
+ free(fieldNotNum);
+ free(border);
+ if (fields)
+ {
+ /* if calloc succeeded, this shouldn't overflow size_t */
+ size_t numfields = ((size_t) nTups + 1) * (size_t) nFields;
+
+ while (numfields-- > 0)
+ free(fields[numfields]);
+ free(fields);
+ }
+ free(fieldNames);
+ if (usePipe)
+ {
+#ifdef WIN32
+ _pclose(fout);
+#else
+ pclose(fout);
+
+#ifdef ENABLE_THREAD_SAFETY
+ /* we can't easily verify if EPIPE occurred, so say it did */
+ if (sigpipe_masked)
+ pq_reset_sigpipe(&osigset, sigpipe_pending, true);
+#else
+ pqsignal(SIGPIPE, oldsigpipehandler);
+#endif /* ENABLE_THREAD_SAFETY */
+#endif /* WIN32 */
+ }
+ }
+}
+
+
+static bool
+do_field(const PQprintOpt *po, const PGresult *res,
+ const int i, const int j, const int fs_len,
+ char **fields,
+ const int nFields, char const **fieldNames,
+ unsigned char *fieldNotNum, int *fieldMax,
+ const int fieldMaxLen, FILE *fout)
+{
+ const char *pval,
+ *p;
+ int plen;
+ bool skipit;
+
+ plen = PQgetlength(res, i, j);
+ pval = PQgetvalue(res, i, j);
+
+ if (plen < 1 || !pval || !*pval)
+ {
+ if (po->align || po->expanded)
+ skipit = true;
+ else
+ {
+ skipit = false;
+ goto efield;
+ }
+ }
+ else
+ skipit = false;
+
+ if (!skipit)
+ {
+ if (po->align && !fieldNotNum[j])
+ {
+ /* Detect whether field contains non-numeric data */
+ char ch = '0';
+
+ for (p = pval; *p; p += PQmblenBounded(p, res->client_encoding))
+ {
+ ch = *p;
+ if (!((ch >= '0' && ch <= '9') ||
+ ch == '.' ||
+ ch == 'E' ||
+ ch == 'e' ||
+ ch == ' ' ||
+ ch == '-'))
+ {
+ fieldNotNum[j] = 1;
+ break;
+ }
+ }
+
+ /*
+ * Above loop will believe E in first column is numeric; also, we
+ * insist on a digit in the last column for a numeric. This test
+ * is still not bulletproof but it handles most cases.
+ */
+ if (*pval == 'E' || *pval == 'e' ||
+ !(ch >= '0' && ch <= '9'))
+ fieldNotNum[j] = 1;
+ }
+
+ if (!po->expanded && (po->align || po->html3))
+ {
+ if (plen > fieldMax[j])
+ fieldMax[j] = plen;
+ if (!(fields[i * nFields + j] = (char *) malloc(plen + 1)))
+ {
+ fprintf(stderr, libpq_gettext("out of memory\n"));
+ return false;
+ }
+ strcpy(fields[i * nFields + j], pval);
+ }
+ else
+ {
+ if (po->expanded)
+ {
+ if (po->html3)
+ fprintf(fout,
+ "<tr><td align=\"left\"><b>%s</b></td>"
+ "<td align=\"%s\">%s</td></tr>\n",
+ fieldNames[j],
+ fieldNotNum[j] ? "left" : "right",
+ pval);
+ else
+ {
+ if (po->align)
+ fprintf(fout,
+ "%-*s%s %s\n",
+ fieldMaxLen - fs_len, fieldNames[j],
+ po->fieldSep,
+ pval);
+ else
+ fprintf(fout,
+ "%s%s%s\n",
+ fieldNames[j], po->fieldSep, pval);
+ }
+ }
+ else
+ {
+ if (!po->html3)
+ {
+ fputs(pval, fout);
+ efield:
+ if ((j + 1) < nFields)
+ fputs(po->fieldSep, fout);
+ else
+ fputc('\n', fout);
+ }
+ }
+ }
+ }
+ return true;
+}
+
+
+static char *
+do_header(FILE *fout, const PQprintOpt *po, const int nFields, int *fieldMax,
+ const char **fieldNames, unsigned char *fieldNotNum,
+ const int fs_len, const PGresult *res)
+{
+ int j; /* for loop index */
+ char *border = NULL;
+
+ if (po->html3)
+ fputs("<tr>", fout);
+ else
+ {
+ int tot = 0;
+ int n = 0;
+ char *p = NULL;
+
+ for (; n < nFields; n++)
+ tot += fieldMax[n] + fs_len + (po->standard ? 2 : 0);
+ if (po->standard)
+ tot += fs_len * 2 + 2;
+ border = malloc(tot + 1);
+ if (!border)
+ {
+ fprintf(stderr, libpq_gettext("out of memory\n"));
+ return NULL;
+ }
+ p = border;
+ if (po->standard)
+ {
+ char *fs = po->fieldSep;
+
+ while (*fs++)
+ *p++ = '+';
+ }
+ for (j = 0; j < nFields; j++)
+ {
+ int len;
+
+ for (len = fieldMax[j] + (po->standard ? 2 : 0); len--; *p++ = '-');
+ if (po->standard || (j + 1) < nFields)
+ {
+ char *fs = po->fieldSep;
+
+ while (*fs++)
+ *p++ = '+';
+ }
+ }
+ *p = '\0';
+ if (po->standard)
+ fprintf(fout, "%s\n", border);
+ }
+ if (po->standard)
+ fputs(po->fieldSep, fout);
+ for (j = 0; j < nFields; j++)
+ {
+ const char *s = PQfname(res, j);
+
+ if (po->html3)
+ {
+ fprintf(fout, "<th align=\"%s\">%s</th>",
+ fieldNotNum[j] ? "left" : "right", fieldNames[j]);
+ }
+ else
+ {
+ int n = strlen(s);
+
+ if (n > fieldMax[j])
+ fieldMax[j] = n;
+ if (po->standard)
+ fprintf(fout,
+ fieldNotNum[j] ? " %-*s " : " %*s ",
+ fieldMax[j], s);
+ else
+ fprintf(fout, fieldNotNum[j] ? "%-*s" : "%*s", fieldMax[j], s);
+ if (po->standard || (j + 1) < nFields)
+ fputs(po->fieldSep, fout);
+ }
+ }
+ if (po->html3)
+ fputs("</tr>\n", fout);
+ else
+ fprintf(fout, "\n%s\n", border);
+ return border;
+}
+
+
+static void
+output_row(FILE *fout, const PQprintOpt *po, const int nFields, char **fields,
+ unsigned char *fieldNotNum, int *fieldMax, char *border,
+ const int row_index)
+{
+ int field_index; /* for loop index */
+
+ if (po->html3)
+ fputs("<tr>", fout);
+ else if (po->standard)
+ fputs(po->fieldSep, fout);
+ for (field_index = 0; field_index < nFields; field_index++)
+ {
+ char *p = fields[row_index * nFields + field_index];
+
+ if (po->html3)
+ fprintf(fout, "<td align=\"%s\">%s</td>",
+ fieldNotNum[field_index] ? "left" : "right", p ? p : "");
+ else
+ {
+ fprintf(fout,
+ fieldNotNum[field_index] ?
+ (po->standard ? " %-*s " : "%-*s") :
+ (po->standard ? " %*s " : "%*s"),
+ fieldMax[field_index],
+ p ? p : "");
+ if (po->standard || field_index + 1 < nFields)
+ fputs(po->fieldSep, fout);
+ }
+ }
+ if (po->html3)
+ fputs("</tr>", fout);
+ else if (po->standard)
+ fprintf(fout, "\n%s", border);
+ fputc('\n', fout);
+}
+
+
+
+/*
+ * really old printing routines
+ */
+
+void
+PQdisplayTuples(const PGresult *res,
+ FILE *fp, /* where to send the output */
+ int fillAlign, /* pad the fields with spaces */
+ const char *fieldSep, /* field separator */
+ int printHeader, /* display headers? */
+ int quiet
+)
+{
+#define DEFAULT_FIELD_SEP " "
+
+ int i,
+ j;
+ int nFields;
+ int nTuples;
+ int *fLength = NULL;
+
+ if (fieldSep == NULL)
+ fieldSep = DEFAULT_FIELD_SEP;
+
+ /* Get some useful info about the results */
+ nFields = PQnfields(res);
+ nTuples = PQntuples(res);
+
+ if (fp == NULL)
+ fp = stdout;
+
+ /* Figure the field lengths to align to */
+ /* will be somewhat time consuming for very large results */
+ if (fillAlign)
+ {
+ fLength = (int *) malloc(nFields * sizeof(int));
+ if (!fLength)
+ {
+ fprintf(stderr, libpq_gettext("out of memory\n"));
+ return;
+ }
+
+ for (j = 0; j < nFields; j++)
+ {
+ fLength[j] = strlen(PQfname(res, j));
+ for (i = 0; i < nTuples; i++)
+ {
+ int flen = PQgetlength(res, i, j);
+
+ if (flen > fLength[j])
+ fLength[j] = flen;
+ }
+ }
+ }
+
+ if (printHeader)
+ {
+ /* first, print out the attribute names */
+ for (i = 0; i < nFields; i++)
+ {
+ fputs(PQfname(res, i), fp);
+ if (fillAlign)
+ fill(strlen(PQfname(res, i)), fLength[i], ' ', fp);
+ fputs(fieldSep, fp);
+ }
+ fprintf(fp, "\n");
+
+ /* Underline the attribute names */
+ for (i = 0; i < nFields; i++)
+ {
+ if (fillAlign)
+ fill(0, fLength[i], '-', fp);
+ fputs(fieldSep, fp);
+ }
+ fprintf(fp, "\n");
+ }
+
+ /* next, print out the instances */
+ for (i = 0; i < nTuples; i++)
+ {
+ for (j = 0; j < nFields; j++)
+ {
+ fprintf(fp, "%s", PQgetvalue(res, i, j));
+ if (fillAlign)
+ fill(strlen(PQgetvalue(res, i, j)), fLength[j], ' ', fp);
+ fputs(fieldSep, fp);
+ }
+ fprintf(fp, "\n");
+ }
+
+ if (!quiet)
+ fprintf(fp, "\nQuery returned %d row%s.\n", PQntuples(res),
+ (PQntuples(res) == 1) ? "" : "s");
+
+ fflush(fp);
+
+ free(fLength);
+}
+
+
+
+void
+PQprintTuples(const PGresult *res,
+ FILE *fout, /* output stream */
+ int PrintAttNames, /* print attribute names or not */
+ int TerseOutput, /* delimiter bars or not? */
+ int colWidth /* width of column, if 0, use variable width */
+)
+{
+ int nFields;
+ int nTups;
+ int i,
+ j;
+ char formatString[80];
+ char *tborder = NULL;
+
+ nFields = PQnfields(res);
+ nTups = PQntuples(res);
+
+ if (colWidth > 0)
+ sprintf(formatString, "%%s %%-%ds", colWidth);
+ else
+ sprintf(formatString, "%%s %%s");
+
+ if (nFields > 0)
+ { /* only print rows with at least 1 field. */
+
+ if (!TerseOutput)
+ {
+ int width;
+
+ width = nFields * 14;
+ tborder = (char *) malloc(width + 1);
+ if (!tborder)
+ {
+ fprintf(stderr, libpq_gettext("out of memory\n"));
+ return;
+ }
+ for (i = 0; i < width; i++)
+ tborder[i] = '-';
+ tborder[width] = '\0';
+ fprintf(fout, "%s\n", tborder);
+ }
+
+ for (i = 0; i < nFields; i++)
+ {
+ if (PrintAttNames)
+ {
+ fprintf(fout, formatString,
+ TerseOutput ? "" : "|",
+ PQfname(res, i));
+ }
+ }
+
+ if (PrintAttNames)
+ {
+ if (TerseOutput)
+ fprintf(fout, "\n");
+ else
+ fprintf(fout, "|\n%s\n", tborder);
+ }
+
+ for (i = 0; i < nTups; i++)
+ {
+ for (j = 0; j < nFields; j++)
+ {
+ const char *pval = PQgetvalue(res, i, j);
+
+ fprintf(fout, formatString,
+ TerseOutput ? "" : "|",
+ pval ? pval : "");
+ }
+ if (TerseOutput)
+ fprintf(fout, "\n");
+ else
+ fprintf(fout, "|\n%s\n", tborder);
+ }
+ }
+
+ free(tborder);
+}
+
+
+/* simply send out max-length number of filler characters to fp */
+
+static void
+fill(int length, int max, char filler, FILE *fp)
+{
+ int count;
+
+ count = max - length;
+ while (count-- >= 0)
+ putc(filler, fp);
+}
diff --git a/contrib/libs/libpq/src/interfaces/libpq/fe-protocol3.c b/contrib/libs/libpq/src/interfaces/libpq/fe-protocol3.c
new file mode 100644
index 0000000000..32b66d561c
--- /dev/null
+++ b/contrib/libs/libpq/src/interfaces/libpq/fe-protocol3.c
@@ -0,0 +1,2306 @@
+/*-------------------------------------------------------------------------
+ *
+ * fe-protocol3.c
+ * functions that are specific to frontend/backend protocol version 3
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/interfaces/libpq/fe-protocol3.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres_fe.h"
+
+#include <ctype.h>
+#include <fcntl.h>
+
+#ifdef WIN32
+#include "win32.h"
+#else
+#include <unistd.h>
+#include <netinet/tcp.h>
+#endif
+
+#include "libpq-fe.h"
+#include "libpq-int.h"
+#include "mb/pg_wchar.h"
+#include "port/pg_bswap.h"
+
+/*
+ * This macro lists the backend message types that could be "long" (more
+ * than a couple of kilobytes).
+ */
+#define VALID_LONG_MESSAGE_TYPE(id) \
+ ((id) == 'T' || (id) == 'D' || (id) == 'd' || (id) == 'V' || \
+ (id) == 'E' || (id) == 'N' || (id) == 'A')
+
+
+static void handleSyncLoss(PGconn *conn, char id, int msgLength);
+static int getRowDescriptions(PGconn *conn, int msgLength);
+static int getParamDescriptions(PGconn *conn, int msgLength);
+static int getAnotherTuple(PGconn *conn, int msgLength);
+static int getParameterStatus(PGconn *conn);
+static int getNotify(PGconn *conn);
+static int getCopyStart(PGconn *conn, ExecStatusType copytype);
+static int getReadyForQuery(PGconn *conn);
+static void reportErrorPosition(PQExpBuffer msg, const char *query,
+ int loc, int encoding);
+static int build_startup_packet(const PGconn *conn, char *packet,
+ const PQEnvironmentOption *options);
+
+
+/*
+ * parseInput: if appropriate, parse input data from backend
+ * until input is exhausted or a stopping state is reached.
+ * Note that this function will NOT attempt to read more data from the backend.
+ */
+void
+pqParseInput3(PGconn *conn)
+{
+ char id;
+ int msgLength;
+ int avail;
+
+ /*
+ * Loop to parse successive complete messages available in the buffer.
+ */
+ for (;;)
+ {
+ /*
+ * Try to read a message. First get the type code and length. Return
+ * if not enough data.
+ */
+ conn->inCursor = conn->inStart;
+ if (pqGetc(&id, conn))
+ return;
+ if (pqGetInt(&msgLength, 4, conn))
+ return;
+
+ /*
+ * Try to validate message type/length here. A length less than 4 is
+ * definitely broken. Large lengths should only be believed for a few
+ * message types.
+ */
+ if (msgLength < 4)
+ {
+ handleSyncLoss(conn, id, msgLength);
+ return;
+ }
+ if (msgLength > 30000 && !VALID_LONG_MESSAGE_TYPE(id))
+ {
+ handleSyncLoss(conn, id, msgLength);
+ return;
+ }
+
+ /*
+ * Can't process if message body isn't all here yet.
+ */
+ msgLength -= 4;
+ avail = conn->inEnd - conn->inCursor;
+ if (avail < msgLength)
+ {
+ /*
+ * Before returning, enlarge the input buffer if needed to hold
+ * the whole message. This is better than leaving it to
+ * pqReadData because we can avoid multiple cycles of realloc()
+ * when the message is large; also, we can implement a reasonable
+ * recovery strategy if we are unable to make the buffer big
+ * enough.
+ */
+ if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength,
+ conn))
+ {
+ /*
+ * XXX add some better recovery code... plan is to skip over
+ * the message using its length, then report an error. For the
+ * moment, just treat this like loss of sync (which indeed it
+ * might be!)
+ */
+ handleSyncLoss(conn, id, msgLength);
+ }
+ return;
+ }
+
+ /*
+ * NOTIFY and NOTICE messages can happen in any state; always process
+ * them right away.
+ *
+ * Most other messages should only be processed while in BUSY state.
+ * (In particular, in READY state we hold off further parsing until
+ * the application collects the current PGresult.)
+ *
+ * However, if the state is IDLE then we got trouble; we need to deal
+ * with the unexpected message somehow.
+ *
+ * ParameterStatus ('S') messages are a special case: in IDLE state we
+ * must process 'em (this case could happen if a new value was adopted
+ * from config file due to SIGHUP), but otherwise we hold off until
+ * BUSY state.
+ */
+ if (id == 'A')
+ {
+ if (getNotify(conn))
+ return;
+ }
+ else if (id == 'N')
+ {
+ if (pqGetErrorNotice3(conn, false))
+ return;
+ }
+ else if (conn->asyncStatus != PGASYNC_BUSY)
+ {
+ /* If not IDLE state, just wait ... */
+ if (conn->asyncStatus != PGASYNC_IDLE)
+ return;
+
+ /*
+ * Unexpected message in IDLE state; need to recover somehow.
+ * ERROR messages are handled using the notice processor;
+ * ParameterStatus is handled normally; anything else is just
+ * dropped on the floor after displaying a suitable warning
+ * notice. (An ERROR is very possibly the backend telling us why
+ * it is about to close the connection, so we don't want to just
+ * discard it...)
+ */
+ if (id == 'E')
+ {
+ if (pqGetErrorNotice3(conn, false /* treat as notice */ ))
+ return;
+ }
+ else if (id == 'S')
+ {
+ if (getParameterStatus(conn))
+ return;
+ }
+ else
+ {
+ /* Any other case is unexpected and we summarily skip it */
+ pqInternalNotice(&conn->noticeHooks,
+ "message type 0x%02x arrived from server while idle",
+ id);
+ /* Discard the unexpected message */
+ conn->inCursor += msgLength;
+ }
+ }
+ else
+ {
+ /*
+ * In BUSY state, we can process everything.
+ */
+ switch (id)
+ {
+ case 'C': /* command complete */
+ if (pqGets(&conn->workBuffer, conn))
+ return;
+ if (!pgHavePendingResult(conn))
+ {
+ conn->result = PQmakeEmptyPGresult(conn,
+ PGRES_COMMAND_OK);
+ if (!conn->result)
+ {
+ libpq_append_conn_error(conn, "out of memory");
+ pqSaveErrorResult(conn);
+ }
+ }
+ if (conn->result)
+ strlcpy(conn->result->cmdStatus, conn->workBuffer.data,
+ CMDSTATUS_LEN);
+ conn->asyncStatus = PGASYNC_READY;
+ break;
+ case 'E': /* error return */
+ if (pqGetErrorNotice3(conn, true))
+ return;
+ conn->asyncStatus = PGASYNC_READY;
+ break;
+ case 'Z': /* sync response, backend is ready for new
+ * query */
+ if (getReadyForQuery(conn))
+ return;
+ if (conn->pipelineStatus != PQ_PIPELINE_OFF)
+ {
+ conn->result = PQmakeEmptyPGresult(conn,
+ PGRES_PIPELINE_SYNC);
+ if (!conn->result)
+ {
+ libpq_append_conn_error(conn, "out of memory");
+ pqSaveErrorResult(conn);
+ }
+ else
+ {
+ conn->pipelineStatus = PQ_PIPELINE_ON;
+ conn->asyncStatus = PGASYNC_READY;
+ }
+ }
+ else
+ {
+ /*
+ * In simple query protocol, advance the command queue
+ * (see PQgetResult).
+ */
+ if (conn->cmd_queue_head &&
+ conn->cmd_queue_head->queryclass == PGQUERY_SIMPLE)
+ pqCommandQueueAdvance(conn);
+ conn->asyncStatus = PGASYNC_IDLE;
+ }
+ break;
+ case 'I': /* empty query */
+ if (!pgHavePendingResult(conn))
+ {
+ conn->result = PQmakeEmptyPGresult(conn,
+ PGRES_EMPTY_QUERY);
+ if (!conn->result)
+ {
+ libpq_append_conn_error(conn, "out of memory");
+ pqSaveErrorResult(conn);
+ }
+ }
+ conn->asyncStatus = PGASYNC_READY;
+ break;
+ case '1': /* Parse Complete */
+ /* If we're doing PQprepare, we're done; else ignore */
+ if (conn->cmd_queue_head &&
+ conn->cmd_queue_head->queryclass == PGQUERY_PREPARE)
+ {
+ if (!pgHavePendingResult(conn))
+ {
+ conn->result = PQmakeEmptyPGresult(conn,
+ PGRES_COMMAND_OK);
+ if (!conn->result)
+ {
+ libpq_append_conn_error(conn, "out of memory");
+ pqSaveErrorResult(conn);
+ }
+ }
+ conn->asyncStatus = PGASYNC_READY;
+ }
+ break;
+ case '2': /* Bind Complete */
+ case '3': /* Close Complete */
+ /* Nothing to do for these message types */
+ break;
+ case 'S': /* parameter status */
+ if (getParameterStatus(conn))
+ return;
+ break;
+ case 'K': /* secret key data from the backend */
+
+ /*
+ * This is expected only during backend startup, but it's
+ * just as easy to handle it as part of the main loop.
+ * Save the data and continue processing.
+ */
+ if (pqGetInt(&(conn->be_pid), 4, conn))
+ return;
+ if (pqGetInt(&(conn->be_key), 4, conn))
+ return;
+ break;
+ case 'T': /* Row Description */
+ if (conn->error_result ||
+ (conn->result != NULL &&
+ conn->result->resultStatus == PGRES_FATAL_ERROR))
+ {
+ /*
+ * We've already choked for some reason. Just discard
+ * the data till we get to the end of the query.
+ */
+ conn->inCursor += msgLength;
+ }
+ else if (conn->result == NULL ||
+ (conn->cmd_queue_head &&
+ conn->cmd_queue_head->queryclass == PGQUERY_DESCRIBE))
+ {
+ /* First 'T' in a query sequence */
+ if (getRowDescriptions(conn, msgLength))
+ return;
+ }
+ else
+ {
+ /*
+ * A new 'T' message is treated as the start of
+ * another PGresult. (It is not clear that this is
+ * really possible with the current backend.) We stop
+ * parsing until the application accepts the current
+ * result.
+ */
+ conn->asyncStatus = PGASYNC_READY;
+ return;
+ }
+ break;
+ case 'n': /* No Data */
+
+ /*
+ * NoData indicates that we will not be seeing a
+ * RowDescription message because the statement or portal
+ * inquired about doesn't return rows.
+ *
+ * If we're doing a Describe, we have to pass something
+ * back to the client, so set up a COMMAND_OK result,
+ * instead of PGRES_TUPLES_OK. Otherwise we can just
+ * ignore this message.
+ */
+ if (conn->cmd_queue_head &&
+ conn->cmd_queue_head->queryclass == PGQUERY_DESCRIBE)
+ {
+ if (!pgHavePendingResult(conn))
+ {
+ conn->result = PQmakeEmptyPGresult(conn,
+ PGRES_COMMAND_OK);
+ if (!conn->result)
+ {
+ libpq_append_conn_error(conn, "out of memory");
+ pqSaveErrorResult(conn);
+ }
+ }
+ conn->asyncStatus = PGASYNC_READY;
+ }
+ break;
+ case 't': /* Parameter Description */
+ if (getParamDescriptions(conn, msgLength))
+ return;
+ break;
+ case 'D': /* Data Row */
+ if (conn->result != NULL &&
+ conn->result->resultStatus == PGRES_TUPLES_OK)
+ {
+ /* Read another tuple of a normal query response */
+ if (getAnotherTuple(conn, msgLength))
+ return;
+ }
+ else if (conn->error_result ||
+ (conn->result != NULL &&
+ conn->result->resultStatus == PGRES_FATAL_ERROR))
+ {
+ /*
+ * We've already choked for some reason. Just discard
+ * tuples till we get to the end of the query.
+ */
+ conn->inCursor += msgLength;
+ }
+ else
+ {
+ /* Set up to report error at end of query */
+ libpq_append_conn_error(conn, "server sent data (\"D\" message) without prior row description (\"T\" message)");
+ pqSaveErrorResult(conn);
+ /* Discard the unexpected message */
+ conn->inCursor += msgLength;
+ }
+ break;
+ case 'G': /* Start Copy In */
+ if (getCopyStart(conn, PGRES_COPY_IN))
+ return;
+ conn->asyncStatus = PGASYNC_COPY_IN;
+ break;
+ case 'H': /* Start Copy Out */
+ if (getCopyStart(conn, PGRES_COPY_OUT))
+ return;
+ conn->asyncStatus = PGASYNC_COPY_OUT;
+ conn->copy_already_done = 0;
+ break;
+ case 'W': /* Start Copy Both */
+ if (getCopyStart(conn, PGRES_COPY_BOTH))
+ return;
+ conn->asyncStatus = PGASYNC_COPY_BOTH;
+ conn->copy_already_done = 0;
+ break;
+ case 'd': /* Copy Data */
+
+ /*
+ * If we see Copy Data, just silently drop it. This would
+ * only occur if application exits COPY OUT mode too
+ * early.
+ */
+ conn->inCursor += msgLength;
+ break;
+ case 'c': /* Copy Done */
+
+ /*
+ * If we see Copy Done, just silently drop it. This is
+ * the normal case during PQendcopy. We will keep
+ * swallowing data, expecting to see command-complete for
+ * the COPY command.
+ */
+ break;
+ default:
+ libpq_append_conn_error(conn, "unexpected response from server; first received character was \"%c\"", id);
+ /* build an error result holding the error message */
+ pqSaveErrorResult(conn);
+ /* not sure if we will see more, so go to ready state */
+ conn->asyncStatus = PGASYNC_READY;
+ /* Discard the unexpected message */
+ conn->inCursor += msgLength;
+ break;
+ } /* switch on protocol character */
+ }
+ /* Successfully consumed this message */
+ if (conn->inCursor == conn->inStart + 5 + msgLength)
+ {
+ /* trace server-to-client message */
+ if (conn->Pfdebug)
+ pqTraceOutputMessage(conn, conn->inBuffer + conn->inStart, false);
+
+ /* Normal case: parsing agrees with specified length */
+ conn->inStart = conn->inCursor;
+ }
+ else
+ {
+ /* Trouble --- report it */
+ libpq_append_conn_error(conn, "message contents do not agree with length in message type \"%c\"", id);
+ /* build an error result holding the error message */
+ pqSaveErrorResult(conn);
+ conn->asyncStatus = PGASYNC_READY;
+ /* trust the specified message length as what to skip */
+ conn->inStart += 5 + msgLength;
+ }
+ }
+}
+
+/*
+ * handleSyncLoss: clean up after loss of message-boundary sync
+ *
+ * There isn't really a lot we can do here except abandon the connection.
+ */
+static void
+handleSyncLoss(PGconn *conn, char id, int msgLength)
+{
+ libpq_append_conn_error(conn, "lost synchronization with server: got message type \"%c\", length %d",
+ id, msgLength);
+ /* build an error result holding the error message */
+ pqSaveErrorResult(conn);
+ conn->asyncStatus = PGASYNC_READY; /* drop out of PQgetResult wait loop */
+ /* flush input data since we're giving up on processing it */
+ pqDropConnection(conn, true);
+ conn->status = CONNECTION_BAD; /* No more connection to backend */
+}
+
+/*
+ * parseInput subroutine to read a 'T' (row descriptions) message.
+ * We'll build a new PGresult structure (unless called for a Describe
+ * command for a prepared statement) containing the attribute data.
+ * Returns: 0 if processed message successfully, EOF to suspend parsing
+ * (the latter case is not actually used currently).
+ */
+static int
+getRowDescriptions(PGconn *conn, int msgLength)
+{
+ PGresult *result;
+ int nfields;
+ const char *errmsg;
+ int i;
+
+ /*
+ * When doing Describe for a prepared statement, there'll already be a
+ * PGresult created by getParamDescriptions, and we should fill data into
+ * that. Otherwise, create a new, empty PGresult.
+ */
+ if (!conn->cmd_queue_head ||
+ (conn->cmd_queue_head &&
+ conn->cmd_queue_head->queryclass == PGQUERY_DESCRIBE))
+ {
+ if (conn->result)
+ result = conn->result;
+ else
+ result = PQmakeEmptyPGresult(conn, PGRES_COMMAND_OK);
+ }
+ else
+ result = PQmakeEmptyPGresult(conn, PGRES_TUPLES_OK);
+ if (!result)
+ {
+ errmsg = NULL; /* means "out of memory", see below */
+ goto advance_and_error;
+ }
+
+ /* parseInput already read the 'T' label and message length. */
+ /* the next two bytes are the number of fields */
+ if (pqGetInt(&(result->numAttributes), 2, conn))
+ {
+ /* We should not run out of data here, so complain */
+ errmsg = libpq_gettext("insufficient data in \"T\" message");
+ goto advance_and_error;
+ }
+ nfields = result->numAttributes;
+
+ /* allocate space for the attribute descriptors */
+ if (nfields > 0)
+ {
+ result->attDescs = (PGresAttDesc *)
+ pqResultAlloc(result, nfields * sizeof(PGresAttDesc), true);
+ if (!result->attDescs)
+ {
+ errmsg = NULL; /* means "out of memory", see below */
+ goto advance_and_error;
+ }
+ MemSet(result->attDescs, 0, nfields * sizeof(PGresAttDesc));
+ }
+
+ /* result->binary is true only if ALL columns are binary */
+ result->binary = (nfields > 0) ? 1 : 0;
+
+ /* get type info */
+ for (i = 0; i < nfields; i++)
+ {
+ int tableid;
+ int columnid;
+ int typid;
+ int typlen;
+ int atttypmod;
+ int format;
+
+ if (pqGets(&conn->workBuffer, conn) ||
+ pqGetInt(&tableid, 4, conn) ||
+ pqGetInt(&columnid, 2, conn) ||
+ pqGetInt(&typid, 4, conn) ||
+ pqGetInt(&typlen, 2, conn) ||
+ pqGetInt(&atttypmod, 4, conn) ||
+ pqGetInt(&format, 2, conn))
+ {
+ /* We should not run out of data here, so complain */
+ errmsg = libpq_gettext("insufficient data in \"T\" message");
+ goto advance_and_error;
+ }
+
+ /*
+ * Since pqGetInt treats 2-byte integers as unsigned, we need to
+ * coerce these results to signed form.
+ */
+ columnid = (int) ((int16) columnid);
+ typlen = (int) ((int16) typlen);
+ format = (int) ((int16) format);
+
+ result->attDescs[i].name = pqResultStrdup(result,
+ conn->workBuffer.data);
+ if (!result->attDescs[i].name)
+ {
+ errmsg = NULL; /* means "out of memory", see below */
+ goto advance_and_error;
+ }
+ result->attDescs[i].tableid = tableid;
+ result->attDescs[i].columnid = columnid;
+ result->attDescs[i].format = format;
+ result->attDescs[i].typid = typid;
+ result->attDescs[i].typlen = typlen;
+ result->attDescs[i].atttypmod = atttypmod;
+
+ if (format != 1)
+ result->binary = 0;
+ }
+
+ /* Success! */
+ conn->result = result;
+
+ /*
+ * If we're doing a Describe, we're done, and ready to pass the result
+ * back to the client.
+ */
+ if ((!conn->cmd_queue_head) ||
+ (conn->cmd_queue_head &&
+ conn->cmd_queue_head->queryclass == PGQUERY_DESCRIBE))
+ {
+ conn->asyncStatus = PGASYNC_READY;
+ return 0;
+ }
+
+ /*
+ * We could perform additional setup for the new result set here, but for
+ * now there's nothing else to do.
+ */
+
+ /* And we're done. */
+ return 0;
+
+advance_and_error:
+ /* Discard unsaved result, if any */
+ if (result && result != conn->result)
+ PQclear(result);
+
+ /*
+ * Replace partially constructed result with an error result. First
+ * discard the old result to try to win back some memory.
+ */
+ pqClearAsyncResult(conn);
+
+ /*
+ * If preceding code didn't provide an error message, assume "out of
+ * memory" was meant. The advantage of having this special case is that
+ * freeing the old result first greatly improves the odds that gettext()
+ * will succeed in providing a translation.
+ */
+ if (!errmsg)
+ errmsg = libpq_gettext("out of memory for query result");
+
+ appendPQExpBuffer(&conn->errorMessage, "%s\n", errmsg);
+ pqSaveErrorResult(conn);
+
+ /*
+ * Show the message as fully consumed, else pqParseInput3 will overwrite
+ * our error with a complaint about that.
+ */
+ conn->inCursor = conn->inStart + 5 + msgLength;
+
+ /*
+ * Return zero to allow input parsing to continue. Subsequent "D"
+ * messages will be ignored until we get to end of data, since an error
+ * result is already set up.
+ */
+ return 0;
+}
+
+/*
+ * parseInput subroutine to read a 't' (ParameterDescription) message.
+ * We'll build a new PGresult structure containing the parameter data.
+ * Returns: 0 if processed message successfully, EOF to suspend parsing
+ * (the latter case is not actually used currently).
+ */
+static int
+getParamDescriptions(PGconn *conn, int msgLength)
+{
+ PGresult *result;
+ const char *errmsg = NULL; /* means "out of memory", see below */
+ int nparams;
+ int i;
+
+ result = PQmakeEmptyPGresult(conn, PGRES_COMMAND_OK);
+ if (!result)
+ goto advance_and_error;
+
+ /* parseInput already read the 't' label and message length. */
+ /* the next two bytes are the number of parameters */
+ if (pqGetInt(&(result->numParameters), 2, conn))
+ goto not_enough_data;
+ nparams = result->numParameters;
+
+ /* allocate space for the parameter descriptors */
+ if (nparams > 0)
+ {
+ result->paramDescs = (PGresParamDesc *)
+ pqResultAlloc(result, nparams * sizeof(PGresParamDesc), true);
+ if (!result->paramDescs)
+ goto advance_and_error;
+ MemSet(result->paramDescs, 0, nparams * sizeof(PGresParamDesc));
+ }
+
+ /* get parameter info */
+ for (i = 0; i < nparams; i++)
+ {
+ int typid;
+
+ if (pqGetInt(&typid, 4, conn))
+ goto not_enough_data;
+ result->paramDescs[i].typid = typid;
+ }
+
+ /* Success! */
+ conn->result = result;
+
+ return 0;
+
+not_enough_data:
+ errmsg = libpq_gettext("insufficient data in \"t\" message");
+
+advance_and_error:
+ /* Discard unsaved result, if any */
+ if (result && result != conn->result)
+ PQclear(result);
+
+ /*
+ * Replace partially constructed result with an error result. First
+ * discard the old result to try to win back some memory.
+ */
+ pqClearAsyncResult(conn);
+
+ /*
+ * If preceding code didn't provide an error message, assume "out of
+ * memory" was meant. The advantage of having this special case is that
+ * freeing the old result first greatly improves the odds that gettext()
+ * will succeed in providing a translation.
+ */
+ if (!errmsg)
+ errmsg = libpq_gettext("out of memory");
+ appendPQExpBuffer(&conn->errorMessage, "%s\n", errmsg);
+ pqSaveErrorResult(conn);
+
+ /*
+ * Show the message as fully consumed, else pqParseInput3 will overwrite
+ * our error with a complaint about that.
+ */
+ conn->inCursor = conn->inStart + 5 + msgLength;
+
+ /*
+ * Return zero to allow input parsing to continue. Essentially, we've
+ * replaced the COMMAND_OK result with an error result, but since this
+ * doesn't affect the protocol state, it's fine.
+ */
+ return 0;
+}
+
+/*
+ * parseInput subroutine to read a 'D' (row data) message.
+ * We fill rowbuf with column pointers and then call the row processor.
+ * Returns: 0 if processed message successfully, EOF to suspend parsing
+ * (the latter case is not actually used currently).
+ */
+static int
+getAnotherTuple(PGconn *conn, int msgLength)
+{
+ PGresult *result = conn->result;
+ int nfields = result->numAttributes;
+ const char *errmsg;
+ PGdataValue *rowbuf;
+ int tupnfields; /* # fields from tuple */
+ int vlen; /* length of the current field value */
+ int i;
+
+ /* Get the field count and make sure it's what we expect */
+ if (pqGetInt(&tupnfields, 2, conn))
+ {
+ /* We should not run out of data here, so complain */
+ errmsg = libpq_gettext("insufficient data in \"D\" message");
+ goto advance_and_error;
+ }
+
+ if (tupnfields != nfields)
+ {
+ errmsg = libpq_gettext("unexpected field count in \"D\" message");
+ goto advance_and_error;
+ }
+
+ /* Resize row buffer if needed */
+ rowbuf = conn->rowBuf;
+ if (nfields > conn->rowBufLen)
+ {
+ rowbuf = (PGdataValue *) realloc(rowbuf,
+ nfields * sizeof(PGdataValue));
+ if (!rowbuf)
+ {
+ errmsg = NULL; /* means "out of memory", see below */
+ goto advance_and_error;
+ }
+ conn->rowBuf = rowbuf;
+ conn->rowBufLen = nfields;
+ }
+
+ /* Scan the fields */
+ for (i = 0; i < nfields; i++)
+ {
+ /* get the value length */
+ if (pqGetInt(&vlen, 4, conn))
+ {
+ /* We should not run out of data here, so complain */
+ errmsg = libpq_gettext("insufficient data in \"D\" message");
+ goto advance_and_error;
+ }
+ rowbuf[i].len = vlen;
+
+ /*
+ * rowbuf[i].value always points to the next address in the data
+ * buffer even if the value is NULL. This allows row processors to
+ * estimate data sizes more easily.
+ */
+ rowbuf[i].value = conn->inBuffer + conn->inCursor;
+
+ /* Skip over the data value */
+ if (vlen > 0)
+ {
+ if (pqSkipnchar(vlen, conn))
+ {
+ /* We should not run out of data here, so complain */
+ errmsg = libpq_gettext("insufficient data in \"D\" message");
+ goto advance_and_error;
+ }
+ }
+ }
+
+ /* Process the collected row */
+ errmsg = NULL;
+ if (pqRowProcessor(conn, &errmsg))
+ return 0; /* normal, successful exit */
+
+ /* pqRowProcessor failed, fall through to report it */
+
+advance_and_error:
+
+ /*
+ * Replace partially constructed result with an error result. First
+ * discard the old result to try to win back some memory.
+ */
+ pqClearAsyncResult(conn);
+
+ /*
+ * If preceding code didn't provide an error message, assume "out of
+ * memory" was meant. The advantage of having this special case is that
+ * freeing the old result first greatly improves the odds that gettext()
+ * will succeed in providing a translation.
+ */
+ if (!errmsg)
+ errmsg = libpq_gettext("out of memory for query result");
+
+ appendPQExpBuffer(&conn->errorMessage, "%s\n", errmsg);
+ pqSaveErrorResult(conn);
+
+ /*
+ * Show the message as fully consumed, else pqParseInput3 will overwrite
+ * our error with a complaint about that.
+ */
+ conn->inCursor = conn->inStart + 5 + msgLength;
+
+ /*
+ * Return zero to allow input parsing to continue. Subsequent "D"
+ * messages will be ignored until we get to end of data, since an error
+ * result is already set up.
+ */
+ return 0;
+}
+
+
+/*
+ * Attempt to read an Error or Notice response message.
+ * This is possible in several places, so we break it out as a subroutine.
+ * Entry: 'E' or 'N' message type and length have already been consumed.
+ * Exit: returns 0 if successfully consumed message.
+ * returns EOF if not enough data.
+ */
+int
+pqGetErrorNotice3(PGconn *conn, bool isError)
+{
+ PGresult *res = NULL;
+ bool have_position = false;
+ PQExpBufferData workBuf;
+ char id;
+
+ /* If in pipeline mode, set error indicator for it */
+ if (isError && conn->pipelineStatus != PQ_PIPELINE_OFF)
+ conn->pipelineStatus = PQ_PIPELINE_ABORTED;
+
+ /*
+ * If this is an error message, pre-emptively clear any incomplete query
+ * result we may have. We'd just throw it away below anyway, and
+ * releasing it before collecting the error might avoid out-of-memory.
+ */
+ if (isError)
+ pqClearAsyncResult(conn);
+
+ /*
+ * Since the fields might be pretty long, we create a temporary
+ * PQExpBuffer rather than using conn->workBuffer. workBuffer is intended
+ * for stuff that is expected to be short. We shouldn't use
+ * conn->errorMessage either, since this might be only a notice.
+ */
+ initPQExpBuffer(&workBuf);
+
+ /*
+ * Make a PGresult to hold the accumulated fields. We temporarily lie
+ * about the result status, so that PQmakeEmptyPGresult doesn't uselessly
+ * copy conn->errorMessage.
+ *
+ * NB: This allocation can fail, if you run out of memory. The rest of the
+ * function handles that gracefully, and we still try to set the error
+ * message as the connection's error message.
+ */
+ res = PQmakeEmptyPGresult(conn, PGRES_EMPTY_QUERY);
+ if (res)
+ res->resultStatus = isError ? PGRES_FATAL_ERROR : PGRES_NONFATAL_ERROR;
+
+ /*
+ * Read the fields and save into res.
+ *
+ * While at it, save the SQLSTATE in conn->last_sqlstate, and note whether
+ * we saw a PG_DIAG_STATEMENT_POSITION field.
+ */
+ for (;;)
+ {
+ if (pqGetc(&id, conn))
+ goto fail;
+ if (id == '\0')
+ break; /* terminator found */
+ if (pqGets(&workBuf, conn))
+ goto fail;
+ pqSaveMessageField(res, id, workBuf.data);
+ if (id == PG_DIAG_SQLSTATE)
+ strlcpy(conn->last_sqlstate, workBuf.data,
+ sizeof(conn->last_sqlstate));
+ else if (id == PG_DIAG_STATEMENT_POSITION)
+ have_position = true;
+ }
+
+ /*
+ * Save the active query text, if any, into res as well; but only if we
+ * might need it for an error cursor display, which is only true if there
+ * is a PG_DIAG_STATEMENT_POSITION field.
+ */
+ if (have_position && res && conn->cmd_queue_head && conn->cmd_queue_head->query)
+ res->errQuery = pqResultStrdup(res, conn->cmd_queue_head->query);
+
+ /*
+ * Now build the "overall" error message for PQresultErrorMessage.
+ */
+ resetPQExpBuffer(&workBuf);
+ pqBuildErrorMessage3(&workBuf, res, conn->verbosity, conn->show_context);
+
+ /*
+ * Either save error as current async result, or just emit the notice.
+ */
+ if (isError)
+ {
+ pqClearAsyncResult(conn); /* redundant, but be safe */
+ if (res)
+ {
+ pqSetResultError(res, &workBuf, 0);
+ conn->result = res;
+ }
+ else
+ {
+ /* Fall back to using the internal-error processing paths */
+ conn->error_result = true;
+ }
+
+ if (PQExpBufferDataBroken(workBuf))
+ libpq_append_conn_error(conn, "out of memory");
+ else
+ appendPQExpBufferStr(&conn->errorMessage, workBuf.data);
+ }
+ else
+ {
+ /* if we couldn't allocate the result set, just discard the NOTICE */
+ if (res)
+ {
+ /*
+ * We can cheat a little here and not copy the message. But if we
+ * were unlucky enough to run out of memory while filling workBuf,
+ * insert "out of memory", as in pqSetResultError.
+ */
+ if (PQExpBufferDataBroken(workBuf))
+ res->errMsg = libpq_gettext("out of memory\n");
+ else
+ res->errMsg = workBuf.data;
+ if (res->noticeHooks.noticeRec != NULL)
+ res->noticeHooks.noticeRec(res->noticeHooks.noticeRecArg, res);
+ PQclear(res);
+ }
+ }
+
+ termPQExpBuffer(&workBuf);
+ return 0;
+
+fail:
+ PQclear(res);
+ termPQExpBuffer(&workBuf);
+ return EOF;
+}
+
+/*
+ * Construct an error message from the fields in the given PGresult,
+ * appending it to the contents of "msg".
+ */
+void
+pqBuildErrorMessage3(PQExpBuffer msg, const PGresult *res,
+ PGVerbosity verbosity, PGContextVisibility show_context)
+{
+ const char *val;
+ const char *querytext = NULL;
+ int querypos = 0;
+
+ /* If we couldn't allocate a PGresult, just say "out of memory" */
+ if (res == NULL)
+ {
+ appendPQExpBufferStr(msg, libpq_gettext("out of memory\n"));
+ return;
+ }
+
+ /*
+ * If we don't have any broken-down fields, just return the base message.
+ * This mainly applies if we're given a libpq-generated error result.
+ */
+ if (res->errFields == NULL)
+ {
+ if (res->errMsg && res->errMsg[0])
+ appendPQExpBufferStr(msg, res->errMsg);
+ else
+ appendPQExpBufferStr(msg, libpq_gettext("no error message available\n"));
+ return;
+ }
+
+ /* Else build error message from relevant fields */
+ val = PQresultErrorField(res, PG_DIAG_SEVERITY);
+ if (val)
+ appendPQExpBuffer(msg, "%s: ", val);
+
+ if (verbosity == PQERRORS_SQLSTATE)
+ {
+ /*
+ * If we have a SQLSTATE, print that and nothing else. If not (which
+ * shouldn't happen for server-generated errors, but might possibly
+ * happen for libpq-generated ones), fall back to TERSE format, as
+ * that seems better than printing nothing at all.
+ */
+ val = PQresultErrorField(res, PG_DIAG_SQLSTATE);
+ if (val)
+ {
+ appendPQExpBuffer(msg, "%s\n", val);
+ return;
+ }
+ verbosity = PQERRORS_TERSE;
+ }
+
+ if (verbosity == PQERRORS_VERBOSE)
+ {
+ val = PQresultErrorField(res, PG_DIAG_SQLSTATE);
+ if (val)
+ appendPQExpBuffer(msg, "%s: ", val);
+ }
+ val = PQresultErrorField(res, PG_DIAG_MESSAGE_PRIMARY);
+ if (val)
+ appendPQExpBufferStr(msg, val);
+ val = PQresultErrorField(res, PG_DIAG_STATEMENT_POSITION);
+ if (val)
+ {
+ if (verbosity != PQERRORS_TERSE && res->errQuery != NULL)
+ {
+ /* emit position as a syntax cursor display */
+ querytext = res->errQuery;
+ querypos = atoi(val);
+ }
+ else
+ {
+ /* emit position as text addition to primary message */
+ /* translator: %s represents a digit string */
+ appendPQExpBuffer(msg, libpq_gettext(" at character %s"),
+ val);
+ }
+ }
+ else
+ {
+ val = PQresultErrorField(res, PG_DIAG_INTERNAL_POSITION);
+ if (val)
+ {
+ querytext = PQresultErrorField(res, PG_DIAG_INTERNAL_QUERY);
+ if (verbosity != PQERRORS_TERSE && querytext != NULL)
+ {
+ /* emit position as a syntax cursor display */
+ querypos = atoi(val);
+ }
+ else
+ {
+ /* emit position as text addition to primary message */
+ /* translator: %s represents a digit string */
+ appendPQExpBuffer(msg, libpq_gettext(" at character %s"),
+ val);
+ }
+ }
+ }
+ appendPQExpBufferChar(msg, '\n');
+ if (verbosity != PQERRORS_TERSE)
+ {
+ if (querytext && querypos > 0)
+ reportErrorPosition(msg, querytext, querypos,
+ res->client_encoding);
+ val = PQresultErrorField(res, PG_DIAG_MESSAGE_DETAIL);
+ if (val)
+ appendPQExpBuffer(msg, libpq_gettext("DETAIL: %s\n"), val);
+ val = PQresultErrorField(res, PG_DIAG_MESSAGE_HINT);
+ if (val)
+ appendPQExpBuffer(msg, libpq_gettext("HINT: %s\n"), val);
+ val = PQresultErrorField(res, PG_DIAG_INTERNAL_QUERY);
+ if (val)
+ appendPQExpBuffer(msg, libpq_gettext("QUERY: %s\n"), val);
+ if (show_context == PQSHOW_CONTEXT_ALWAYS ||
+ (show_context == PQSHOW_CONTEXT_ERRORS &&
+ res->resultStatus == PGRES_FATAL_ERROR))
+ {
+ val = PQresultErrorField(res, PG_DIAG_CONTEXT);
+ if (val)
+ appendPQExpBuffer(msg, libpq_gettext("CONTEXT: %s\n"),
+ val);
+ }
+ }
+ if (verbosity == PQERRORS_VERBOSE)
+ {
+ val = PQresultErrorField(res, PG_DIAG_SCHEMA_NAME);
+ if (val)
+ appendPQExpBuffer(msg,
+ libpq_gettext("SCHEMA NAME: %s\n"), val);
+ val = PQresultErrorField(res, PG_DIAG_TABLE_NAME);
+ if (val)
+ appendPQExpBuffer(msg,
+ libpq_gettext("TABLE NAME: %s\n"), val);
+ val = PQresultErrorField(res, PG_DIAG_COLUMN_NAME);
+ if (val)
+ appendPQExpBuffer(msg,
+ libpq_gettext("COLUMN NAME: %s\n"), val);
+ val = PQresultErrorField(res, PG_DIAG_DATATYPE_NAME);
+ if (val)
+ appendPQExpBuffer(msg,
+ libpq_gettext("DATATYPE NAME: %s\n"), val);
+ val = PQresultErrorField(res, PG_DIAG_CONSTRAINT_NAME);
+ if (val)
+ appendPQExpBuffer(msg,
+ libpq_gettext("CONSTRAINT NAME: %s\n"), val);
+ }
+ if (verbosity == PQERRORS_VERBOSE)
+ {
+ const char *valf;
+ const char *vall;
+
+ valf = PQresultErrorField(res, PG_DIAG_SOURCE_FILE);
+ vall = PQresultErrorField(res, PG_DIAG_SOURCE_LINE);
+ val = PQresultErrorField(res, PG_DIAG_SOURCE_FUNCTION);
+ if (val || valf || vall)
+ {
+ appendPQExpBufferStr(msg, libpq_gettext("LOCATION: "));
+ if (val)
+ appendPQExpBuffer(msg, libpq_gettext("%s, "), val);
+ if (valf && vall) /* unlikely we'd have just one */
+ appendPQExpBuffer(msg, libpq_gettext("%s:%s"),
+ valf, vall);
+ appendPQExpBufferChar(msg, '\n');
+ }
+ }
+}
+
+/*
+ * Add an error-location display to the error message under construction.
+ *
+ * The cursor location is measured in logical characters; the query string
+ * is presumed to be in the specified encoding.
+ */
+static void
+reportErrorPosition(PQExpBuffer msg, const char *query, int loc, int encoding)
+{
+#define DISPLAY_SIZE 60 /* screen width limit, in screen cols */
+#define MIN_RIGHT_CUT 10 /* try to keep this far away from EOL */
+
+ char *wquery;
+ int slen,
+ cno,
+ i,
+ *qidx,
+ *scridx,
+ qoffset,
+ scroffset,
+ ibeg,
+ iend,
+ loc_line;
+ bool mb_encoding,
+ beg_trunc,
+ end_trunc;
+
+ /* Convert loc from 1-based to 0-based; no-op if out of range */
+ loc--;
+ if (loc < 0)
+ return;
+
+ /* Need a writable copy of the query */
+ wquery = strdup(query);
+ if (wquery == NULL)
+ return; /* fail silently if out of memory */
+
+ /*
+ * Each character might occupy multiple physical bytes in the string, and
+ * in some Far Eastern character sets it might take more than one screen
+ * column as well. We compute the starting byte offset and starting
+ * screen column of each logical character, and store these in qidx[] and
+ * scridx[] respectively.
+ */
+
+ /* we need a safe allocation size... */
+ slen = strlen(wquery) + 1;
+
+ qidx = (int *) malloc(slen * sizeof(int));
+ if (qidx == NULL)
+ {
+ free(wquery);
+ return;
+ }
+ scridx = (int *) malloc(slen * sizeof(int));
+ if (scridx == NULL)
+ {
+ free(qidx);
+ free(wquery);
+ return;
+ }
+
+ /* We can optimize a bit if it's a single-byte encoding */
+ mb_encoding = (pg_encoding_max_length(encoding) != 1);
+
+ /*
+ * Within the scanning loop, cno is the current character's logical
+ * number, qoffset is its offset in wquery, and scroffset is its starting
+ * logical screen column (all indexed from 0). "loc" is the logical
+ * character number of the error location. We scan to determine loc_line
+ * (the 1-based line number containing loc) and ibeg/iend (first character
+ * number and last+1 character number of the line containing loc). Note
+ * that qidx[] and scridx[] are filled only as far as iend.
+ */
+ qoffset = 0;
+ scroffset = 0;
+ loc_line = 1;
+ ibeg = 0;
+ iend = -1; /* -1 means not set yet */
+
+ for (cno = 0; wquery[qoffset] != '\0'; cno++)
+ {
+ char ch = wquery[qoffset];
+
+ qidx[cno] = qoffset;
+ scridx[cno] = scroffset;
+
+ /*
+ * Replace tabs with spaces in the writable copy. (Later we might
+ * want to think about coping with their variable screen width, but
+ * not today.)
+ */
+ if (ch == '\t')
+ wquery[qoffset] = ' ';
+
+ /*
+ * If end-of-line, count lines and mark positions. Each \r or \n
+ * counts as a line except when \r \n appear together.
+ */
+ else if (ch == '\r' || ch == '\n')
+ {
+ if (cno < loc)
+ {
+ if (ch == '\r' ||
+ cno == 0 ||
+ wquery[qidx[cno - 1]] != '\r')
+ loc_line++;
+ /* extract beginning = last line start before loc. */
+ ibeg = cno + 1;
+ }
+ else
+ {
+ /* set extract end. */
+ iend = cno;
+ /* done scanning. */
+ break;
+ }
+ }
+
+ /* Advance */
+ if (mb_encoding)
+ {
+ int w;
+
+ w = pg_encoding_dsplen(encoding, &wquery[qoffset]);
+ /* treat any non-tab control chars as width 1 */
+ if (w <= 0)
+ w = 1;
+ scroffset += w;
+ qoffset += PQmblenBounded(&wquery[qoffset], encoding);
+ }
+ else
+ {
+ /* We assume wide chars only exist in multibyte encodings */
+ scroffset++;
+ qoffset++;
+ }
+ }
+ /* Fix up if we didn't find an end-of-line after loc */
+ if (iend < 0)
+ {
+ iend = cno; /* query length in chars, +1 */
+ qidx[iend] = qoffset;
+ scridx[iend] = scroffset;
+ }
+
+ /* Print only if loc is within computed query length */
+ if (loc <= cno)
+ {
+ /* If the line extracted is too long, we truncate it. */
+ beg_trunc = false;
+ end_trunc = false;
+ if (scridx[iend] - scridx[ibeg] > DISPLAY_SIZE)
+ {
+ /*
+ * We first truncate right if it is enough. This code might be
+ * off a space or so on enforcing MIN_RIGHT_CUT if there's a wide
+ * character right there, but that should be okay.
+ */
+ if (scridx[ibeg] + DISPLAY_SIZE >= scridx[loc] + MIN_RIGHT_CUT)
+ {
+ while (scridx[iend] - scridx[ibeg] > DISPLAY_SIZE)
+ iend--;
+ end_trunc = true;
+ }
+ else
+ {
+ /* Truncate right if not too close to loc. */
+ while (scridx[loc] + MIN_RIGHT_CUT < scridx[iend])
+ {
+ iend--;
+ end_trunc = true;
+ }
+
+ /* Truncate left if still too long. */
+ while (scridx[iend] - scridx[ibeg] > DISPLAY_SIZE)
+ {
+ ibeg++;
+ beg_trunc = true;
+ }
+ }
+ }
+
+ /* truncate working copy at desired endpoint */
+ wquery[qidx[iend]] = '\0';
+
+ /* Begin building the finished message. */
+ i = msg->len;
+ appendPQExpBuffer(msg, libpq_gettext("LINE %d: "), loc_line);
+ if (beg_trunc)
+ appendPQExpBufferStr(msg, "...");
+
+ /*
+ * While we have the prefix in the msg buffer, compute its screen
+ * width.
+ */
+ scroffset = 0;
+ for (; i < msg->len; i += PQmblenBounded(&msg->data[i], encoding))
+ {
+ int w = pg_encoding_dsplen(encoding, &msg->data[i]);
+
+ if (w <= 0)
+ w = 1;
+ scroffset += w;
+ }
+
+ /* Finish up the LINE message line. */
+ appendPQExpBufferStr(msg, &wquery[qidx[ibeg]]);
+ if (end_trunc)
+ appendPQExpBufferStr(msg, "...");
+ appendPQExpBufferChar(msg, '\n');
+
+ /* Now emit the cursor marker line. */
+ scroffset += scridx[loc] - scridx[ibeg];
+ for (i = 0; i < scroffset; i++)
+ appendPQExpBufferChar(msg, ' ');
+ appendPQExpBufferChar(msg, '^');
+ appendPQExpBufferChar(msg, '\n');
+ }
+
+ /* Clean up. */
+ free(scridx);
+ free(qidx);
+ free(wquery);
+}
+
+
+/*
+ * Attempt to read a NegotiateProtocolVersion message.
+ * Entry: 'v' message type and length have already been consumed.
+ * Exit: returns 0 if successfully consumed message.
+ * returns EOF if not enough data.
+ */
+int
+pqGetNegotiateProtocolVersion3(PGconn *conn)
+{
+ int tmp;
+ ProtocolVersion their_version;
+ int num;
+ PQExpBufferData buf;
+
+ if (pqGetInt(&tmp, 4, conn) != 0)
+ return EOF;
+ their_version = tmp;
+
+ if (pqGetInt(&num, 4, conn) != 0)
+ return EOF;
+
+ initPQExpBuffer(&buf);
+ for (int i = 0; i < num; i++)
+ {
+ if (pqGets(&conn->workBuffer, conn))
+ {
+ termPQExpBuffer(&buf);
+ return EOF;
+ }
+ if (buf.len > 0)
+ appendPQExpBufferChar(&buf, ' ');
+ appendPQExpBufferStr(&buf, conn->workBuffer.data);
+ }
+
+ if (their_version < conn->pversion)
+ libpq_append_conn_error(conn, "protocol version not supported by server: client uses %u.%u, server supports up to %u.%u",
+ PG_PROTOCOL_MAJOR(conn->pversion), PG_PROTOCOL_MINOR(conn->pversion),
+ PG_PROTOCOL_MAJOR(their_version), PG_PROTOCOL_MINOR(their_version));
+ if (num > 0)
+ {
+ appendPQExpBuffer(&conn->errorMessage,
+ libpq_ngettext("protocol extension not supported by server: %s",
+ "protocol extensions not supported by server: %s", num),
+ buf.data);
+ appendPQExpBufferChar(&conn->errorMessage, '\n');
+ }
+
+ /* neither -- server shouldn't have sent it */
+ if (!(their_version < conn->pversion) && !(num > 0))
+ libpq_append_conn_error(conn, "invalid %s message", "NegotiateProtocolVersion");
+
+ termPQExpBuffer(&buf);
+ return 0;
+}
+
+
+/*
+ * Attempt to read a ParameterStatus message.
+ * This is possible in several places, so we break it out as a subroutine.
+ * Entry: 'S' message type and length have already been consumed.
+ * Exit: returns 0 if successfully consumed message.
+ * returns EOF if not enough data.
+ */
+static int
+getParameterStatus(PGconn *conn)
+{
+ PQExpBufferData valueBuf;
+
+ /* Get the parameter name */
+ if (pqGets(&conn->workBuffer, conn))
+ return EOF;
+ /* Get the parameter value (could be large) */
+ initPQExpBuffer(&valueBuf);
+ if (pqGets(&valueBuf, conn))
+ {
+ termPQExpBuffer(&valueBuf);
+ return EOF;
+ }
+ /* And save it */
+ pqSaveParameterStatus(conn, conn->workBuffer.data, valueBuf.data);
+ termPQExpBuffer(&valueBuf);
+ return 0;
+}
+
+
+/*
+ * Attempt to read a Notify response message.
+ * This is possible in several places, so we break it out as a subroutine.
+ * Entry: 'A' message type and length have already been consumed.
+ * Exit: returns 0 if successfully consumed Notify message.
+ * returns EOF if not enough data.
+ */
+static int
+getNotify(PGconn *conn)
+{
+ int be_pid;
+ char *svname;
+ int nmlen;
+ int extralen;
+ PGnotify *newNotify;
+
+ if (pqGetInt(&be_pid, 4, conn))
+ return EOF;
+ if (pqGets(&conn->workBuffer, conn))
+ return EOF;
+ /* must save name while getting extra string */
+ svname = strdup(conn->workBuffer.data);
+ if (!svname)
+ return EOF;
+ if (pqGets(&conn->workBuffer, conn))
+ {
+ free(svname);
+ return EOF;
+ }
+
+ /*
+ * Store the strings right after the PGnotify structure so it can all be
+ * freed at once. We don't use NAMEDATALEN because we don't want to tie
+ * this interface to a specific server name length.
+ */
+ nmlen = strlen(svname);
+ extralen = strlen(conn->workBuffer.data);
+ newNotify = (PGnotify *) malloc(sizeof(PGnotify) + nmlen + extralen + 2);
+ if (newNotify)
+ {
+ newNotify->relname = (char *) newNotify + sizeof(PGnotify);
+ strcpy(newNotify->relname, svname);
+ newNotify->extra = newNotify->relname + nmlen + 1;
+ strcpy(newNotify->extra, conn->workBuffer.data);
+ newNotify->be_pid = be_pid;
+ newNotify->next = NULL;
+ if (conn->notifyTail)
+ conn->notifyTail->next = newNotify;
+ else
+ conn->notifyHead = newNotify;
+ conn->notifyTail = newNotify;
+ }
+
+ free(svname);
+ return 0;
+}
+
+/*
+ * getCopyStart - process CopyInResponse, CopyOutResponse or
+ * CopyBothResponse message
+ *
+ * parseInput already read the message type and length.
+ */
+static int
+getCopyStart(PGconn *conn, ExecStatusType copytype)
+{
+ PGresult *result;
+ int nfields;
+ int i;
+
+ result = PQmakeEmptyPGresult(conn, copytype);
+ if (!result)
+ goto failure;
+
+ if (pqGetc(&conn->copy_is_binary, conn))
+ goto failure;
+ result->binary = conn->copy_is_binary;
+ /* the next two bytes are the number of fields */
+ if (pqGetInt(&(result->numAttributes), 2, conn))
+ goto failure;
+ nfields = result->numAttributes;
+
+ /* allocate space for the attribute descriptors */
+ if (nfields > 0)
+ {
+ result->attDescs = (PGresAttDesc *)
+ pqResultAlloc(result, nfields * sizeof(PGresAttDesc), true);
+ if (!result->attDescs)
+ goto failure;
+ MemSet(result->attDescs, 0, nfields * sizeof(PGresAttDesc));
+ }
+
+ for (i = 0; i < nfields; i++)
+ {
+ int format;
+
+ if (pqGetInt(&format, 2, conn))
+ goto failure;
+
+ /*
+ * Since pqGetInt treats 2-byte integers as unsigned, we need to
+ * coerce these results to signed form.
+ */
+ format = (int) ((int16) format);
+ result->attDescs[i].format = format;
+ }
+
+ /* Success! */
+ conn->result = result;
+ return 0;
+
+failure:
+ PQclear(result);
+ return EOF;
+}
+
+/*
+ * getReadyForQuery - process ReadyForQuery message
+ */
+static int
+getReadyForQuery(PGconn *conn)
+{
+ char xact_status;
+
+ if (pqGetc(&xact_status, conn))
+ return EOF;
+ switch (xact_status)
+ {
+ case 'I':
+ conn->xactStatus = PQTRANS_IDLE;
+ break;
+ case 'T':
+ conn->xactStatus = PQTRANS_INTRANS;
+ break;
+ case 'E':
+ conn->xactStatus = PQTRANS_INERROR;
+ break;
+ default:
+ conn->xactStatus = PQTRANS_UNKNOWN;
+ break;
+ }
+
+ return 0;
+}
+
+/*
+ * getCopyDataMessage - fetch next CopyData message, process async messages
+ *
+ * Returns length word of CopyData message (> 0), or 0 if no complete
+ * message available, -1 if end of copy, -2 if error.
+ */
+static int
+getCopyDataMessage(PGconn *conn)
+{
+ char id;
+ int msgLength;
+ int avail;
+
+ for (;;)
+ {
+ /*
+ * Do we have the next input message? To make life simpler for async
+ * callers, we keep returning 0 until the next message is fully
+ * available, even if it is not Copy Data.
+ */
+ conn->inCursor = conn->inStart;
+ if (pqGetc(&id, conn))
+ return 0;
+ if (pqGetInt(&msgLength, 4, conn))
+ return 0;
+ if (msgLength < 4)
+ {
+ handleSyncLoss(conn, id, msgLength);
+ return -2;
+ }
+ avail = conn->inEnd - conn->inCursor;
+ if (avail < msgLength - 4)
+ {
+ /*
+ * Before returning, enlarge the input buffer if needed to hold
+ * the whole message. See notes in parseInput.
+ */
+ if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength - 4,
+ conn))
+ {
+ /*
+ * XXX add some better recovery code... plan is to skip over
+ * the message using its length, then report an error. For the
+ * moment, just treat this like loss of sync (which indeed it
+ * might be!)
+ */
+ handleSyncLoss(conn, id, msgLength);
+ return -2;
+ }
+ return 0;
+ }
+
+ /*
+ * If it's a legitimate async message type, process it. (NOTIFY
+ * messages are not currently possible here, but we handle them for
+ * completeness.) Otherwise, if it's anything except Copy Data,
+ * report end-of-copy.
+ */
+ switch (id)
+ {
+ case 'A': /* NOTIFY */
+ if (getNotify(conn))
+ return 0;
+ break;
+ case 'N': /* NOTICE */
+ if (pqGetErrorNotice3(conn, false))
+ return 0;
+ break;
+ case 'S': /* ParameterStatus */
+ if (getParameterStatus(conn))
+ return 0;
+ break;
+ case 'd': /* Copy Data, pass it back to caller */
+ return msgLength;
+ case 'c':
+
+ /*
+ * If this is a CopyDone message, exit COPY_OUT mode and let
+ * caller read status with PQgetResult(). If we're in
+ * COPY_BOTH mode, return to COPY_IN mode.
+ */
+ if (conn->asyncStatus == PGASYNC_COPY_BOTH)
+ conn->asyncStatus = PGASYNC_COPY_IN;
+ else
+ conn->asyncStatus = PGASYNC_BUSY;
+ return -1;
+ default: /* treat as end of copy */
+
+ /*
+ * Any other message terminates either COPY_IN or COPY_BOTH
+ * mode.
+ */
+ conn->asyncStatus = PGASYNC_BUSY;
+ return -1;
+ }
+
+ /* trace server-to-client message */
+ if (conn->Pfdebug)
+ pqTraceOutputMessage(conn, conn->inBuffer + conn->inStart, false);
+
+ /* Drop the processed message and loop around for another */
+ conn->inStart = conn->inCursor;
+ }
+}
+
+/*
+ * PQgetCopyData - read a row of data from the backend during COPY OUT
+ * or COPY BOTH
+ *
+ * If successful, sets *buffer to point to a malloc'd row of data, and
+ * returns row length (always > 0) as result.
+ * Returns 0 if no row available yet (only possible if async is true),
+ * -1 if end of copy (consult PQgetResult), or -2 if error (consult
+ * PQerrorMessage).
+ */
+int
+pqGetCopyData3(PGconn *conn, char **buffer, int async)
+{
+ int msgLength;
+
+ for (;;)
+ {
+ /*
+ * Collect the next input message. To make life simpler for async
+ * callers, we keep returning 0 until the next message is fully
+ * available, even if it is not Copy Data.
+ */
+ msgLength = getCopyDataMessage(conn);
+ if (msgLength < 0)
+ return msgLength; /* end-of-copy or error */
+ if (msgLength == 0)
+ {
+ /* Don't block if async read requested */
+ if (async)
+ return 0;
+ /* Need to load more data */
+ if (pqWait(true, false, conn) ||
+ pqReadData(conn) < 0)
+ return -2;
+ continue;
+ }
+
+ /*
+ * Drop zero-length messages (shouldn't happen anyway). Otherwise
+ * pass the data back to the caller.
+ */
+ msgLength -= 4;
+ if (msgLength > 0)
+ {
+ *buffer = (char *) malloc(msgLength + 1);
+ if (*buffer == NULL)
+ {
+ libpq_append_conn_error(conn, "out of memory");
+ return -2;
+ }
+ memcpy(*buffer, &conn->inBuffer[conn->inCursor], msgLength);
+ (*buffer)[msgLength] = '\0'; /* Add terminating null */
+
+ /* Mark message consumed */
+ conn->inStart = conn->inCursor + msgLength;
+
+ return msgLength;
+ }
+
+ /* Empty, so drop it and loop around for another */
+ conn->inStart = conn->inCursor;
+ }
+}
+
+/*
+ * PQgetline - gets a newline-terminated string from the backend.
+ *
+ * See fe-exec.c for documentation.
+ */
+int
+pqGetline3(PGconn *conn, char *s, int maxlen)
+{
+ int status;
+
+ if (conn->sock == PGINVALID_SOCKET ||
+ (conn->asyncStatus != PGASYNC_COPY_OUT &&
+ conn->asyncStatus != PGASYNC_COPY_BOTH) ||
+ conn->copy_is_binary)
+ {
+ libpq_append_conn_error(conn, "PQgetline: not doing text COPY OUT");
+ *s = '\0';
+ return EOF;
+ }
+
+ while ((status = PQgetlineAsync(conn, s, maxlen - 1)) == 0)
+ {
+ /* need to load more data */
+ if (pqWait(true, false, conn) ||
+ pqReadData(conn) < 0)
+ {
+ *s = '\0';
+ return EOF;
+ }
+ }
+
+ if (status < 0)
+ {
+ /* End of copy detected; gin up old-style terminator */
+ strcpy(s, "\\.");
+ return 0;
+ }
+
+ /* Add null terminator, and strip trailing \n if present */
+ if (s[status - 1] == '\n')
+ {
+ s[status - 1] = '\0';
+ return 0;
+ }
+ else
+ {
+ s[status] = '\0';
+ return 1;
+ }
+}
+
+/*
+ * PQgetlineAsync - gets a COPY data row without blocking.
+ *
+ * See fe-exec.c for documentation.
+ */
+int
+pqGetlineAsync3(PGconn *conn, char *buffer, int bufsize)
+{
+ int msgLength;
+ int avail;
+
+ if (conn->asyncStatus != PGASYNC_COPY_OUT
+ && conn->asyncStatus != PGASYNC_COPY_BOTH)
+ return -1; /* we are not doing a copy... */
+
+ /*
+ * Recognize the next input message. To make life simpler for async
+ * callers, we keep returning 0 until the next message is fully available
+ * even if it is not Copy Data. This should keep PQendcopy from blocking.
+ * (Note: unlike pqGetCopyData3, we do not change asyncStatus here.)
+ */
+ msgLength = getCopyDataMessage(conn);
+ if (msgLength < 0)
+ return -1; /* end-of-copy or error */
+ if (msgLength == 0)
+ return 0; /* no data yet */
+
+ /*
+ * Move data from libpq's buffer to the caller's. In the case where a
+ * prior call found the caller's buffer too small, we use
+ * conn->copy_already_done to remember how much of the row was already
+ * returned to the caller.
+ */
+ conn->inCursor += conn->copy_already_done;
+ avail = msgLength - 4 - conn->copy_already_done;
+ if (avail <= bufsize)
+ {
+ /* Able to consume the whole message */
+ memcpy(buffer, &conn->inBuffer[conn->inCursor], avail);
+ /* Mark message consumed */
+ conn->inStart = conn->inCursor + avail;
+ /* Reset state for next time */
+ conn->copy_already_done = 0;
+ return avail;
+ }
+ else
+ {
+ /* We must return a partial message */
+ memcpy(buffer, &conn->inBuffer[conn->inCursor], bufsize);
+ /* The message is NOT consumed from libpq's buffer */
+ conn->copy_already_done += bufsize;
+ return bufsize;
+ }
+}
+
+/*
+ * PQendcopy
+ *
+ * See fe-exec.c for documentation.
+ */
+int
+pqEndcopy3(PGconn *conn)
+{
+ PGresult *result;
+
+ if (conn->asyncStatus != PGASYNC_COPY_IN &&
+ conn->asyncStatus != PGASYNC_COPY_OUT &&
+ conn->asyncStatus != PGASYNC_COPY_BOTH)
+ {
+ libpq_append_conn_error(conn, "no COPY in progress");
+ return 1;
+ }
+
+ /* Send the CopyDone message if needed */
+ if (conn->asyncStatus == PGASYNC_COPY_IN ||
+ conn->asyncStatus == PGASYNC_COPY_BOTH)
+ {
+ if (pqPutMsgStart('c', conn) < 0 ||
+ pqPutMsgEnd(conn) < 0)
+ return 1;
+
+ /*
+ * If we sent the COPY command in extended-query mode, we must issue a
+ * Sync as well.
+ */
+ if (conn->cmd_queue_head &&
+ conn->cmd_queue_head->queryclass != PGQUERY_SIMPLE)
+ {
+ if (pqPutMsgStart('S', conn) < 0 ||
+ pqPutMsgEnd(conn) < 0)
+ return 1;
+ }
+ }
+
+ /*
+ * make sure no data is waiting to be sent, abort if we are non-blocking
+ * and the flush fails
+ */
+ if (pqFlush(conn) && pqIsnonblocking(conn))
+ return 1;
+
+ /* Return to active duty */
+ conn->asyncStatus = PGASYNC_BUSY;
+
+ /*
+ * Non blocking connections may have to abort at this point. If everyone
+ * played the game there should be no problem, but in error scenarios the
+ * expected messages may not have arrived yet. (We are assuming that the
+ * backend's packetizing will ensure that CommandComplete arrives along
+ * with the CopyDone; are there corner cases where that doesn't happen?)
+ */
+ if (pqIsnonblocking(conn) && PQisBusy(conn))
+ return 1;
+
+ /* Wait for the completion response */
+ result = PQgetResult(conn);
+
+ /* Expecting a successful result */
+ if (result && result->resultStatus == PGRES_COMMAND_OK)
+ {
+ PQclear(result);
+ return 0;
+ }
+
+ /*
+ * Trouble. For backwards-compatibility reasons, we issue the error
+ * message as if it were a notice (would be nice to get rid of this
+ * silliness, but too many apps probably don't handle errors from
+ * PQendcopy reasonably). Note that the app can still obtain the error
+ * status from the PGconn object.
+ */
+ if (conn->errorMessage.len > 0)
+ {
+ /* We have to strip the trailing newline ... pain in neck... */
+ char svLast = conn->errorMessage.data[conn->errorMessage.len - 1];
+
+ if (svLast == '\n')
+ conn->errorMessage.data[conn->errorMessage.len - 1] = '\0';
+ pqInternalNotice(&conn->noticeHooks, "%s", conn->errorMessage.data);
+ conn->errorMessage.data[conn->errorMessage.len - 1] = svLast;
+ }
+
+ PQclear(result);
+
+ return 1;
+}
+
+
+/*
+ * PQfn - Send a function call to the POSTGRES backend.
+ *
+ * See fe-exec.c for documentation.
+ */
+PGresult *
+pqFunctionCall3(PGconn *conn, Oid fnid,
+ int *result_buf, int *actual_result_len,
+ int result_is_int,
+ const PQArgBlock *args, int nargs)
+{
+ bool needInput = false;
+ ExecStatusType status = PGRES_FATAL_ERROR;
+ char id;
+ int msgLength;
+ int avail;
+ int i;
+
+ /* already validated by PQfn */
+ Assert(conn->pipelineStatus == PQ_PIPELINE_OFF);
+
+ /* PQfn already validated connection state */
+
+ if (pqPutMsgStart('F', conn) < 0 || /* function call msg */
+ pqPutInt(fnid, 4, conn) < 0 || /* function id */
+ pqPutInt(1, 2, conn) < 0 || /* # of format codes */
+ pqPutInt(1, 2, conn) < 0 || /* format code: BINARY */
+ pqPutInt(nargs, 2, conn) < 0) /* # of args */
+ {
+ /* error message should be set up already */
+ return NULL;
+ }
+
+ for (i = 0; i < nargs; ++i)
+ { /* len.int4 + contents */
+ if (pqPutInt(args[i].len, 4, conn))
+ return NULL;
+ if (args[i].len == -1)
+ continue; /* it's NULL */
+
+ if (args[i].isint)
+ {
+ if (pqPutInt(args[i].u.integer, args[i].len, conn))
+ return NULL;
+ }
+ else
+ {
+ if (pqPutnchar((char *) args[i].u.ptr, args[i].len, conn))
+ return NULL;
+ }
+ }
+
+ if (pqPutInt(1, 2, conn) < 0) /* result format code: BINARY */
+ return NULL;
+
+ if (pqPutMsgEnd(conn) < 0 ||
+ pqFlush(conn))
+ return NULL;
+
+ for (;;)
+ {
+ if (needInput)
+ {
+ /* Wait for some data to arrive (or for the channel to close) */
+ if (pqWait(true, false, conn) ||
+ pqReadData(conn) < 0)
+ break;
+ }
+
+ /*
+ * Scan the message. If we run out of data, loop around to try again.
+ */
+ needInput = true;
+
+ conn->inCursor = conn->inStart;
+ if (pqGetc(&id, conn))
+ continue;
+ if (pqGetInt(&msgLength, 4, conn))
+ continue;
+
+ /*
+ * Try to validate message type/length here. A length less than 4 is
+ * definitely broken. Large lengths should only be believed for a few
+ * message types.
+ */
+ if (msgLength < 4)
+ {
+ handleSyncLoss(conn, id, msgLength);
+ break;
+ }
+ if (msgLength > 30000 && !VALID_LONG_MESSAGE_TYPE(id))
+ {
+ handleSyncLoss(conn, id, msgLength);
+ break;
+ }
+
+ /*
+ * Can't process if message body isn't all here yet.
+ */
+ msgLength -= 4;
+ avail = conn->inEnd - conn->inCursor;
+ if (avail < msgLength)
+ {
+ /*
+ * Before looping, enlarge the input buffer if needed to hold the
+ * whole message. See notes in parseInput.
+ */
+ if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength,
+ conn))
+ {
+ /*
+ * XXX add some better recovery code... plan is to skip over
+ * the message using its length, then report an error. For the
+ * moment, just treat this like loss of sync (which indeed it
+ * might be!)
+ */
+ handleSyncLoss(conn, id, msgLength);
+ break;
+ }
+ continue;
+ }
+
+ /*
+ * We should see V or E response to the command, but might get N
+ * and/or A notices first. We also need to swallow the final Z before
+ * returning.
+ */
+ switch (id)
+ {
+ case 'V': /* function result */
+ if (pqGetInt(actual_result_len, 4, conn))
+ continue;
+ if (*actual_result_len != -1)
+ {
+ if (result_is_int)
+ {
+ if (pqGetInt(result_buf, *actual_result_len, conn))
+ continue;
+ }
+ else
+ {
+ if (pqGetnchar((char *) result_buf,
+ *actual_result_len,
+ conn))
+ continue;
+ }
+ }
+ /* correctly finished function result message */
+ status = PGRES_COMMAND_OK;
+ break;
+ case 'E': /* error return */
+ if (pqGetErrorNotice3(conn, true))
+ continue;
+ status = PGRES_FATAL_ERROR;
+ break;
+ case 'A': /* notify message */
+ /* handle notify and go back to processing return values */
+ if (getNotify(conn))
+ continue;
+ break;
+ case 'N': /* notice */
+ /* handle notice and go back to processing return values */
+ if (pqGetErrorNotice3(conn, false))
+ continue;
+ break;
+ case 'Z': /* backend is ready for new query */
+ if (getReadyForQuery(conn))
+ continue;
+ /* consume the message and exit */
+ conn->inStart += 5 + msgLength;
+
+ /*
+ * If we already have a result object (probably an error), use
+ * that. Otherwise, if we saw a function result message,
+ * report COMMAND_OK. Otherwise, the backend violated the
+ * protocol, so complain.
+ */
+ if (!pgHavePendingResult(conn))
+ {
+ if (status == PGRES_COMMAND_OK)
+ {
+ conn->result = PQmakeEmptyPGresult(conn, status);
+ if (!conn->result)
+ {
+ libpq_append_conn_error(conn, "out of memory");
+ pqSaveErrorResult(conn);
+ }
+ }
+ else
+ {
+ libpq_append_conn_error(conn, "protocol error: no function result");
+ pqSaveErrorResult(conn);
+ }
+ }
+ return pqPrepareAsyncResult(conn);
+ case 'S': /* parameter status */
+ if (getParameterStatus(conn))
+ continue;
+ break;
+ default:
+ /* The backend violates the protocol. */
+ libpq_append_conn_error(conn, "protocol error: id=0x%x", id);
+ pqSaveErrorResult(conn);
+ /* trust the specified message length as what to skip */
+ conn->inStart += 5 + msgLength;
+ return pqPrepareAsyncResult(conn);
+ }
+
+ /* trace server-to-client message */
+ if (conn->Pfdebug)
+ pqTraceOutputMessage(conn, conn->inBuffer + conn->inStart, false);
+
+ /* Completed this message, keep going */
+ /* trust the specified message length as what to skip */
+ conn->inStart += 5 + msgLength;
+ needInput = false;
+ }
+
+ /*
+ * We fall out of the loop only upon failing to read data.
+ * conn->errorMessage has been set by pqWait or pqReadData. We want to
+ * append it to any already-received error message.
+ */
+ pqSaveErrorResult(conn);
+ return pqPrepareAsyncResult(conn);
+}
+
+
+/*
+ * Construct startup packet
+ *
+ * Returns a malloc'd packet buffer, or NULL if out of memory
+ */
+char *
+pqBuildStartupPacket3(PGconn *conn, int *packetlen,
+ const PQEnvironmentOption *options)
+{
+ char *startpacket;
+
+ *packetlen = build_startup_packet(conn, NULL, options);
+ startpacket = (char *) malloc(*packetlen);
+ if (!startpacket)
+ return NULL;
+ *packetlen = build_startup_packet(conn, startpacket, options);
+ return startpacket;
+}
+
+/*
+ * Build a startup packet given a filled-in PGconn structure.
+ *
+ * We need to figure out how much space is needed, then fill it in.
+ * To avoid duplicate logic, this routine is called twice: the first time
+ * (with packet == NULL) just counts the space needed, the second time
+ * (with packet == allocated space) fills it in. Return value is the number
+ * of bytes used.
+ */
+static int
+build_startup_packet(const PGconn *conn, char *packet,
+ const PQEnvironmentOption *options)
+{
+ int packet_len = 0;
+ const PQEnvironmentOption *next_eo;
+ const char *val;
+
+ /* Protocol version comes first. */
+ if (packet)
+ {
+ ProtocolVersion pv = pg_hton32(conn->pversion);
+
+ memcpy(packet + packet_len, &pv, sizeof(ProtocolVersion));
+ }
+ packet_len += sizeof(ProtocolVersion);
+
+ /* Add user name, database name, options */
+
+#define ADD_STARTUP_OPTION(optname, optval) \
+ do { \
+ if (packet) \
+ strcpy(packet + packet_len, optname); \
+ packet_len += strlen(optname) + 1; \
+ if (packet) \
+ strcpy(packet + packet_len, optval); \
+ packet_len += strlen(optval) + 1; \
+ } while(0)
+
+ if (conn->pguser && conn->pguser[0])
+ ADD_STARTUP_OPTION("user", conn->pguser);
+ if (conn->dbName && conn->dbName[0])
+ ADD_STARTUP_OPTION("database", conn->dbName);
+ if (conn->replication && conn->replication[0])
+ ADD_STARTUP_OPTION("replication", conn->replication);
+ if (conn->pgoptions && conn->pgoptions[0])
+ ADD_STARTUP_OPTION("options", conn->pgoptions);
+ if (conn->send_appname)
+ {
+ /* Use appname if present, otherwise use fallback */
+ val = conn->appname ? conn->appname : conn->fbappname;
+ if (val && val[0])
+ ADD_STARTUP_OPTION("application_name", val);
+ }
+
+ if (conn->client_encoding_initial && conn->client_encoding_initial[0])
+ ADD_STARTUP_OPTION("client_encoding", conn->client_encoding_initial);
+
+ /* Add any environment-driven GUC settings needed */
+ for (next_eo = options; next_eo->envName; next_eo++)
+ {
+ if ((val = getenv(next_eo->envName)) != NULL)
+ {
+ if (pg_strcasecmp(val, "default") != 0)
+ ADD_STARTUP_OPTION(next_eo->pgName, val);
+ }
+ }
+
+ /* Add trailing terminator */
+ if (packet)
+ packet[packet_len] = '\0';
+ packet_len++;
+
+ return packet_len;
+}
diff --git a/contrib/libs/libpq/src/interfaces/libpq/fe-secure-common.c b/contrib/libs/libpq/src/interfaces/libpq/fe-secure-common.c
new file mode 100644
index 0000000000..3ecc7bf615
--- /dev/null
+++ b/contrib/libs/libpq/src/interfaces/libpq/fe-secure-common.c
@@ -0,0 +1,307 @@
+/*-------------------------------------------------------------------------
+ *
+ * fe-secure-common.c
+ *
+ * common implementation-independent SSL support code
+ *
+ * While fe-secure.c contains the interfaces that the rest of libpq call, this
+ * file contains support routines that are used by the library-specific
+ * implementations such as fe-secure-openssl.c.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/interfaces/libpq/fe-secure-common.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres_fe.h"
+
+#include <arpa/inet.h>
+
+#include "fe-secure-common.h"
+
+#include "libpq-int.h"
+#include "pqexpbuffer.h"
+
+/*
+ * Check if a wildcard certificate matches the server hostname.
+ *
+ * The rule for this is:
+ * 1. We only match the '*' character as wildcard
+ * 2. We match only wildcards at the start of the string
+ * 3. The '*' character does *not* match '.', meaning that we match only
+ * a single pathname component.
+ * 4. We don't support more than one '*' in a single pattern.
+ *
+ * This is roughly in line with RFC2818, but contrary to what most browsers
+ * appear to be implementing (point 3 being the difference)
+ *
+ * Matching is always case-insensitive, since DNS is case insensitive.
+ */
+static bool
+wildcard_certificate_match(const char *pattern, const char *string)
+{
+ int lenpat = strlen(pattern);
+ int lenstr = strlen(string);
+
+ /* If we don't start with a wildcard, it's not a match (rule 1 & 2) */
+ if (lenpat < 3 ||
+ pattern[0] != '*' ||
+ pattern[1] != '.')
+ return false;
+
+ /* If pattern is longer than the string, we can never match */
+ if (lenpat > lenstr)
+ return false;
+
+ /*
+ * If string does not end in pattern (minus the wildcard), we don't match
+ */
+ if (pg_strcasecmp(pattern + 1, string + lenstr - lenpat + 1) != 0)
+ return false;
+
+ /*
+ * If there is a dot left of where the pattern started to match, we don't
+ * match (rule 3)
+ */
+ if (strchr(string, '.') < string + lenstr - lenpat)
+ return false;
+
+ /* String ended with pattern, and didn't have a dot before, so we match */
+ return true;
+}
+
+/*
+ * Check if a name from a server's certificate matches the peer's hostname.
+ *
+ * Returns 1 if the name matches, and 0 if it does not. On error, returns
+ * -1, and sets the libpq error message.
+ *
+ * The name extracted from the certificate is returned in *store_name. The
+ * caller is responsible for freeing it.
+ */
+int
+pq_verify_peer_name_matches_certificate_name(PGconn *conn,
+ const char *namedata, size_t namelen,
+ char **store_name)
+{
+ char *name;
+ int result;
+ char *host = conn->connhost[conn->whichhost].host;
+
+ *store_name = NULL;
+
+ if (!(host && host[0] != '\0'))
+ {
+ libpq_append_conn_error(conn, "host name must be specified");
+ return -1;
+ }
+
+ /*
+ * There is no guarantee the string returned from the certificate is
+ * NULL-terminated, so make a copy that is.
+ */
+ name = malloc(namelen + 1);
+ if (name == NULL)
+ {
+ libpq_append_conn_error(conn, "out of memory");
+ return -1;
+ }
+ memcpy(name, namedata, namelen);
+ name[namelen] = '\0';
+
+ /*
+ * Reject embedded NULLs in certificate common or alternative name to
+ * prevent attacks like CVE-2009-4034.
+ */
+ if (namelen != strlen(name))
+ {
+ free(name);
+ libpq_append_conn_error(conn, "SSL certificate's name contains embedded null");
+ return -1;
+ }
+
+ if (pg_strcasecmp(name, host) == 0)
+ {
+ /* Exact name match */
+ result = 1;
+ }
+ else if (wildcard_certificate_match(name, host))
+ {
+ /* Matched wildcard name */
+ result = 1;
+ }
+ else
+ {
+ result = 0;
+ }
+
+ *store_name = name;
+ return result;
+}
+
+/*
+ * Check if an IP address from a server's certificate matches the peer's
+ * hostname (which must itself be an IPv4/6 address).
+ *
+ * Returns 1 if the address matches, and 0 if it does not. On error, returns
+ * -1, and sets the libpq error message.
+ *
+ * A string representation of the certificate's IP address is returned in
+ * *store_name. The caller is responsible for freeing it.
+ */
+int
+pq_verify_peer_name_matches_certificate_ip(PGconn *conn,
+ const unsigned char *ipdata,
+ size_t iplen,
+ char **store_name)
+{
+ char *addrstr;
+ int match = 0;
+ char *host = conn->connhost[conn->whichhost].host;
+ int family;
+ char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
+ char sebuf[PG_STRERROR_R_BUFLEN];
+
+ *store_name = NULL;
+
+ if (!(host && host[0] != '\0'))
+ {
+ libpq_append_conn_error(conn, "host name must be specified");
+ return -1;
+ }
+
+ /*
+ * The data from the certificate is in network byte order. Convert our
+ * host string to network-ordered bytes as well, for comparison. (The host
+ * string isn't guaranteed to actually be an IP address, so if this
+ * conversion fails we need to consider it a mismatch rather than an
+ * error.)
+ */
+ if (iplen == 4)
+ {
+ /* IPv4 */
+ struct in_addr addr;
+
+ family = AF_INET;
+
+ /*
+ * The use of inet_aton() is deliberate; we accept alternative IPv4
+ * address notations that are accepted by inet_aton() but not
+ * inet_pton() as server addresses.
+ */
+ if (inet_aton(host, &addr))
+ {
+ if (memcmp(ipdata, &addr.s_addr, iplen) == 0)
+ match = 1;
+ }
+ }
+
+ /*
+ * If they don't have inet_pton(), skip this. Then, an IPv6 address in a
+ * certificate will cause an error.
+ */
+#ifdef HAVE_INET_PTON
+ else if (iplen == 16)
+ {
+ /* IPv6 */
+ struct in6_addr addr;
+
+ family = AF_INET6;
+
+ if (inet_pton(AF_INET6, host, &addr) == 1)
+ {
+ if (memcmp(ipdata, &addr.s6_addr, iplen) == 0)
+ match = 1;
+ }
+ }
+#endif
+ else
+ {
+ /*
+ * Not IPv4 or IPv6. We could ignore the field, but leniency seems
+ * wrong given the subject matter.
+ */
+ libpq_append_conn_error(conn, "certificate contains IP address with invalid length %zu",
+ iplen);
+ return -1;
+ }
+
+ /* Generate a human-readable representation of the certificate's IP. */
+ addrstr = pg_inet_net_ntop(family, ipdata, 8 * iplen, tmp, sizeof(tmp));
+ if (!addrstr)
+ {
+ libpq_append_conn_error(conn, "could not convert certificate's IP address to string: %s",
+ strerror_r(errno, sebuf, sizeof(sebuf)));
+ return -1;
+ }
+
+ *store_name = strdup(addrstr);
+ return match;
+}
+
+/*
+ * Verify that the server certificate matches the hostname we connected to.
+ *
+ * The certificate's Common Name and Subject Alternative Names are considered.
+ */
+bool
+pq_verify_peer_name_matches_certificate(PGconn *conn)
+{
+ char *host = conn->connhost[conn->whichhost].host;
+ int rc;
+ int names_examined = 0;
+ char *first_name = NULL;
+
+ /*
+ * If told not to verify the peer name, don't do it. Return true
+ * indicating that the verification was successful.
+ */
+ if (strcmp(conn->sslmode, "verify-full") != 0)
+ return true;
+
+ /* Check that we have a hostname to compare with. */
+ if (!(host && host[0] != '\0'))
+ {
+ libpq_append_conn_error(conn, "host name must be specified for a verified SSL connection");
+ return false;
+ }
+
+ rc = pgtls_verify_peer_name_matches_certificate_guts(conn, &names_examined, &first_name);
+
+ if (rc == 0)
+ {
+ /*
+ * No match. Include the name from the server certificate in the error
+ * message, to aid debugging broken configurations. If there are
+ * multiple names, only print the first one to avoid an overly long
+ * error message.
+ */
+ if (names_examined > 1)
+ {
+ appendPQExpBuffer(&conn->errorMessage,
+ libpq_ngettext("server certificate for \"%s\" (and %d other name) does not match host name \"%s\"",
+ "server certificate for \"%s\" (and %d other names) does not match host name \"%s\"",
+ names_examined - 1),
+ first_name, names_examined - 1, host);
+ appendPQExpBufferChar(&conn->errorMessage, '\n');
+ }
+ else if (names_examined == 1)
+ {
+ libpq_append_conn_error(conn, "server certificate for \"%s\" does not match host name \"%s\"",
+ first_name, host);
+ }
+ else
+ {
+ libpq_append_conn_error(conn, "could not get server's host name from server certificate");
+ }
+ }
+
+ /* clean up */
+ free(first_name);
+
+ return (rc == 1);
+}
diff --git a/contrib/libs/libpq/src/interfaces/libpq/fe-secure-common.h b/contrib/libs/libpq/src/interfaces/libpq/fe-secure-common.h
new file mode 100644
index 0000000000..e048f97b01
--- /dev/null
+++ b/contrib/libs/libpq/src/interfaces/libpq/fe-secure-common.h
@@ -0,0 +1,30 @@
+/*-------------------------------------------------------------------------
+ *
+ * fe-secure-common.h
+ *
+ * common implementation-independent SSL support code
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/interfaces/libpq/fe-secure-common.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FE_SECURE_COMMON_H
+#define FE_SECURE_COMMON_H
+
+#include "libpq-fe.h"
+
+extern int pq_verify_peer_name_matches_certificate_name(PGconn *conn,
+ const char *namedata, size_t namelen,
+ char **store_name);
+extern int pq_verify_peer_name_matches_certificate_ip(PGconn *conn,
+ const unsigned char *ipdata,
+ size_t iplen,
+ char **store_name);
+extern bool pq_verify_peer_name_matches_certificate(PGconn *conn);
+
+#endif /* FE_SECURE_COMMON_H */
diff --git a/contrib/libs/libpq/src/interfaces/libpq/fe-secure-openssl.c b/contrib/libs/libpq/src/interfaces/libpq/fe-secure-openssl.c
new file mode 100644
index 0000000000..5c220e0e69
--- /dev/null
+++ b/contrib/libs/libpq/src/interfaces/libpq/fe-secure-openssl.c
@@ -0,0 +1,2062 @@
+/*-------------------------------------------------------------------------
+ *
+ * fe-secure-openssl.c
+ * OpenSSL support
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/interfaces/libpq/fe-secure-openssl.c
+ *
+ * NOTES
+ *
+ * We don't provide informational callbacks here (like
+ * info_cb() in be-secure-openssl.c), since there's no good mechanism to
+ * display such information to the user.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres_fe.h"
+
+#include <signal.h>
+#include <fcntl.h>
+#include <ctype.h>
+
+#include "libpq-fe.h"
+#include "fe-auth.h"
+#include "fe-secure-common.h"
+#include "libpq-int.h"
+
+#ifdef WIN32
+#include "win32.h"
+#else
+#include <sys/socket.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#endif
+
+#include <sys/stat.h>
+
+#ifdef ENABLE_THREAD_SAFETY
+#ifdef WIN32
+#include "pthread-win32.h"
+#else
+#include <pthread.h>
+#endif
+#endif
+
+/*
+ * These SSL-related #includes must come after all system-provided headers.
+ * This ensures that OpenSSL can take care of conflicts with Windows'
+ * <wincrypt.h> by #undef'ing the conflicting macros. (We don't directly
+ * include <wincrypt.h>, but some other Windows headers do.)
+ */
+#include "common/openssl.h"
+#include <openssl/conf.h>
+#ifdef USE_SSL_ENGINE
+#include <openssl/engine.h>
+#endif
+#include <openssl/x509v3.h>
+
+
+static int verify_cb(int ok, X509_STORE_CTX *ctx);
+static int openssl_verify_peer_name_matches_certificate_name(PGconn *conn,
+ ASN1_STRING *name_entry,
+ char **store_name);
+static int openssl_verify_peer_name_matches_certificate_ip(PGconn *conn,
+ ASN1_OCTET_STRING *addr_entry,
+ char **store_name);
+static void destroy_ssl_system(void);
+static int initialize_SSL(PGconn *conn);
+static PostgresPollingStatusType open_client_SSL(PGconn *conn);
+static char *SSLerrmessage(unsigned long ecode);
+static void SSLerrfree(char *buf);
+static int PQssl_passwd_cb(char *buf, int size, int rwflag, void *userdata);
+
+static int my_sock_read(BIO *h, char *buf, int size);
+static int my_sock_write(BIO *h, const char *buf, int size);
+static BIO_METHOD *my_BIO_s_socket(void);
+static int my_SSL_set_fd(PGconn *conn, int fd);
+
+
+static bool pq_init_ssl_lib = true;
+static bool pq_init_crypto_lib = true;
+
+static bool ssl_lib_initialized = false;
+
+#ifdef ENABLE_THREAD_SAFETY
+static long crypto_open_connections = 0;
+
+#ifndef WIN32
+static pthread_mutex_t ssl_config_mutex = PTHREAD_MUTEX_INITIALIZER;
+#else
+static pthread_mutex_t ssl_config_mutex = NULL;
+static long win32_ssl_create_mutex = 0;
+#endif
+#endif /* ENABLE_THREAD_SAFETY */
+
+static PQsslKeyPassHook_OpenSSL_type PQsslKeyPassHook = NULL;
+static int ssl_protocol_version_to_openssl(const char *protocol);
+
+/* ------------------------------------------------------------ */
+/* Procedures common to all secure sessions */
+/* ------------------------------------------------------------ */
+
+void
+pgtls_init_library(bool do_ssl, int do_crypto)
+{
+#ifdef ENABLE_THREAD_SAFETY
+
+ /*
+ * Disallow changing the flags while we have open connections, else we'd
+ * get completely confused.
+ */
+ if (crypto_open_connections != 0)
+ return;
+#endif
+
+ pq_init_ssl_lib = do_ssl;
+ pq_init_crypto_lib = do_crypto;
+}
+
+PostgresPollingStatusType
+pgtls_open_client(PGconn *conn)
+{
+ /* First time through? */
+ if (conn->ssl == NULL)
+ {
+ /*
+ * Create a connection-specific SSL object, and load client
+ * certificate, private key, and trusted CA certs.
+ */
+ if (initialize_SSL(conn) != 0)
+ {
+ /* initialize_SSL already put a message in conn->errorMessage */
+ pgtls_close(conn);
+ return PGRES_POLLING_FAILED;
+ }
+ }
+
+ /* Begin or continue the actual handshake */
+ return open_client_SSL(conn);
+}
+
+ssize_t
+pgtls_read(PGconn *conn, void *ptr, size_t len)
+{
+ ssize_t n;
+ int result_errno = 0;
+ char sebuf[PG_STRERROR_R_BUFLEN];
+ int err;
+ unsigned long ecode;
+
+rloop:
+
+ /*
+ * Prepare to call SSL_get_error() by clearing thread's OpenSSL error
+ * queue. In general, the current thread's error queue must be empty
+ * before the TLS/SSL I/O operation is attempted, or SSL_get_error() will
+ * not work reliably. Since the possibility exists that other OpenSSL
+ * clients running in the same thread but not under our control will fail
+ * to call ERR_get_error() themselves (after their own I/O operations),
+ * pro-actively clear the per-thread error queue now.
+ */
+ SOCK_ERRNO_SET(0);
+ ERR_clear_error();
+ n = SSL_read(conn->ssl, ptr, len);
+ err = SSL_get_error(conn->ssl, n);
+
+ /*
+ * Other clients of OpenSSL may fail to call ERR_get_error(), but we
+ * always do, so as to not cause problems for OpenSSL clients that don't
+ * call ERR_clear_error() defensively. Be sure that this happens by
+ * calling now. SSL_get_error() relies on the OpenSSL per-thread error
+ * queue being intact, so this is the earliest possible point
+ * ERR_get_error() may be called.
+ */
+ ecode = (err != SSL_ERROR_NONE || n < 0) ? ERR_get_error() : 0;
+ switch (err)
+ {
+ case SSL_ERROR_NONE:
+ if (n < 0)
+ {
+ /* Not supposed to happen, so we don't translate the msg */
+ appendPQExpBufferStr(&conn->errorMessage,
+ "SSL_read failed but did not provide error information\n");
+ /* assume the connection is broken */
+ result_errno = ECONNRESET;
+ }
+ break;
+ case SSL_ERROR_WANT_READ:
+ n = 0;
+ break;
+ case SSL_ERROR_WANT_WRITE:
+
+ /*
+ * Returning 0 here would cause caller to wait for read-ready,
+ * which is not correct since what SSL wants is wait for
+ * write-ready. The former could get us stuck in an infinite
+ * wait, so don't risk it; busy-loop instead.
+ */
+ goto rloop;
+ case SSL_ERROR_SYSCALL:
+ if (n < 0)
+ {
+ result_errno = SOCK_ERRNO;
+ if (result_errno == EPIPE ||
+ result_errno == ECONNRESET)
+ libpq_append_conn_error(conn, "server closed the connection unexpectedly\n"
+ "\tThis probably means the server terminated abnormally\n"
+ "\tbefore or while processing the request.");
+ else
+ libpq_append_conn_error(conn, "SSL SYSCALL error: %s",
+ SOCK_STRERROR(result_errno,
+ sebuf, sizeof(sebuf)));
+ }
+ else
+ {
+ libpq_append_conn_error(conn, "SSL SYSCALL error: EOF detected");
+ /* assume the connection is broken */
+ result_errno = ECONNRESET;
+ n = -1;
+ }
+ break;
+ case SSL_ERROR_SSL:
+ {
+ char *errm = SSLerrmessage(ecode);
+
+ libpq_append_conn_error(conn, "SSL error: %s", errm);
+ SSLerrfree(errm);
+ /* assume the connection is broken */
+ result_errno = ECONNRESET;
+ n = -1;
+ break;
+ }
+ case SSL_ERROR_ZERO_RETURN:
+
+ /*
+ * Per OpenSSL documentation, this error code is only returned for
+ * a clean connection closure, so we should not report it as a
+ * server crash.
+ */
+ libpq_append_conn_error(conn, "SSL connection has been closed unexpectedly");
+ result_errno = ECONNRESET;
+ n = -1;
+ break;
+ default:
+ libpq_append_conn_error(conn, "unrecognized SSL error code: %d", err);
+ /* assume the connection is broken */
+ result_errno = ECONNRESET;
+ n = -1;
+ break;
+ }
+
+ /* ensure we return the intended errno to caller */
+ SOCK_ERRNO_SET(result_errno);
+
+ return n;
+}
+
+bool
+pgtls_read_pending(PGconn *conn)
+{
+ return SSL_pending(conn->ssl) > 0;
+}
+
+ssize_t
+pgtls_write(PGconn *conn, const void *ptr, size_t len)
+{
+ ssize_t n;
+ int result_errno = 0;
+ char sebuf[PG_STRERROR_R_BUFLEN];
+ int err;
+ unsigned long ecode;
+
+ SOCK_ERRNO_SET(0);
+ ERR_clear_error();
+ n = SSL_write(conn->ssl, ptr, len);
+ err = SSL_get_error(conn->ssl, n);
+ ecode = (err != SSL_ERROR_NONE || n < 0) ? ERR_get_error() : 0;
+ switch (err)
+ {
+ case SSL_ERROR_NONE:
+ if (n < 0)
+ {
+ /* Not supposed to happen, so we don't translate the msg */
+ appendPQExpBufferStr(&conn->errorMessage,
+ "SSL_write failed but did not provide error information\n");
+ /* assume the connection is broken */
+ result_errno = ECONNRESET;
+ }
+ break;
+ case SSL_ERROR_WANT_READ:
+
+ /*
+ * Returning 0 here causes caller to wait for write-ready, which
+ * is not really the right thing, but it's the best we can do.
+ */
+ n = 0;
+ break;
+ case SSL_ERROR_WANT_WRITE:
+ n = 0;
+ break;
+ case SSL_ERROR_SYSCALL:
+ if (n < 0)
+ {
+ result_errno = SOCK_ERRNO;
+ if (result_errno == EPIPE || result_errno == ECONNRESET)
+ libpq_append_conn_error(conn, "server closed the connection unexpectedly\n"
+ "\tThis probably means the server terminated abnormally\n"
+ "\tbefore or while processing the request.");
+ else
+ libpq_append_conn_error(conn, "SSL SYSCALL error: %s",
+ SOCK_STRERROR(result_errno,
+ sebuf, sizeof(sebuf)));
+ }
+ else
+ {
+ libpq_append_conn_error(conn, "SSL SYSCALL error: EOF detected");
+ /* assume the connection is broken */
+ result_errno = ECONNRESET;
+ n = -1;
+ }
+ break;
+ case SSL_ERROR_SSL:
+ {
+ char *errm = SSLerrmessage(ecode);
+
+ libpq_append_conn_error(conn, "SSL error: %s", errm);
+ SSLerrfree(errm);
+ /* assume the connection is broken */
+ result_errno = ECONNRESET;
+ n = -1;
+ break;
+ }
+ case SSL_ERROR_ZERO_RETURN:
+
+ /*
+ * Per OpenSSL documentation, this error code is only returned for
+ * a clean connection closure, so we should not report it as a
+ * server crash.
+ */
+ libpq_append_conn_error(conn, "SSL connection has been closed unexpectedly");
+ result_errno = ECONNRESET;
+ n = -1;
+ break;
+ default:
+ libpq_append_conn_error(conn, "unrecognized SSL error code: %d", err);
+ /* assume the connection is broken */
+ result_errno = ECONNRESET;
+ n = -1;
+ break;
+ }
+
+ /* ensure we return the intended errno to caller */
+ SOCK_ERRNO_SET(result_errno);
+
+ return n;
+}
+
+#if defined(HAVE_X509_GET_SIGNATURE_NID) || defined(HAVE_X509_GET_SIGNATURE_INFO)
+char *
+pgtls_get_peer_certificate_hash(PGconn *conn, size_t *len)
+{
+ X509 *peer_cert;
+ const EVP_MD *algo_type;
+ unsigned char hash[EVP_MAX_MD_SIZE]; /* size for SHA-512 */
+ unsigned int hash_size;
+ int algo_nid;
+ char *cert_hash;
+
+ *len = 0;
+
+ if (!conn->peer)
+ return NULL;
+
+ peer_cert = conn->peer;
+
+ /*
+ * Get the signature algorithm of the certificate to determine the hash
+ * algorithm to use for the result. Prefer X509_get_signature_info(),
+ * introduced in OpenSSL 1.1.1, which can handle RSA-PSS signatures.
+ */
+#if HAVE_X509_GET_SIGNATURE_INFO
+ if (!X509_get_signature_info(peer_cert, &algo_nid, NULL, NULL, NULL))
+#else
+ if (!OBJ_find_sigid_algs(X509_get_signature_nid(peer_cert),
+ &algo_nid, NULL))
+#endif
+ {
+ libpq_append_conn_error(conn, "could not determine server certificate signature algorithm");
+ return NULL;
+ }
+
+ /*
+ * The TLS server's certificate bytes need to be hashed with SHA-256 if
+ * its signature algorithm is MD5 or SHA-1 as per RFC 5929
+ * (https://tools.ietf.org/html/rfc5929#section-4.1). If something else
+ * is used, the same hash as the signature algorithm is used.
+ */
+ switch (algo_nid)
+ {
+ case NID_md5:
+ case NID_sha1:
+ algo_type = EVP_sha256();
+ break;
+ default:
+ algo_type = EVP_get_digestbynid(algo_nid);
+ if (algo_type == NULL)
+ {
+ libpq_append_conn_error(conn, "could not find digest for NID %s",
+ OBJ_nid2sn(algo_nid));
+ return NULL;
+ }
+ break;
+ }
+
+ if (!X509_digest(peer_cert, algo_type, hash, &hash_size))
+ {
+ libpq_append_conn_error(conn, "could not generate peer certificate hash");
+ return NULL;
+ }
+
+ /* save result */
+ cert_hash = malloc(hash_size);
+ if (cert_hash == NULL)
+ {
+ libpq_append_conn_error(conn, "out of memory");
+ return NULL;
+ }
+ memcpy(cert_hash, hash, hash_size);
+ *len = hash_size;
+
+ return cert_hash;
+}
+#endif /* HAVE_X509_GET_SIGNATURE_NID */
+
+/* ------------------------------------------------------------ */
+/* OpenSSL specific code */
+/* ------------------------------------------------------------ */
+
+/*
+ * Certificate verification callback
+ *
+ * This callback allows us to log intermediate problems during
+ * verification, but there doesn't seem to be a clean way to get
+ * our PGconn * structure. So we can't log anything!
+ *
+ * This callback also allows us to override the default acceptance
+ * criteria (e.g., accepting self-signed or expired certs), but
+ * for now we accept the default checks.
+ */
+static int
+verify_cb(int ok, X509_STORE_CTX *ctx)
+{
+ return ok;
+}
+
+#ifdef HAVE_SSL_CTX_SET_CERT_CB
+/*
+ * Certificate selection callback
+ *
+ * This callback lets us choose the client certificate we send to the server
+ * after seeing its CertificateRequest. We only support sending a single
+ * hard-coded certificate via sslcert, so we don't actually set any certificates
+ * here; we just use it to record whether or not the server has actually asked
+ * for one and whether we have one to send.
+ */
+static int
+cert_cb(SSL *ssl, void *arg)
+{
+ PGconn *conn = arg;
+
+ conn->ssl_cert_requested = true;
+
+ /* Do we have a certificate loaded to send back? */
+ if (SSL_get_certificate(ssl))
+ conn->ssl_cert_sent = true;
+
+ /*
+ * Tell OpenSSL that the callback succeeded; we're not required to
+ * actually make any changes to the SSL handle.
+ */
+ return 1;
+}
+#endif
+
+/*
+ * OpenSSL-specific wrapper around
+ * pq_verify_peer_name_matches_certificate_name(), converting the ASN1_STRING
+ * into a plain C string.
+ */
+static int
+openssl_verify_peer_name_matches_certificate_name(PGconn *conn, ASN1_STRING *name_entry,
+ char **store_name)
+{
+ int len;
+ const unsigned char *namedata;
+
+ /* Should not happen... */
+ if (name_entry == NULL)
+ {
+ libpq_append_conn_error(conn, "SSL certificate's name entry is missing");
+ return -1;
+ }
+
+ /*
+ * GEN_DNS can be only IA5String, equivalent to US ASCII.
+ */
+#ifdef HAVE_ASN1_STRING_GET0_DATA
+ namedata = ASN1_STRING_get0_data(name_entry);
+#else
+ namedata = ASN1_STRING_data(name_entry);
+#endif
+ len = ASN1_STRING_length(name_entry);
+
+ /* OK to cast from unsigned to plain char, since it's all ASCII. */
+ return pq_verify_peer_name_matches_certificate_name(conn, (const char *) namedata, len, store_name);
+}
+
+/*
+ * OpenSSL-specific wrapper around
+ * pq_verify_peer_name_matches_certificate_ip(), converting the
+ * ASN1_OCTET_STRING into a plain C string.
+ */
+static int
+openssl_verify_peer_name_matches_certificate_ip(PGconn *conn,
+ ASN1_OCTET_STRING *addr_entry,
+ char **store_name)
+{
+ int len;
+ const unsigned char *addrdata;
+
+ /* Should not happen... */
+ if (addr_entry == NULL)
+ {
+ libpq_append_conn_error(conn, "SSL certificate's address entry is missing");
+ return -1;
+ }
+
+ /*
+ * GEN_IPADD is an OCTET STRING containing an IP address in network byte
+ * order.
+ */
+#ifdef HAVE_ASN1_STRING_GET0_DATA
+ addrdata = ASN1_STRING_get0_data(addr_entry);
+#else
+ addrdata = ASN1_STRING_data(addr_entry);
+#endif
+ len = ASN1_STRING_length(addr_entry);
+
+ return pq_verify_peer_name_matches_certificate_ip(conn, addrdata, len, store_name);
+}
+
+static bool
+is_ip_address(const char *host)
+{
+ struct in_addr dummy4;
+#ifdef HAVE_INET_PTON
+ struct in6_addr dummy6;
+#endif
+
+ return inet_aton(host, &dummy4)
+#ifdef HAVE_INET_PTON
+ || (inet_pton(AF_INET6, host, &dummy6) == 1)
+#endif
+ ;
+}
+
+/*
+ * Verify that the server certificate matches the hostname we connected to.
+ *
+ * The certificate's Common Name and Subject Alternative Names are considered.
+ */
+int
+pgtls_verify_peer_name_matches_certificate_guts(PGconn *conn,
+ int *names_examined,
+ char **first_name)
+{
+ STACK_OF(GENERAL_NAME) * peer_san;
+ int i;
+ int rc = 0;
+ char *host = conn->connhost[conn->whichhost].host;
+ int host_type;
+ bool check_cn = true;
+
+ Assert(host && host[0]); /* should be guaranteed by caller */
+
+ /*
+ * We try to match the NSS behavior here, which is a slight departure from
+ * the spec but seems to make more intuitive sense:
+ *
+ * If connhost contains a DNS name, and the certificate's SANs contain any
+ * dNSName entries, then we'll ignore the Subject Common Name entirely;
+ * otherwise, we fall back to checking the CN. (This behavior matches the
+ * RFC.)
+ *
+ * If connhost contains an IP address, and the SANs contain iPAddress
+ * entries, we again ignore the CN. Otherwise, we allow the CN to match,
+ * EVEN IF there is a dNSName in the SANs. (RFC 6125 prohibits this: "A
+ * client MUST NOT seek a match for a reference identifier of CN-ID if the
+ * presented identifiers include a DNS-ID, SRV-ID, URI-ID, or any
+ * application-specific identifier types supported by the client.")
+ *
+ * NOTE: Prior versions of libpq did not consider iPAddress entries at
+ * all, so this new behavior might break a certificate that has different
+ * IP addresses in the Subject CN and the SANs.
+ */
+ if (is_ip_address(host))
+ host_type = GEN_IPADD;
+ else
+ host_type = GEN_DNS;
+
+ /*
+ * First, get the Subject Alternative Names (SANs) from the certificate,
+ * and compare them against the originally given hostname.
+ */
+ peer_san = (STACK_OF(GENERAL_NAME) *)
+ X509_get_ext_d2i(conn->peer, NID_subject_alt_name, NULL, NULL);
+
+ if (peer_san)
+ {
+ int san_len = sk_GENERAL_NAME_num(peer_san);
+
+ for (i = 0; i < san_len; i++)
+ {
+ const GENERAL_NAME *name = sk_GENERAL_NAME_value(peer_san, i);
+ char *alt_name = NULL;
+
+ if (name->type == host_type)
+ {
+ /*
+ * This SAN is of the same type (IP or DNS) as our host name,
+ * so don't allow a fallback check of the CN.
+ */
+ check_cn = false;
+ }
+
+ if (name->type == GEN_DNS)
+ {
+ (*names_examined)++;
+ rc = openssl_verify_peer_name_matches_certificate_name(conn,
+ name->d.dNSName,
+ &alt_name);
+ }
+ else if (name->type == GEN_IPADD)
+ {
+ (*names_examined)++;
+ rc = openssl_verify_peer_name_matches_certificate_ip(conn,
+ name->d.iPAddress,
+ &alt_name);
+ }
+
+ if (alt_name)
+ {
+ if (!*first_name)
+ *first_name = alt_name;
+ else
+ free(alt_name);
+ }
+
+ if (rc != 0)
+ {
+ /*
+ * Either we hit an error or a match, and either way we should
+ * not fall back to the CN.
+ */
+ check_cn = false;
+ break;
+ }
+ }
+ sk_GENERAL_NAME_pop_free(peer_san, GENERAL_NAME_free);
+ }
+
+ /*
+ * If there is no subjectAltName extension of the matching type, check the
+ * Common Name.
+ *
+ * (Per RFC 2818 and RFC 6125, if the subjectAltName extension of type
+ * dNSName is present, the CN must be ignored. We break this rule if host
+ * is an IP address; see the comment above.)
+ */
+ if (check_cn)
+ {
+ X509_NAME *subject_name;
+
+ subject_name = X509_get_subject_name(conn->peer);
+ if (subject_name != NULL)
+ {
+ int cn_index;
+
+ cn_index = X509_NAME_get_index_by_NID(subject_name,
+ NID_commonName, -1);
+ if (cn_index >= 0)
+ {
+ char *common_name = NULL;
+
+ (*names_examined)++;
+ rc = openssl_verify_peer_name_matches_certificate_name(conn,
+ X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subject_name, cn_index)),
+ &common_name);
+
+ if (common_name)
+ {
+ if (!*first_name)
+ *first_name = common_name;
+ else
+ free(common_name);
+ }
+ }
+ }
+ }
+
+ return rc;
+}
+
+#if defined(ENABLE_THREAD_SAFETY) && defined(HAVE_CRYPTO_LOCK)
+/*
+ * Callback functions for OpenSSL internal locking. (OpenSSL 1.1.0
+ * does its own locking, and doesn't need these anymore. The
+ * CRYPTO_lock() function was removed in 1.1.0, when the callbacks
+ * were made obsolete, so we assume that if CRYPTO_lock() exists,
+ * the callbacks are still required.)
+ */
+
+static unsigned long
+pq_threadidcallback(void)
+{
+ /*
+ * This is not standards-compliant. pthread_self() returns pthread_t, and
+ * shouldn't be cast to unsigned long, but CRYPTO_set_id_callback requires
+ * it, so we have to do it.
+ */
+ return (unsigned long) pthread_self();
+}
+
+static pthread_mutex_t *pq_lockarray;
+
+static void
+pq_lockingcallback(int mode, int n, const char *file, int line)
+{
+ /*
+ * There's no way to report a mutex-primitive failure, so we just Assert
+ * in development builds, and ignore any errors otherwise. Fortunately
+ * this is all obsolete in modern OpenSSL.
+ */
+ if (mode & CRYPTO_LOCK)
+ {
+ if (pthread_mutex_lock(&pq_lockarray[n]))
+ Assert(false);
+ }
+ else
+ {
+ if (pthread_mutex_unlock(&pq_lockarray[n]))
+ Assert(false);
+ }
+}
+#endif /* ENABLE_THREAD_SAFETY && HAVE_CRYPTO_LOCK */
+
+/*
+ * Initialize SSL library.
+ *
+ * In threadsafe mode, this includes setting up libcrypto callback functions
+ * to do thread locking.
+ *
+ * If the caller has told us (through PQinitOpenSSL) that he's taking care
+ * of libcrypto, we expect that callbacks are already set, and won't try to
+ * override it.
+ */
+int
+pgtls_init(PGconn *conn, bool do_ssl, bool do_crypto)
+{
+#ifdef ENABLE_THREAD_SAFETY
+#ifdef WIN32
+ /* Also see similar code in fe-connect.c, default_threadlock() */
+ if (ssl_config_mutex == NULL)
+ {
+ while (InterlockedExchange(&win32_ssl_create_mutex, 1) == 1)
+ /* loop, another thread own the lock */ ;
+ if (ssl_config_mutex == NULL)
+ {
+ if (pthread_mutex_init(&ssl_config_mutex, NULL))
+ return -1;
+ }
+ InterlockedExchange(&win32_ssl_create_mutex, 0);
+ }
+#endif
+ if (pthread_mutex_lock(&ssl_config_mutex))
+ return -1;
+
+#ifdef HAVE_CRYPTO_LOCK
+ if (pq_init_crypto_lib)
+ {
+ /*
+ * If necessary, set up an array to hold locks for libcrypto.
+ * libcrypto will tell us how big to make this array.
+ */
+ if (pq_lockarray == NULL)
+ {
+ int i;
+
+ pq_lockarray = malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks());
+ if (!pq_lockarray)
+ {
+ pthread_mutex_unlock(&ssl_config_mutex);
+ return -1;
+ }
+ for (i = 0; i < CRYPTO_num_locks(); i++)
+ {
+ if (pthread_mutex_init(&pq_lockarray[i], NULL))
+ {
+ free(pq_lockarray);
+ pq_lockarray = NULL;
+ pthread_mutex_unlock(&ssl_config_mutex);
+ return -1;
+ }
+ }
+ }
+
+ if (do_crypto && !conn->crypto_loaded)
+ {
+ if (crypto_open_connections++ == 0)
+ {
+ /*
+ * These are only required for threaded libcrypto
+ * applications, but make sure we don't stomp on them if
+ * they're already set.
+ */
+ if (CRYPTO_get_id_callback() == NULL)
+ CRYPTO_set_id_callback(pq_threadidcallback);
+ if (CRYPTO_get_locking_callback() == NULL)
+ CRYPTO_set_locking_callback(pq_lockingcallback);
+ }
+
+ conn->crypto_loaded = true;
+ }
+ }
+#endif /* HAVE_CRYPTO_LOCK */
+#endif /* ENABLE_THREAD_SAFETY */
+
+ if (!ssl_lib_initialized && do_ssl)
+ {
+ if (pq_init_ssl_lib)
+ {
+#ifdef HAVE_OPENSSL_INIT_SSL
+ OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
+#else
+ OPENSSL_config(NULL);
+ SSL_library_init();
+ SSL_load_error_strings();
+#endif
+ }
+ ssl_lib_initialized = true;
+ }
+
+#ifdef ENABLE_THREAD_SAFETY
+ pthread_mutex_unlock(&ssl_config_mutex);
+#endif
+ return 0;
+}
+
+/*
+ * This function is needed because if the libpq library is unloaded
+ * from the application, the callback functions will no longer exist when
+ * libcrypto is used by other parts of the system. For this reason,
+ * we unregister the callback functions when the last libpq
+ * connection is closed. (The same would apply for OpenSSL callbacks
+ * if we had any.)
+ *
+ * Callbacks are only set when we're compiled in threadsafe mode, so
+ * we only need to remove them in this case. They are also not needed
+ * with OpenSSL 1.1.0 anymore.
+ */
+static void
+destroy_ssl_system(void)
+{
+#if defined(ENABLE_THREAD_SAFETY) && defined(HAVE_CRYPTO_LOCK)
+ /* Mutex is created in pgtls_init() */
+ if (pthread_mutex_lock(&ssl_config_mutex))
+ return;
+
+ if (pq_init_crypto_lib && crypto_open_connections > 0)
+ --crypto_open_connections;
+
+ if (pq_init_crypto_lib && crypto_open_connections == 0)
+ {
+ /*
+ * No connections left, unregister libcrypto callbacks, if no one
+ * registered different ones in the meantime.
+ */
+ if (CRYPTO_get_locking_callback() == pq_lockingcallback)
+ CRYPTO_set_locking_callback(NULL);
+ if (CRYPTO_get_id_callback() == pq_threadidcallback)
+ CRYPTO_set_id_callback(NULL);
+
+ /*
+ * We don't free the lock array. If we get another connection in this
+ * process, we will just re-use them with the existing mutexes.
+ *
+ * This means we leak a little memory on repeated load/unload of the
+ * library.
+ */
+ }
+
+ pthread_mutex_unlock(&ssl_config_mutex);
+#endif
+}
+
+/*
+ * Create per-connection SSL object, and load the client certificate,
+ * private key, and trusted CA certs.
+ *
+ * Returns 0 if OK, -1 on failure (with a message in conn->errorMessage).
+ */
+static int
+initialize_SSL(PGconn *conn)
+{
+ SSL_CTX *SSL_context;
+ struct stat buf;
+ char homedir[MAXPGPATH];
+ char fnbuf[MAXPGPATH];
+ char sebuf[PG_STRERROR_R_BUFLEN];
+ bool have_homedir;
+ bool have_cert;
+ bool have_rootcert;
+ EVP_PKEY *pkey = NULL;
+
+ /*
+ * We'll need the home directory if any of the relevant parameters are
+ * defaulted. If pqGetHomeDirectory fails, act as though none of the
+ * files could be found.
+ */
+ if (!(conn->sslcert && strlen(conn->sslcert) > 0) ||
+ !(conn->sslkey && strlen(conn->sslkey) > 0) ||
+ !(conn->sslrootcert && strlen(conn->sslrootcert) > 0) ||
+ !((conn->sslcrl && strlen(conn->sslcrl) > 0) ||
+ (conn->sslcrldir && strlen(conn->sslcrldir) > 0)))
+ have_homedir = pqGetHomeDirectory(homedir, sizeof(homedir));
+ else /* won't need it */
+ have_homedir = false;
+
+ /*
+ * Create a new SSL_CTX object.
+ *
+ * We used to share a single SSL_CTX between all connections, but it was
+ * complicated if connections used different certificates. So now we
+ * create a separate context for each connection, and accept the overhead.
+ */
+ SSL_context = SSL_CTX_new(SSLv23_method());
+ if (!SSL_context)
+ {
+ char *err = SSLerrmessage(ERR_get_error());
+
+ libpq_append_conn_error(conn, "could not create SSL context: %s", err);
+ SSLerrfree(err);
+ return -1;
+ }
+
+ /*
+ * Delegate the client cert password prompt to the libpq wrapper callback
+ * if any is defined.
+ *
+ * If the application hasn't installed its own and the sslpassword
+ * parameter is non-null, we install ours now to make sure we supply
+ * PGconn->sslpassword to OpenSSL instead of letting it prompt on stdin.
+ *
+ * This will replace OpenSSL's default PEM_def_callback (which prompts on
+ * stdin), but we're only setting it for this SSL context so it's
+ * harmless.
+ */
+ if (PQsslKeyPassHook
+ || (conn->sslpassword && strlen(conn->sslpassword) > 0))
+ {
+ SSL_CTX_set_default_passwd_cb(SSL_context, PQssl_passwd_cb);
+ SSL_CTX_set_default_passwd_cb_userdata(SSL_context, conn);
+ }
+
+#ifdef HAVE_SSL_CTX_SET_CERT_CB
+ /* Set up a certificate selection callback. */
+ SSL_CTX_set_cert_cb(SSL_context, cert_cb, conn);
+#endif
+
+ /* Disable old protocol versions */
+ SSL_CTX_set_options(SSL_context, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
+
+ /* Set the minimum and maximum protocol versions if necessary */
+ if (conn->ssl_min_protocol_version &&
+ strlen(conn->ssl_min_protocol_version) != 0)
+ {
+ int ssl_min_ver;
+
+ ssl_min_ver = ssl_protocol_version_to_openssl(conn->ssl_min_protocol_version);
+
+ if (ssl_min_ver == -1)
+ {
+ libpq_append_conn_error(conn, "invalid value \"%s\" for minimum SSL protocol version",
+ conn->ssl_min_protocol_version);
+ SSL_CTX_free(SSL_context);
+ return -1;
+ }
+
+ if (!SSL_CTX_set_min_proto_version(SSL_context, ssl_min_ver))
+ {
+ char *err = SSLerrmessage(ERR_get_error());
+
+ libpq_append_conn_error(conn, "could not set minimum SSL protocol version: %s", err);
+ SSLerrfree(err);
+ SSL_CTX_free(SSL_context);
+ return -1;
+ }
+ }
+
+ if (conn->ssl_max_protocol_version &&
+ strlen(conn->ssl_max_protocol_version) != 0)
+ {
+ int ssl_max_ver;
+
+ ssl_max_ver = ssl_protocol_version_to_openssl(conn->ssl_max_protocol_version);
+
+ if (ssl_max_ver == -1)
+ {
+ libpq_append_conn_error(conn, "invalid value \"%s\" for maximum SSL protocol version",
+ conn->ssl_max_protocol_version);
+ SSL_CTX_free(SSL_context);
+ return -1;
+ }
+
+ if (!SSL_CTX_set_max_proto_version(SSL_context, ssl_max_ver))
+ {
+ char *err = SSLerrmessage(ERR_get_error());
+
+ libpq_append_conn_error(conn, "could not set maximum SSL protocol version: %s", err);
+ SSLerrfree(err);
+ SSL_CTX_free(SSL_context);
+ return -1;
+ }
+ }
+
+ /*
+ * Disable OpenSSL's moving-write-buffer sanity check, because it causes
+ * unnecessary failures in nonblocking send cases.
+ */
+ SSL_CTX_set_mode(SSL_context, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
+
+ /*
+ * If the root cert file exists, load it so we can perform certificate
+ * verification. If sslmode is "verify-full" we will also do further
+ * verification after the connection has been completed.
+ */
+ if (conn->sslrootcert && strlen(conn->sslrootcert) > 0)
+ strlcpy(fnbuf, conn->sslrootcert, sizeof(fnbuf));
+ else if (have_homedir)
+ snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, ROOT_CERT_FILE);
+ else
+ fnbuf[0] = '\0';
+
+ if (strcmp(fnbuf, "system") == 0)
+ {
+ /*
+ * The "system" sentinel value indicates that we should load whatever
+ * root certificates are installed for use by OpenSSL; these locations
+ * differ by platform. Note that the default system locations may be
+ * further overridden by the SSL_CERT_DIR and SSL_CERT_FILE
+ * environment variables.
+ */
+ if (SSL_CTX_set_default_verify_paths(SSL_context) != 1)
+ {
+ char *err = SSLerrmessage(ERR_get_error());
+
+ libpq_append_conn_error(conn, "could not load system root certificate paths: %s",
+ err);
+ SSLerrfree(err);
+ SSL_CTX_free(SSL_context);
+ return -1;
+ }
+ have_rootcert = true;
+ }
+ else if (fnbuf[0] != '\0' &&
+ stat(fnbuf, &buf) == 0)
+ {
+ X509_STORE *cvstore;
+
+ if (SSL_CTX_load_verify_locations(SSL_context, fnbuf, NULL) != 1)
+ {
+ char *err = SSLerrmessage(ERR_get_error());
+
+ libpq_append_conn_error(conn, "could not read root certificate file \"%s\": %s",
+ fnbuf, err);
+ SSLerrfree(err);
+ SSL_CTX_free(SSL_context);
+ return -1;
+ }
+
+ if ((cvstore = SSL_CTX_get_cert_store(SSL_context)) != NULL)
+ {
+ char *fname = NULL;
+ char *dname = NULL;
+
+ if (conn->sslcrl && strlen(conn->sslcrl) > 0)
+ fname = conn->sslcrl;
+ if (conn->sslcrldir && strlen(conn->sslcrldir) > 0)
+ dname = conn->sslcrldir;
+
+ /* defaults to use the default CRL file */
+ if (!fname && !dname && have_homedir)
+ {
+ snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, ROOT_CRL_FILE);
+ fname = fnbuf;
+ }
+
+ /* Set the flags to check against the complete CRL chain */
+ if ((fname || dname) &&
+ X509_STORE_load_locations(cvstore, fname, dname) == 1)
+ {
+ X509_STORE_set_flags(cvstore,
+ X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
+ }
+
+ /* if not found, silently ignore; we do not require CRL */
+ ERR_clear_error();
+ }
+ have_rootcert = true;
+ }
+ else
+ {
+ /*
+ * stat() failed; assume root file doesn't exist. If sslmode is
+ * verify-ca or verify-full, this is an error. Otherwise, continue
+ * without performing any server cert verification.
+ */
+ if (conn->sslmode[0] == 'v') /* "verify-ca" or "verify-full" */
+ {
+ /*
+ * The only way to reach here with an empty filename is if
+ * pqGetHomeDirectory failed. That's a sufficiently unusual case
+ * that it seems worth having a specialized error message for it.
+ */
+ if (fnbuf[0] == '\0')
+ libpq_append_conn_error(conn, "could not get home directory to locate root certificate file\n"
+ "Either provide the file, use the system's trusted roots with sslrootcert=system, or change sslmode to disable server certificate verification.");
+ else
+ libpq_append_conn_error(conn, "root certificate file \"%s\" does not exist\n"
+ "Either provide the file, use the system's trusted roots with sslrootcert=system, or change sslmode to disable server certificate verification.", fnbuf);
+ SSL_CTX_free(SSL_context);
+ return -1;
+ }
+ have_rootcert = false;
+ }
+
+ /* Read the client certificate file */
+ if (conn->sslcert && strlen(conn->sslcert) > 0)
+ strlcpy(fnbuf, conn->sslcert, sizeof(fnbuf));
+ else if (have_homedir)
+ snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_CERT_FILE);
+ else
+ fnbuf[0] = '\0';
+
+ if (conn->sslcertmode[0] == 'd') /* disable */
+ {
+ /* don't send a client cert even if we have one */
+ have_cert = false;
+ }
+ else if (fnbuf[0] == '\0')
+ {
+ /* no home directory, proceed without a client cert */
+ have_cert = false;
+ }
+ else if (stat(fnbuf, &buf) != 0)
+ {
+ /*
+ * If file is not present, just go on without a client cert; server
+ * might or might not accept the connection. Any other error,
+ * however, is grounds for complaint.
+ */
+ if (errno != ENOENT && errno != ENOTDIR)
+ {
+ libpq_append_conn_error(conn, "could not open certificate file \"%s\": %s",
+ fnbuf, strerror_r(errno, sebuf, sizeof(sebuf)));
+ SSL_CTX_free(SSL_context);
+ return -1;
+ }
+ have_cert = false;
+ }
+ else
+ {
+ /*
+ * Cert file exists, so load it. Since OpenSSL doesn't provide the
+ * equivalent of "SSL_use_certificate_chain_file", we have to load it
+ * into the SSL context, rather than the SSL object.
+ */
+ if (SSL_CTX_use_certificate_chain_file(SSL_context, fnbuf) != 1)
+ {
+ char *err = SSLerrmessage(ERR_get_error());
+
+ libpq_append_conn_error(conn, "could not read certificate file \"%s\": %s",
+ fnbuf, err);
+ SSLerrfree(err);
+ SSL_CTX_free(SSL_context);
+ return -1;
+ }
+
+ /* need to load the associated private key, too */
+ have_cert = true;
+ }
+
+ /*
+ * The SSL context is now loaded with the correct root and client
+ * certificates. Create a connection-specific SSL object. The private key
+ * is loaded directly into the SSL object. (We could load the private key
+ * into the context, too, but we have done it this way historically, and
+ * it doesn't really matter.)
+ */
+ if (!(conn->ssl = SSL_new(SSL_context)) ||
+ !SSL_set_app_data(conn->ssl, conn) ||
+ !my_SSL_set_fd(conn, conn->sock))
+ {
+ char *err = SSLerrmessage(ERR_get_error());
+
+ libpq_append_conn_error(conn, "could not establish SSL connection: %s", err);
+ SSLerrfree(err);
+ SSL_CTX_free(SSL_context);
+ return -1;
+ }
+ conn->ssl_in_use = true;
+
+ /*
+ * SSL contexts are reference counted by OpenSSL. We can free it as soon
+ * as we have created the SSL object, and it will stick around for as long
+ * as it's actually needed.
+ */
+ SSL_CTX_free(SSL_context);
+ SSL_context = NULL;
+
+ /*
+ * Set Server Name Indication (SNI), if enabled by connection parameters.
+ * Per RFC 6066, do not set it if the host is a literal IP address (IPv4
+ * or IPv6).
+ */
+ if (conn->sslsni && conn->sslsni[0] == '1')
+ {
+ const char *host = conn->connhost[conn->whichhost].host;
+
+ if (host && host[0] &&
+ !(strspn(host, "0123456789.") == strlen(host) ||
+ strchr(host, ':')))
+ {
+ if (SSL_set_tlsext_host_name(conn->ssl, host) != 1)
+ {
+ char *err = SSLerrmessage(ERR_get_error());
+
+ libpq_append_conn_error(conn, "could not set SSL Server Name Indication (SNI): %s", err);
+ SSLerrfree(err);
+ return -1;
+ }
+ }
+ }
+
+ /*
+ * Read the SSL key. If a key is specified, treat it as an engine:key
+ * combination if there is colon present - we don't support files with
+ * colon in the name. The exception is if the second character is a colon,
+ * in which case it can be a Windows filename with drive specification.
+ */
+ if (have_cert && conn->sslkey && strlen(conn->sslkey) > 0)
+ {
+#ifdef USE_SSL_ENGINE
+ if (strchr(conn->sslkey, ':')
+#ifdef WIN32
+ && conn->sslkey[1] != ':'
+#endif
+ )
+ {
+ /* Colon, but not in second character, treat as engine:key */
+ char *engine_str = strdup(conn->sslkey);
+ char *engine_colon;
+
+ if (engine_str == NULL)
+ {
+ libpq_append_conn_error(conn, "out of memory");
+ return -1;
+ }
+
+ /* cannot return NULL because we already checked before strdup */
+ engine_colon = strchr(engine_str, ':');
+
+ *engine_colon = '\0'; /* engine_str now has engine name */
+ engine_colon++; /* engine_colon now has key name */
+
+ conn->engine = ENGINE_by_id(engine_str);
+ if (conn->engine == NULL)
+ {
+ char *err = SSLerrmessage(ERR_get_error());
+
+ libpq_append_conn_error(conn, "could not load SSL engine \"%s\": %s",
+ engine_str, err);
+ SSLerrfree(err);
+ free(engine_str);
+ return -1;
+ }
+
+ if (ENGINE_init(conn->engine) == 0)
+ {
+ char *err = SSLerrmessage(ERR_get_error());
+
+ libpq_append_conn_error(conn, "could not initialize SSL engine \"%s\": %s",
+ engine_str, err);
+ SSLerrfree(err);
+ ENGINE_free(conn->engine);
+ conn->engine = NULL;
+ free(engine_str);
+ return -1;
+ }
+
+ pkey = ENGINE_load_private_key(conn->engine, engine_colon,
+ NULL, NULL);
+ if (pkey == NULL)
+ {
+ char *err = SSLerrmessage(ERR_get_error());
+
+ libpq_append_conn_error(conn, "could not read private SSL key \"%s\" from engine \"%s\": %s",
+ engine_colon, engine_str, err);
+ SSLerrfree(err);
+ ENGINE_finish(conn->engine);
+ ENGINE_free(conn->engine);
+ conn->engine = NULL;
+ free(engine_str);
+ return -1;
+ }
+ if (SSL_use_PrivateKey(conn->ssl, pkey) != 1)
+ {
+ char *err = SSLerrmessage(ERR_get_error());
+
+ libpq_append_conn_error(conn, "could not load private SSL key \"%s\" from engine \"%s\": %s",
+ engine_colon, engine_str, err);
+ SSLerrfree(err);
+ ENGINE_finish(conn->engine);
+ ENGINE_free(conn->engine);
+ conn->engine = NULL;
+ free(engine_str);
+ return -1;
+ }
+
+ free(engine_str);
+
+ fnbuf[0] = '\0'; /* indicate we're not going to load from a
+ * file */
+ }
+ else
+#endif /* USE_SSL_ENGINE */
+ {
+ /* PGSSLKEY is not an engine, treat it as a filename */
+ strlcpy(fnbuf, conn->sslkey, sizeof(fnbuf));
+ }
+ }
+ else if (have_homedir)
+ {
+ /* No PGSSLKEY specified, load default file */
+ snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_KEY_FILE);
+ }
+ else
+ fnbuf[0] = '\0';
+
+ if (have_cert && fnbuf[0] != '\0')
+ {
+ /* read the client key from file */
+
+ if (stat(fnbuf, &buf) != 0)
+ {
+ if (errno == ENOENT)
+ libpq_append_conn_error(conn, "certificate present, but not private key file \"%s\"",
+ fnbuf);
+ else
+ libpq_append_conn_error(conn, "could not stat private key file \"%s\": %m",
+ fnbuf);
+ return -1;
+ }
+
+ /* Key file must be a regular file */
+ if (!S_ISREG(buf.st_mode))
+ {
+ libpq_append_conn_error(conn, "private key file \"%s\" is not a regular file",
+ fnbuf);
+ return -1;
+ }
+
+ /*
+ * Refuse to load world-readable key files. We accept root-owned
+ * files with mode 0640 or less, so that we can access system-wide
+ * certificates if we have a supplementary group membership that
+ * allows us to read 'em. For files with non-root ownership, require
+ * mode 0600 or less. We need not check the file's ownership exactly;
+ * if we're able to read it despite it having such restrictive
+ * permissions, it must have the right ownership.
+ *
+ * Note: be very careful about tightening these rules. Some people
+ * expect, for example, that a client process running as root should
+ * be able to use a non-root-owned key file.
+ *
+ * Note that roughly similar checks are performed in
+ * src/backend/libpq/be-secure-common.c so any changes here may need
+ * to be made there as well. However, this code caters for the case
+ * of current user == root, while that code does not.
+ *
+ * Ideally we would do similar permissions checks on Windows, but it
+ * is not clear how that would work since Unix-style permissions may
+ * not be available.
+ */
+#if !defined(WIN32) && !defined(__CYGWIN__)
+ if (buf.st_uid == 0 ?
+ buf.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO) :
+ buf.st_mode & (S_IRWXG | S_IRWXO))
+ {
+ libpq_append_conn_error(conn,
+ "private key file \"%s\" has group or world access; file must have permissions u=rw (0600) or less if owned by the current user, or permissions u=rw,g=r (0640) or less if owned by root",
+ fnbuf);
+ return -1;
+ }
+#endif
+
+ if (SSL_use_PrivateKey_file(conn->ssl, fnbuf, SSL_FILETYPE_PEM) != 1)
+ {
+ char *err = SSLerrmessage(ERR_get_error());
+
+ /*
+ * We'll try to load the file in DER (binary ASN.1) format, and if
+ * that fails too, report the original error. This could mask
+ * issues where there's something wrong with a DER-format cert,
+ * but we'd have to duplicate openssl's format detection to be
+ * smarter than this. We can't just probe for a leading -----BEGIN
+ * because PEM can have leading non-matching lines and blanks.
+ * OpenSSL doesn't expose its get_name(...) and its PEM routines
+ * don't differentiate between failure modes in enough detail to
+ * let us tell the difference between "not PEM, try DER" and
+ * "wrong password".
+ */
+ if (SSL_use_PrivateKey_file(conn->ssl, fnbuf, SSL_FILETYPE_ASN1) != 1)
+ {
+ libpq_append_conn_error(conn, "could not load private key file \"%s\": %s",
+ fnbuf, err);
+ SSLerrfree(err);
+ return -1;
+ }
+
+ SSLerrfree(err);
+ }
+ }
+
+ /* verify that the cert and key go together */
+ if (have_cert &&
+ SSL_check_private_key(conn->ssl) != 1)
+ {
+ char *err = SSLerrmessage(ERR_get_error());
+
+ libpq_append_conn_error(conn, "certificate does not match private key file \"%s\": %s",
+ fnbuf, err);
+ SSLerrfree(err);
+ return -1;
+ }
+
+ /*
+ * If a root cert was loaded, also set our certificate verification
+ * callback.
+ */
+ if (have_rootcert)
+ SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, verify_cb);
+
+ /*
+ * Set compression option if necessary.
+ */
+ if (conn->sslcompression && conn->sslcompression[0] == '0')
+ SSL_set_options(conn->ssl, SSL_OP_NO_COMPRESSION);
+ else
+ SSL_clear_options(conn->ssl, SSL_OP_NO_COMPRESSION);
+
+ return 0;
+}
+
+/*
+ * Attempt to negotiate SSL connection.
+ */
+static PostgresPollingStatusType
+open_client_SSL(PGconn *conn)
+{
+ int r;
+
+ SOCK_ERRNO_SET(0);
+ ERR_clear_error();
+ r = SSL_connect(conn->ssl);
+ if (r <= 0)
+ {
+ int save_errno = SOCK_ERRNO;
+ int err = SSL_get_error(conn->ssl, r);
+ unsigned long ecode;
+
+ ecode = ERR_get_error();
+ switch (err)
+ {
+ case SSL_ERROR_WANT_READ:
+ return PGRES_POLLING_READING;
+
+ case SSL_ERROR_WANT_WRITE:
+ return PGRES_POLLING_WRITING;
+
+ case SSL_ERROR_SYSCALL:
+ {
+ char sebuf[PG_STRERROR_R_BUFLEN];
+ unsigned long vcode;
+
+ vcode = SSL_get_verify_result(conn->ssl);
+
+ /*
+ * If we get an X509 error here for failing to load the
+ * local issuer cert, without an error in the socket layer
+ * it means that verification failed due to a missing
+ * system CA pool without it being a protocol error. We
+ * inspect the sslrootcert setting to ensure that the user
+ * was using the system CA pool. For other errors, log
+ * them using the normal SYSCALL logging.
+ */
+ if (!save_errno && vcode == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY &&
+ strcmp(conn->sslrootcert, "system") == 0)
+ libpq_append_conn_error(conn, "SSL error: certificate verify failed: %s",
+ X509_verify_cert_error_string(vcode));
+ else if (r == -1)
+ libpq_append_conn_error(conn, "SSL SYSCALL error: %s",
+ SOCK_STRERROR(save_errno, sebuf, sizeof(sebuf)));
+ else
+ libpq_append_conn_error(conn, "SSL SYSCALL error: EOF detected");
+ pgtls_close(conn);
+ return PGRES_POLLING_FAILED;
+ }
+ case SSL_ERROR_SSL:
+ {
+ char *err = SSLerrmessage(ecode);
+
+ libpq_append_conn_error(conn, "SSL error: %s", err);
+ SSLerrfree(err);
+ switch (ERR_GET_REASON(ecode))
+ {
+ /*
+ * UNSUPPORTED_PROTOCOL, WRONG_VERSION_NUMBER, and
+ * TLSV1_ALERT_PROTOCOL_VERSION have been observed
+ * when trying to communicate with an old OpenSSL
+ * library, or when the client and server specify
+ * disjoint protocol ranges.
+ * NO_PROTOCOLS_AVAILABLE occurs if there's a
+ * local misconfiguration (which can happen
+ * despite our checks, if openssl.cnf injects a
+ * limit we didn't account for). It's not very
+ * clear what would make OpenSSL return the other
+ * codes listed here, but a hint about protocol
+ * versions seems like it's appropriate for all.
+ */
+ case SSL_R_NO_PROTOCOLS_AVAILABLE:
+ case SSL_R_UNSUPPORTED_PROTOCOL:
+ case SSL_R_BAD_PROTOCOL_VERSION_NUMBER:
+ case SSL_R_UNKNOWN_PROTOCOL:
+ case SSL_R_UNKNOWN_SSL_VERSION:
+ case SSL_R_UNSUPPORTED_SSL_VERSION:
+ case SSL_R_WRONG_SSL_VERSION:
+ case SSL_R_WRONG_VERSION_NUMBER:
+ case SSL_R_TLSV1_ALERT_PROTOCOL_VERSION:
+#ifdef SSL_R_VERSION_TOO_HIGH
+ case SSL_R_VERSION_TOO_HIGH:
+ case SSL_R_VERSION_TOO_LOW:
+#endif
+ libpq_append_conn_error(conn, "This may indicate that the server does not support any SSL protocol version between %s and %s.",
+ conn->ssl_min_protocol_version ?
+ conn->ssl_min_protocol_version :
+ MIN_OPENSSL_TLS_VERSION,
+ conn->ssl_max_protocol_version ?
+ conn->ssl_max_protocol_version :
+ MAX_OPENSSL_TLS_VERSION);
+ break;
+ default:
+ break;
+ }
+ pgtls_close(conn);
+ return PGRES_POLLING_FAILED;
+ }
+
+ default:
+ libpq_append_conn_error(conn, "unrecognized SSL error code: %d", err);
+ pgtls_close(conn);
+ return PGRES_POLLING_FAILED;
+ }
+ }
+
+ /*
+ * We already checked the server certificate in initialize_SSL() using
+ * SSL_CTX_set_verify(), if root.crt exists.
+ */
+
+ /* get server certificate */
+ conn->peer = SSL_get_peer_certificate(conn->ssl);
+ if (conn->peer == NULL)
+ {
+ char *err = SSLerrmessage(ERR_get_error());
+
+ libpq_append_conn_error(conn, "certificate could not be obtained: %s", err);
+ SSLerrfree(err);
+ pgtls_close(conn);
+ return PGRES_POLLING_FAILED;
+ }
+
+ if (!pq_verify_peer_name_matches_certificate(conn))
+ {
+ pgtls_close(conn);
+ return PGRES_POLLING_FAILED;
+ }
+
+ /* SSL handshake is complete */
+ return PGRES_POLLING_OK;
+}
+
+void
+pgtls_close(PGconn *conn)
+{
+ bool destroy_needed = false;
+
+ if (conn->ssl_in_use)
+ {
+ if (conn->ssl)
+ {
+ /*
+ * We can't destroy everything SSL-related here due to the
+ * possible later calls to OpenSSL routines which may need our
+ * thread callbacks, so set a flag here and check at the end.
+ */
+
+ if (SSL_shutdown(conn->ssl) < 0) {
+ // Pop an error and ignore it. We might have already printed one
+ // and SSL_shutdown just yields logic warnings as errors.
+ ERR_get_error();
+ }
+ SSL_free(conn->ssl);
+ conn->ssl = NULL;
+ conn->ssl_in_use = false;
+
+ destroy_needed = true;
+ }
+
+ if (conn->peer)
+ {
+ X509_free(conn->peer);
+ conn->peer = NULL;
+ }
+
+#ifdef USE_SSL_ENGINE
+ if (conn->engine)
+ {
+ ENGINE_finish(conn->engine);
+ ENGINE_free(conn->engine);
+ conn->engine = NULL;
+ }
+#endif
+ }
+ else
+ {
+ /*
+ * In the non-SSL case, just remove the crypto callbacks if the
+ * connection has then loaded. This code path has no dependency on
+ * any pending SSL calls.
+ */
+ if (conn->crypto_loaded)
+ destroy_needed = true;
+ }
+
+ /*
+ * This will remove our crypto locking hooks if this is the last
+ * connection using libcrypto which means we must wait to call it until
+ * after all the potential SSL calls have been made, otherwise we can end
+ * up with a race condition and possible deadlocks.
+ *
+ * See comments above destroy_ssl_system().
+ */
+ if (destroy_needed)
+ {
+ destroy_ssl_system();
+ conn->crypto_loaded = false;
+ }
+}
+
+
+/*
+ * Obtain reason string for passed SSL errcode
+ *
+ * ERR_get_error() is used by caller to get errcode to pass here.
+ *
+ * Some caution is needed here since ERR_reason_error_string will
+ * return NULL if it doesn't recognize the error code. We don't
+ * want to return NULL ever.
+ */
+static char ssl_nomem[] = "out of memory allocating error description";
+
+#define SSL_ERR_LEN 128
+
+static char *
+SSLerrmessage(unsigned long ecode)
+{
+ const char *errreason;
+ char *errbuf;
+
+ errbuf = malloc(SSL_ERR_LEN);
+ if (!errbuf)
+ return ssl_nomem;
+ if (ecode == 0)
+ {
+ snprintf(errbuf, SSL_ERR_LEN, libpq_gettext("no SSL error reported"));
+ return errbuf;
+ }
+ errreason = ERR_reason_error_string(ecode);
+ if (errreason != NULL)
+ {
+ strlcpy(errbuf, errreason, SSL_ERR_LEN);
+ return errbuf;
+ }
+ snprintf(errbuf, SSL_ERR_LEN, libpq_gettext("SSL error code %lu"), ecode);
+ return errbuf;
+}
+
+static void
+SSLerrfree(char *buf)
+{
+ if (buf != ssl_nomem)
+ free(buf);
+}
+
+/* ------------------------------------------------------------ */
+/* SSL information functions */
+/* ------------------------------------------------------------ */
+
+/*
+ * Return pointer to OpenSSL object.
+ */
+void *
+PQgetssl(PGconn *conn)
+{
+ if (!conn)
+ return NULL;
+ return conn->ssl;
+}
+
+void *
+PQsslStruct(PGconn *conn, const char *struct_name)
+{
+ if (!conn)
+ return NULL;
+ if (strcmp(struct_name, "OpenSSL") == 0)
+ return conn->ssl;
+ return NULL;
+}
+
+const char *const *
+PQsslAttributeNames(PGconn *conn)
+{
+ static const char *const openssl_attrs[] = {
+ "library",
+ "key_bits",
+ "cipher",
+ "compression",
+ "protocol",
+ NULL
+ };
+ static const char *const empty_attrs[] = {NULL};
+
+ if (!conn)
+ {
+ /* Return attributes of default SSL library */
+ return openssl_attrs;
+ }
+
+ /* No attrs for unencrypted connection */
+ if (conn->ssl == NULL)
+ return empty_attrs;
+
+ return openssl_attrs;
+}
+
+const char *
+PQsslAttribute(PGconn *conn, const char *attribute_name)
+{
+ if (!conn)
+ {
+ /* PQsslAttribute(NULL, "library") reports the default SSL library */
+ if (strcmp(attribute_name, "library") == 0)
+ return "OpenSSL";
+ return NULL;
+ }
+
+ /* All attributes read as NULL for a non-encrypted connection */
+ if (conn->ssl == NULL)
+ return NULL;
+
+ if (strcmp(attribute_name, "library") == 0)
+ return "OpenSSL";
+
+ if (strcmp(attribute_name, "key_bits") == 0)
+ {
+ static char sslbits_str[12];
+ int sslbits;
+
+ SSL_get_cipher_bits(conn->ssl, &sslbits);
+ snprintf(sslbits_str, sizeof(sslbits_str), "%d", sslbits);
+ return sslbits_str;
+ }
+
+ if (strcmp(attribute_name, "cipher") == 0)
+ return SSL_get_cipher(conn->ssl);
+
+ if (strcmp(attribute_name, "compression") == 0)
+ return SSL_get_current_compression(conn->ssl) ? "on" : "off";
+
+ if (strcmp(attribute_name, "protocol") == 0)
+ return SSL_get_version(conn->ssl);
+
+ return NULL; /* unknown attribute */
+}
+
+/*
+ * Private substitute BIO: this does the sending and receiving using
+ * pqsecure_raw_write() and pqsecure_raw_read() instead, to allow those
+ * functions to disable SIGPIPE and give better error messages on I/O errors.
+ *
+ * These functions are closely modelled on the standard socket BIO in OpenSSL;
+ * see sock_read() and sock_write() in OpenSSL's crypto/bio/bss_sock.c.
+ * XXX OpenSSL 1.0.1e considers many more errcodes than just EINTR as reasons
+ * to retry; do we need to adopt their logic for that?
+ */
+
+#ifndef HAVE_BIO_GET_DATA
+#define BIO_get_data(bio) (bio->ptr)
+#define BIO_set_data(bio, data) (bio->ptr = data)
+#endif
+
+static BIO_METHOD *my_bio_methods;
+
+static int
+my_sock_read(BIO *h, char *buf, int size)
+{
+ int res;
+
+ res = pqsecure_raw_read((PGconn *) BIO_get_data(h), buf, size);
+ BIO_clear_retry_flags(h);
+ if (res < 0)
+ {
+ /* If we were interrupted, tell caller to retry */
+ switch (SOCK_ERRNO)
+ {
+#ifdef EAGAIN
+ case EAGAIN:
+#endif
+#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
+ case EWOULDBLOCK:
+#endif
+ case EINTR:
+ BIO_set_retry_read(h);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return res;
+}
+
+static int
+my_sock_write(BIO *h, const char *buf, int size)
+{
+ int res;
+
+ res = pqsecure_raw_write((PGconn *) BIO_get_data(h), buf, size);
+ BIO_clear_retry_flags(h);
+ if (res < 0)
+ {
+ /* If we were interrupted, tell caller to retry */
+ switch (SOCK_ERRNO)
+ {
+#ifdef EAGAIN
+ case EAGAIN:
+#endif
+#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
+ case EWOULDBLOCK:
+#endif
+ case EINTR:
+ BIO_set_retry_write(h);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return res;
+}
+
+static BIO_METHOD *
+my_BIO_s_socket(void)
+{
+ if (!my_bio_methods)
+ {
+ BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket();
+#ifdef HAVE_BIO_METH_NEW
+ int my_bio_index;
+
+ my_bio_index = BIO_get_new_index();
+ if (my_bio_index == -1)
+ return NULL;
+ my_bio_index |= (BIO_TYPE_DESCRIPTOR | BIO_TYPE_SOURCE_SINK);
+ my_bio_methods = BIO_meth_new(my_bio_index, "libpq socket");
+ if (!my_bio_methods)
+ return NULL;
+
+ /*
+ * As of this writing, these functions never fail. But check anyway,
+ * like OpenSSL's own examples do.
+ */
+ if (!BIO_meth_set_write(my_bio_methods, my_sock_write) ||
+ !BIO_meth_set_read(my_bio_methods, my_sock_read) ||
+ !BIO_meth_set_gets(my_bio_methods, BIO_meth_get_gets(biom)) ||
+ !BIO_meth_set_puts(my_bio_methods, BIO_meth_get_puts(biom)) ||
+ !BIO_meth_set_ctrl(my_bio_methods, BIO_meth_get_ctrl(biom)) ||
+ !BIO_meth_set_create(my_bio_methods, BIO_meth_get_create(biom)) ||
+ !BIO_meth_set_destroy(my_bio_methods, BIO_meth_get_destroy(biom)) ||
+ !BIO_meth_set_callback_ctrl(my_bio_methods, BIO_meth_get_callback_ctrl(biom)))
+ {
+ BIO_meth_free(my_bio_methods);
+ my_bio_methods = NULL;
+ return NULL;
+ }
+#else
+ my_bio_methods = malloc(sizeof(BIO_METHOD));
+ if (!my_bio_methods)
+ return NULL;
+ memcpy(my_bio_methods, biom, sizeof(BIO_METHOD));
+ my_bio_methods->bread = my_sock_read;
+ my_bio_methods->bwrite = my_sock_write;
+#endif
+ }
+ return my_bio_methods;
+}
+
+/* This should exactly match OpenSSL's SSL_set_fd except for using my BIO */
+static int
+my_SSL_set_fd(PGconn *conn, int fd)
+{
+ int ret = 0;
+ BIO *bio;
+ BIO_METHOD *bio_method;
+
+ bio_method = my_BIO_s_socket();
+ if (bio_method == NULL)
+ {
+ SSLerr(SSL_F_SSL_SET_FD, ERR_R_BUF_LIB);
+ goto err;
+ }
+ bio = BIO_new(bio_method);
+ if (bio == NULL)
+ {
+ SSLerr(SSL_F_SSL_SET_FD, ERR_R_BUF_LIB);
+ goto err;
+ }
+ BIO_set_data(bio, conn);
+
+ SSL_set_bio(conn->ssl, bio, bio);
+ BIO_set_fd(bio, fd, BIO_NOCLOSE);
+ ret = 1;
+err:
+ return ret;
+}
+
+/*
+ * This is the default handler to return a client cert password from
+ * conn->sslpassword. Apps may install it explicitly if they want to
+ * prevent openssl from ever prompting on stdin.
+ */
+int
+PQdefaultSSLKeyPassHook_OpenSSL(char *buf, int size, PGconn *conn)
+{
+ if (conn && conn->sslpassword)
+ {
+ if (strlen(conn->sslpassword) + 1 > size)
+ fprintf(stderr, libpq_gettext("WARNING: sslpassword truncated\n"));
+ strncpy(buf, conn->sslpassword, size);
+ buf[size - 1] = '\0';
+ return strlen(buf);
+ }
+ else
+ {
+ buf[0] = '\0';
+ return 0;
+ }
+}
+
+PQsslKeyPassHook_OpenSSL_type
+PQgetSSLKeyPassHook_OpenSSL(void)
+{
+ return PQsslKeyPassHook;
+}
+
+void
+PQsetSSLKeyPassHook_OpenSSL(PQsslKeyPassHook_OpenSSL_type hook)
+{
+ PQsslKeyPassHook = hook;
+}
+
+/*
+ * Supply a password to decrypt a client certificate.
+ *
+ * This must match OpenSSL type pem_password_cb.
+ */
+static int
+PQssl_passwd_cb(char *buf, int size, int rwflag, void *userdata)
+{
+ PGconn *conn = userdata;
+
+ if (PQsslKeyPassHook)
+ return PQsslKeyPassHook(buf, size, conn);
+ else
+ return PQdefaultSSLKeyPassHook_OpenSSL(buf, size, conn);
+}
+
+/*
+ * Convert TLS protocol version string to OpenSSL values
+ *
+ * If a version is passed that is not supported by the current OpenSSL version,
+ * then we return -1. If a non-negative value is returned, subsequent code can
+ * assume it is working with a supported version.
+ *
+ * Note: this is rather similar to the backend routine in be-secure-openssl.c,
+ * so make sure to update both routines if changing this one.
+ */
+static int
+ssl_protocol_version_to_openssl(const char *protocol)
+{
+ if (pg_strcasecmp("TLSv1", protocol) == 0)
+ return TLS1_VERSION;
+
+#ifdef TLS1_1_VERSION
+ if (pg_strcasecmp("TLSv1.1", protocol) == 0)
+ return TLS1_1_VERSION;
+#endif
+
+#ifdef TLS1_2_VERSION
+ if (pg_strcasecmp("TLSv1.2", protocol) == 0)
+ return TLS1_2_VERSION;
+#endif
+
+#ifdef TLS1_3_VERSION
+ if (pg_strcasecmp("TLSv1.3", protocol) == 0)
+ return TLS1_3_VERSION;
+#endif
+
+ return -1;
+}
diff --git a/contrib/libs/libpq/src/interfaces/libpq/fe-secure.c b/contrib/libs/libpq/src/interfaces/libpq/fe-secure.c
new file mode 100644
index 0000000000..8069e38142
--- /dev/null
+++ b/contrib/libs/libpq/src/interfaces/libpq/fe-secure.c
@@ -0,0 +1,611 @@
+/*-------------------------------------------------------------------------
+ *
+ * fe-secure.c
+ * functions related to setting up a secure connection to the backend.
+ * Secure connections are expected to provide confidentiality,
+ * message integrity and endpoint authentication.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/interfaces/libpq/fe-secure.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres_fe.h"
+
+#include <signal.h>
+#include <fcntl.h>
+#include <ctype.h>
+
+#ifdef WIN32
+#include "win32.h"
+#else
+#include <sys/socket.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#endif
+
+#include <sys/stat.h>
+
+#ifdef ENABLE_THREAD_SAFETY
+#ifdef WIN32
+#include "pthread-win32.h"
+#else
+#include <pthread.h>
+#endif
+#endif
+
+#include "fe-auth.h"
+#include "libpq-fe.h"
+#include "libpq-int.h"
+
+/*
+ * Macros to handle disabling and then restoring the state of SIGPIPE handling.
+ * On Windows, these are all no-ops since there's no SIGPIPEs.
+ */
+
+#ifndef WIN32
+
+#define SIGPIPE_MASKED(conn) ((conn)->sigpipe_so || (conn)->sigpipe_flag)
+
+#ifdef ENABLE_THREAD_SAFETY
+
+struct sigpipe_info
+{
+ sigset_t oldsigmask;
+ bool sigpipe_pending;
+ bool got_epipe;
+};
+
+#define DECLARE_SIGPIPE_INFO(spinfo) struct sigpipe_info spinfo
+
+#define DISABLE_SIGPIPE(conn, spinfo, failaction) \
+ do { \
+ (spinfo).got_epipe = false; \
+ if (!SIGPIPE_MASKED(conn)) \
+ { \
+ if (pq_block_sigpipe(&(spinfo).oldsigmask, \
+ &(spinfo).sigpipe_pending) < 0) \
+ failaction; \
+ } \
+ } while (0)
+
+#define REMEMBER_EPIPE(spinfo, cond) \
+ do { \
+ if (cond) \
+ (spinfo).got_epipe = true; \
+ } while (0)
+
+#define RESTORE_SIGPIPE(conn, spinfo) \
+ do { \
+ if (!SIGPIPE_MASKED(conn)) \
+ pq_reset_sigpipe(&(spinfo).oldsigmask, (spinfo).sigpipe_pending, \
+ (spinfo).got_epipe); \
+ } while (0)
+#else /* !ENABLE_THREAD_SAFETY */
+
+#define DECLARE_SIGPIPE_INFO(spinfo) pqsigfunc spinfo = NULL
+
+#define DISABLE_SIGPIPE(conn, spinfo, failaction) \
+ do { \
+ if (!SIGPIPE_MASKED(conn)) \
+ spinfo = pqsignal(SIGPIPE, SIG_IGN); \
+ } while (0)
+
+#define REMEMBER_EPIPE(spinfo, cond)
+
+#define RESTORE_SIGPIPE(conn, spinfo) \
+ do { \
+ if (!SIGPIPE_MASKED(conn)) \
+ pqsignal(SIGPIPE, spinfo); \
+ } while (0)
+#endif /* ENABLE_THREAD_SAFETY */
+#else /* WIN32 */
+
+#define DECLARE_SIGPIPE_INFO(spinfo)
+#define DISABLE_SIGPIPE(conn, spinfo, failaction)
+#define REMEMBER_EPIPE(spinfo, cond)
+#define RESTORE_SIGPIPE(conn, spinfo)
+#endif /* WIN32 */
+
+/* ------------------------------------------------------------ */
+/* Procedures common to all secure sessions */
+/* ------------------------------------------------------------ */
+
+
+int
+PQsslInUse(PGconn *conn)
+{
+ if (!conn)
+ return 0;
+ return conn->ssl_in_use;
+}
+
+/*
+ * Exported function to allow application to tell us it's already
+ * initialized OpenSSL.
+ */
+void
+PQinitSSL(int do_init)
+{
+#ifdef USE_SSL
+ pgtls_init_library(do_init, do_init);
+#endif
+}
+
+/*
+ * Exported function to allow application to tell us it's already
+ * initialized OpenSSL and/or libcrypto.
+ */
+void
+PQinitOpenSSL(int do_ssl, int do_crypto)
+{
+#ifdef USE_SSL
+ pgtls_init_library(do_ssl, do_crypto);
+#endif
+}
+
+/*
+ * Initialize global SSL context
+ */
+int
+pqsecure_initialize(PGconn *conn, bool do_ssl, bool do_crypto)
+{
+ int r = 0;
+
+#ifdef USE_SSL
+ r = pgtls_init(conn, do_ssl, do_crypto);
+#endif
+
+ return r;
+}
+
+/*
+ * Begin or continue negotiating a secure session.
+ */
+PostgresPollingStatusType
+pqsecure_open_client(PGconn *conn)
+{
+#ifdef USE_SSL
+ return pgtls_open_client(conn);
+#else
+ /* shouldn't get here */
+ return PGRES_POLLING_FAILED;
+#endif
+}
+
+/*
+ * Close secure session.
+ */
+void
+pqsecure_close(PGconn *conn)
+{
+#ifdef USE_SSL
+ pgtls_close(conn);
+#endif
+}
+
+/*
+ * Read data from a secure connection.
+ *
+ * On failure, this function is responsible for appending a suitable message
+ * to conn->errorMessage. The caller must still inspect errno, but only
+ * to determine whether to continue/retry after error.
+ */
+ssize_t
+pqsecure_read(PGconn *conn, void *ptr, size_t len)
+{
+ ssize_t n;
+
+#ifdef USE_SSL
+ if (conn->ssl_in_use)
+ {
+ n = pgtls_read(conn, ptr, len);
+ }
+ else
+#endif
+#ifdef ENABLE_GSS
+ if (conn->gssenc)
+ {
+ n = pg_GSS_read(conn, ptr, len);
+ }
+ else
+#endif
+ {
+ n = pqsecure_raw_read(conn, ptr, len);
+ }
+
+ return n;
+}
+
+ssize_t
+pqsecure_raw_read(PGconn *conn, void *ptr, size_t len)
+{
+ ssize_t n;
+ int result_errno = 0;
+ char sebuf[PG_STRERROR_R_BUFLEN];
+
+ n = recv(conn->sock, ptr, len, 0);
+
+ if (n < 0)
+ {
+ result_errno = SOCK_ERRNO;
+
+ /* Set error message if appropriate */
+ switch (result_errno)
+ {
+#ifdef EAGAIN
+ case EAGAIN:
+#endif
+#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
+ case EWOULDBLOCK:
+#endif
+ case EINTR:
+ /* no error message, caller is expected to retry */
+ break;
+
+ case EPIPE:
+ case ECONNRESET:
+ libpq_append_conn_error(conn, "server closed the connection unexpectedly\n"
+ "\tThis probably means the server terminated abnormally\n"
+ "\tbefore or while processing the request.");
+ break;
+
+ default:
+ libpq_append_conn_error(conn, "could not receive data from server: %s",
+ SOCK_STRERROR(result_errno,
+ sebuf, sizeof(sebuf)));
+ break;
+ }
+ }
+
+ /* ensure we return the intended errno to caller */
+ SOCK_ERRNO_SET(result_errno);
+
+ return n;
+}
+
+/*
+ * Write data to a secure connection.
+ *
+ * Returns the number of bytes written, or a negative value (with errno
+ * set) upon failure. The write count could be less than requested.
+ *
+ * Note that socket-level hard failures are masked from the caller,
+ * instead setting conn->write_failed and storing an error message
+ * in conn->write_err_msg; see pqsecure_raw_write. This allows us to
+ * postpone reporting of write failures until we're sure no error
+ * message is available from the server.
+ *
+ * However, errors detected in the SSL or GSS management level are reported
+ * via a negative result, with message appended to conn->errorMessage.
+ * It's frequently unclear whether such errors should be considered read or
+ * write errors, so we don't attempt to postpone reporting them.
+ *
+ * The caller must still inspect errno upon failure, but only to determine
+ * whether to continue/retry; a message has been saved someplace in any case.
+ */
+ssize_t
+pqsecure_write(PGconn *conn, const void *ptr, size_t len)
+{
+ ssize_t n;
+
+#ifdef USE_SSL
+ if (conn->ssl_in_use)
+ {
+ n = pgtls_write(conn, ptr, len);
+ }
+ else
+#endif
+#ifdef ENABLE_GSS
+ if (conn->gssenc)
+ {
+ n = pg_GSS_write(conn, ptr, len);
+ }
+ else
+#endif
+ {
+ n = pqsecure_raw_write(conn, ptr, len);
+ }
+
+ return n;
+}
+
+/*
+ * Low-level implementation of pqsecure_write.
+ *
+ * This is used directly for an unencrypted connection. For encrypted
+ * connections, this does the physical I/O on behalf of pgtls_write or
+ * pg_GSS_write.
+ *
+ * This function reports failure (i.e., returns a negative result) only
+ * for retryable errors such as EINTR. Looping for such cases is to be
+ * handled at some outer level, maybe all the way up to the application.
+ * For hard failures, we set conn->write_failed and store an error message
+ * in conn->write_err_msg, but then claim to have written the data anyway.
+ * This is because we don't want to report write failures so long as there
+ * is a possibility of reading from the server and getting an error message
+ * that could explain why the connection dropped. Many TCP stacks have
+ * race conditions such that a write failure may or may not be reported
+ * before all incoming data has been read.
+ *
+ * Note that this error behavior happens below the SSL management level when
+ * we are using SSL. That's because at least some versions of OpenSSL are
+ * too quick to report a write failure when there's still a possibility to
+ * get a more useful error from the server.
+ */
+ssize_t
+pqsecure_raw_write(PGconn *conn, const void *ptr, size_t len)
+{
+ ssize_t n;
+ int flags = 0;
+ int result_errno = 0;
+ char msgbuf[1024];
+ char sebuf[PG_STRERROR_R_BUFLEN];
+
+ DECLARE_SIGPIPE_INFO(spinfo);
+
+ /*
+ * If we already had a write failure, we will never again try to send data
+ * on that connection. Even if the kernel would let us, we've probably
+ * lost message boundary sync with the server. conn->write_failed
+ * therefore persists until the connection is reset, and we just discard
+ * all data presented to be written.
+ */
+ if (conn->write_failed)
+ return len;
+
+#ifdef MSG_NOSIGNAL
+ if (conn->sigpipe_flag)
+ flags |= MSG_NOSIGNAL;
+
+retry_masked:
+#endif /* MSG_NOSIGNAL */
+
+ DISABLE_SIGPIPE(conn, spinfo, return -1);
+
+ n = send(conn->sock, ptr, len, flags);
+
+ if (n < 0)
+ {
+ result_errno = SOCK_ERRNO;
+
+ /*
+ * If we see an EINVAL, it may be because MSG_NOSIGNAL isn't available
+ * on this machine. So, clear sigpipe_flag so we don't try the flag
+ * again, and retry the send().
+ */
+#ifdef MSG_NOSIGNAL
+ if (flags != 0 && result_errno == EINVAL)
+ {
+ conn->sigpipe_flag = false;
+ flags = 0;
+ goto retry_masked;
+ }
+#endif /* MSG_NOSIGNAL */
+
+ /* Set error message if appropriate */
+ switch (result_errno)
+ {
+#ifdef EAGAIN
+ case EAGAIN:
+#endif
+#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
+ case EWOULDBLOCK:
+#endif
+ case EINTR:
+ /* no error message, caller is expected to retry */
+ break;
+
+ case EPIPE:
+ /* Set flag for EPIPE */
+ REMEMBER_EPIPE(spinfo, true);
+
+ /* FALL THRU */
+
+ case ECONNRESET:
+ conn->write_failed = true;
+ /* Store error message in conn->write_err_msg, if possible */
+ /* (strdup failure is OK, we'll cope later) */
+ snprintf(msgbuf, sizeof(msgbuf),
+ libpq_gettext("server closed the connection unexpectedly\n"
+ "\tThis probably means the server terminated abnormally\n"
+ "\tbefore or while processing the request."));
+ /* keep newline out of translated string */
+ strlcat(msgbuf, "\n", sizeof(msgbuf));
+ conn->write_err_msg = strdup(msgbuf);
+ /* Now claim the write succeeded */
+ n = len;
+ break;
+
+ default:
+ conn->write_failed = true;
+ /* Store error message in conn->write_err_msg, if possible */
+ /* (strdup failure is OK, we'll cope later) */
+ snprintf(msgbuf, sizeof(msgbuf),
+ libpq_gettext("could not send data to server: %s"),
+ SOCK_STRERROR(result_errno,
+ sebuf, sizeof(sebuf)));
+ /* keep newline out of translated string */
+ strlcat(msgbuf, "\n", sizeof(msgbuf));
+ conn->write_err_msg = strdup(msgbuf);
+ /* Now claim the write succeeded */
+ n = len;
+ break;
+ }
+ }
+
+ RESTORE_SIGPIPE(conn, spinfo);
+
+ /* ensure we return the intended errno to caller */
+ SOCK_ERRNO_SET(result_errno);
+
+ return n;
+}
+
+/* Dummy versions of SSL info functions, when built without SSL support */
+#ifndef USE_SSL
+
+void *
+PQgetssl(PGconn *conn)
+{
+ return NULL;
+}
+
+void *
+PQsslStruct(PGconn *conn, const char *struct_name)
+{
+ return NULL;
+}
+
+const char *
+PQsslAttribute(PGconn *conn, const char *attribute_name)
+{
+ return NULL;
+}
+
+const char *const *
+PQsslAttributeNames(PGconn *conn)
+{
+ static const char *const result[] = {NULL};
+
+ return result;
+}
+#endif /* USE_SSL */
+
+/*
+ * Dummy versions of OpenSSL key password hook functions, when built without
+ * OpenSSL.
+ */
+#ifndef USE_OPENSSL
+
+PQsslKeyPassHook_OpenSSL_type
+PQgetSSLKeyPassHook_OpenSSL(void)
+{
+ return NULL;
+}
+
+void
+PQsetSSLKeyPassHook_OpenSSL(PQsslKeyPassHook_OpenSSL_type hook)
+{
+ return;
+}
+
+int
+PQdefaultSSLKeyPassHook_OpenSSL(char *buf, int size, PGconn *conn)
+{
+ return 0;
+}
+#endif /* USE_OPENSSL */
+
+/* Dummy version of GSSAPI information functions, when built without GSS support */
+#ifndef ENABLE_GSS
+
+void *
+PQgetgssctx(PGconn *conn)
+{
+ return NULL;
+}
+
+int
+PQgssEncInUse(PGconn *conn)
+{
+ return 0;
+}
+
+#endif /* ENABLE_GSS */
+
+
+#if defined(ENABLE_THREAD_SAFETY) && !defined(WIN32)
+
+/*
+ * Block SIGPIPE for this thread. This prevents send()/write() from exiting
+ * the application.
+ */
+int
+pq_block_sigpipe(sigset_t *osigset, bool *sigpipe_pending)
+{
+ sigset_t sigpipe_sigset;
+ sigset_t sigset;
+
+ sigemptyset(&sigpipe_sigset);
+ sigaddset(&sigpipe_sigset, SIGPIPE);
+
+ /* Block SIGPIPE and save previous mask for later reset */
+ SOCK_ERRNO_SET(pthread_sigmask(SIG_BLOCK, &sigpipe_sigset, osigset));
+ if (SOCK_ERRNO)
+ return -1;
+
+ /* We can have a pending SIGPIPE only if it was blocked before */
+ if (sigismember(osigset, SIGPIPE))
+ {
+ /* Is there a pending SIGPIPE? */
+ if (sigpending(&sigset) != 0)
+ return -1;
+
+ if (sigismember(&sigset, SIGPIPE))
+ *sigpipe_pending = true;
+ else
+ *sigpipe_pending = false;
+ }
+ else
+ *sigpipe_pending = false;
+
+ return 0;
+}
+
+/*
+ * Discard any pending SIGPIPE and reset the signal mask.
+ *
+ * Note: we are effectively assuming here that the C library doesn't queue
+ * up multiple SIGPIPE events. If it did, then we'd accidentally leave
+ * ours in the queue when an event was already pending and we got another.
+ * As long as it doesn't queue multiple events, we're OK because the caller
+ * can't tell the difference.
+ *
+ * The caller should say got_epipe = false if it is certain that it
+ * didn't get an EPIPE error; in that case we'll skip the clear operation
+ * and things are definitely OK, queuing or no. If it got one or might have
+ * gotten one, pass got_epipe = true.
+ *
+ * We do not want this to change errno, since if it did that could lose
+ * the error code from a preceding send(). We essentially assume that if
+ * we were able to do pq_block_sigpipe(), this can't fail.
+ */
+void
+pq_reset_sigpipe(sigset_t *osigset, bool sigpipe_pending, bool got_epipe)
+{
+ int save_errno = SOCK_ERRNO;
+ int signo;
+ sigset_t sigset;
+
+ /* Clear SIGPIPE only if none was pending */
+ if (got_epipe && !sigpipe_pending)
+ {
+ if (sigpending(&sigset) == 0 &&
+ sigismember(&sigset, SIGPIPE))
+ {
+ sigset_t sigpipe_sigset;
+
+ sigemptyset(&sigpipe_sigset);
+ sigaddset(&sigpipe_sigset, SIGPIPE);
+
+ sigwait(&sigpipe_sigset, &signo);
+ }
+ }
+
+ /* Restore saved block mask */
+ pthread_sigmask(SIG_SETMASK, osigset, NULL);
+
+ SOCK_ERRNO_SET(save_errno);
+}
+
+#endif /* ENABLE_THREAD_SAFETY && !WIN32 */
diff --git a/contrib/libs/libpq/src/interfaces/libpq/fe-trace.c b/contrib/libs/libpq/src/interfaces/libpq/fe-trace.c
new file mode 100644
index 0000000000..402784f40e
--- /dev/null
+++ b/contrib/libs/libpq/src/interfaces/libpq/fe-trace.c
@@ -0,0 +1,729 @@
+/*-------------------------------------------------------------------------
+ *
+ * fe-trace.c
+ * functions for libpq protocol tracing
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/interfaces/libpq/fe-trace.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres_fe.h"
+
+#include <ctype.h>
+#include <limits.h>
+#include <sys/time.h>
+#include <time.h>
+
+#ifdef WIN32
+#include "win32.h"
+#else
+#include <unistd.h>
+#endif
+
+#include "libpq-fe.h"
+#include "libpq-int.h"
+#include "port/pg_bswap.h"
+
+
+/* Enable tracing */
+void
+PQtrace(PGconn *conn, FILE *debug_port)
+{
+ if (conn == NULL)
+ return;
+ PQuntrace(conn);
+ if (debug_port == NULL)
+ return;
+
+ conn->Pfdebug = debug_port;
+ conn->traceFlags = 0;
+}
+
+/* Disable tracing */
+void
+PQuntrace(PGconn *conn)
+{
+ if (conn == NULL)
+ return;
+ if (conn->Pfdebug)
+ {
+ fflush(conn->Pfdebug);
+ conn->Pfdebug = NULL;
+ }
+
+ conn->traceFlags = 0;
+}
+
+/* Set flags for current tracing session */
+void
+PQsetTraceFlags(PGconn *conn, int flags)
+{
+ if (conn == NULL)
+ return;
+ /* If PQtrace() failed, do nothing. */
+ if (conn->Pfdebug == NULL)
+ return;
+ conn->traceFlags = flags;
+}
+
+/*
+ * Print the current time, with microseconds, into a caller-supplied
+ * buffer.
+ * Cribbed from get_formatted_log_time, but much simpler.
+ */
+static void
+pqTraceFormatTimestamp(char *timestr, size_t ts_len)
+{
+ struct timeval tval;
+ time_t now;
+
+ gettimeofday(&tval, NULL);
+
+ /*
+ * MSVC's implementation of timeval uses a long for tv_sec, however,
+ * localtime() expects a time_t pointer. Here we'll assign tv_sec to a
+ * local time_t variable so that we pass localtime() the correct pointer
+ * type.
+ */
+ now = tval.tv_sec;
+ strftime(timestr, ts_len,
+ "%Y-%m-%d %H:%M:%S",
+ localtime(&now));
+ /* append microseconds */
+ snprintf(timestr + strlen(timestr), ts_len - strlen(timestr),
+ ".%06u", (unsigned int) (tval.tv_usec));
+}
+
+/*
+ * pqTraceOutputByte1: output a 1-char message to the log
+ */
+static void
+pqTraceOutputByte1(FILE *pfdebug, const char *data, int *cursor)
+{
+ const char *v = data + *cursor;
+
+ /*
+ * Show non-printable data in hex format, including the terminating \0
+ * that completes ErrorResponse and NoticeResponse messages.
+ */
+ if (!isprint((unsigned char) *v))
+ fprintf(pfdebug, " \\x%02x", *v);
+ else
+ fprintf(pfdebug, " %c", *v);
+ *cursor += 1;
+}
+
+/*
+ * pqTraceOutputInt16: output a 2-byte integer message to the log
+ */
+static int
+pqTraceOutputInt16(FILE *pfdebug, const char *data, int *cursor)
+{
+ uint16 tmp;
+ int result;
+
+ memcpy(&tmp, data + *cursor, 2);
+ *cursor += 2;
+ result = (int) pg_ntoh16(tmp);
+ fprintf(pfdebug, " %d", result);
+
+ return result;
+}
+
+/*
+ * pqTraceOutputInt32: output a 4-byte integer message to the log
+ *
+ * If 'suppress' is true, print a literal NNNN instead of the actual number.
+ */
+static int
+pqTraceOutputInt32(FILE *pfdebug, const char *data, int *cursor, bool suppress)
+{
+ int result;
+
+ memcpy(&result, data + *cursor, 4);
+ *cursor += 4;
+ result = (int) pg_ntoh32(result);
+ if (suppress)
+ fprintf(pfdebug, " NNNN");
+ else
+ fprintf(pfdebug, " %d", result);
+
+ return result;
+}
+
+/*
+ * pqTraceOutputString: output a string message to the log
+ */
+static void
+pqTraceOutputString(FILE *pfdebug, const char *data, int *cursor, bool suppress)
+{
+ int len;
+
+ if (suppress)
+ {
+ fprintf(pfdebug, " \"SSSS\"");
+ *cursor += strlen(data + *cursor) + 1;
+ }
+ else
+ {
+ len = fprintf(pfdebug, " \"%s\"", data + *cursor);
+
+ /*
+ * This is a null-terminated string. So add 1 after subtracting 3
+ * which is the double quotes and space length from len.
+ */
+ *cursor += (len - 3 + 1);
+ }
+}
+
+/*
+ * pqTraceOutputNchar: output a string of exactly len bytes message to the log
+ */
+static void
+pqTraceOutputNchar(FILE *pfdebug, int len, const char *data, int *cursor)
+{
+ int i,
+ next; /* first char not yet printed */
+ const char *v = data + *cursor;
+
+ fprintf(pfdebug, " \'");
+
+ for (next = i = 0; i < len; ++i)
+ {
+ if (isprint((unsigned char) v[i]))
+ continue;
+ else
+ {
+ fwrite(v + next, 1, i - next, pfdebug);
+ fprintf(pfdebug, "\\x%02x", v[i]);
+ next = i + 1;
+ }
+ }
+ if (next < len)
+ fwrite(v + next, 1, len - next, pfdebug);
+
+ fprintf(pfdebug, "\'");
+ *cursor += len;
+}
+
+/*
+ * Output functions by protocol message type
+ */
+
+/* NotificationResponse */
+static void
+pqTraceOutputA(FILE *f, const char *message, int *cursor, bool regress)
+{
+ fprintf(f, "NotificationResponse\t");
+ pqTraceOutputInt32(f, message, cursor, regress);
+ pqTraceOutputString(f, message, cursor, false);
+ pqTraceOutputString(f, message, cursor, false);
+}
+
+/* Bind */
+static void
+pqTraceOutputB(FILE *f, const char *message, int *cursor)
+{
+ int nparams;
+
+ fprintf(f, "Bind\t");
+ pqTraceOutputString(f, message, cursor, false);
+ pqTraceOutputString(f, message, cursor, false);
+ nparams = pqTraceOutputInt16(f, message, cursor);
+
+ for (int i = 0; i < nparams; i++)
+ pqTraceOutputInt16(f, message, cursor);
+
+ nparams = pqTraceOutputInt16(f, message, cursor);
+
+ for (int i = 0; i < nparams; i++)
+ {
+ int nbytes;
+
+ nbytes = pqTraceOutputInt32(f, message, cursor, false);
+ if (nbytes == -1)
+ continue;
+ pqTraceOutputNchar(f, nbytes, message, cursor);
+ }
+
+ nparams = pqTraceOutputInt16(f, message, cursor);
+ for (int i = 0; i < nparams; i++)
+ pqTraceOutputInt16(f, message, cursor);
+}
+
+/* Close(F) or CommandComplete(B) */
+static void
+pqTraceOutputC(FILE *f, bool toServer, const char *message, int *cursor)
+{
+ if (toServer)
+ {
+ fprintf(f, "Close\t");
+ pqTraceOutputByte1(f, message, cursor);
+ pqTraceOutputString(f, message, cursor, false);
+ }
+ else
+ {
+ fprintf(f, "CommandComplete\t");
+ pqTraceOutputString(f, message, cursor, false);
+ }
+}
+
+/* Describe(F) or DataRow(B) */
+static void
+pqTraceOutputD(FILE *f, bool toServer, const char *message, int *cursor)
+{
+ if (toServer)
+ {
+ fprintf(f, "Describe\t");
+ pqTraceOutputByte1(f, message, cursor);
+ pqTraceOutputString(f, message, cursor, false);
+ }
+ else
+ {
+ int nfields;
+ int len;
+ int i;
+
+ fprintf(f, "DataRow\t");
+ nfields = pqTraceOutputInt16(f, message, cursor);
+ for (i = 0; i < nfields; i++)
+ {
+ len = pqTraceOutputInt32(f, message, cursor, false);
+ if (len == -1)
+ continue;
+ pqTraceOutputNchar(f, len, message, cursor);
+ }
+ }
+}
+
+/* NoticeResponse / ErrorResponse */
+static void
+pqTraceOutputNR(FILE *f, const char *type, const char *message, int *cursor,
+ bool regress)
+{
+ fprintf(f, "%s\t", type);
+ for (;;)
+ {
+ char field;
+ bool suppress;
+
+ pqTraceOutputByte1(f, message, cursor);
+ field = message[*cursor - 1];
+ if (field == '\0')
+ break;
+
+ suppress = regress && (field == 'L' || field == 'F' || field == 'R');
+ pqTraceOutputString(f, message, cursor, suppress);
+ }
+}
+
+/* Execute(F) or ErrorResponse(B) */
+static void
+pqTraceOutputE(FILE *f, bool toServer, const char *message, int *cursor, bool regress)
+{
+ if (toServer)
+ {
+ fprintf(f, "Execute\t");
+ pqTraceOutputString(f, message, cursor, false);
+ pqTraceOutputInt32(f, message, cursor, false);
+ }
+ else
+ pqTraceOutputNR(f, "ErrorResponse", message, cursor, regress);
+}
+
+/* CopyFail */
+static void
+pqTraceOutputf(FILE *f, const char *message, int *cursor)
+{
+ fprintf(f, "CopyFail\t");
+ pqTraceOutputString(f, message, cursor, false);
+}
+
+/* FunctionCall */
+static void
+pqTraceOutputF(FILE *f, const char *message, int *cursor, bool regress)
+{
+ int nfields;
+ int nbytes;
+
+ fprintf(f, "FunctionCall\t");
+ pqTraceOutputInt32(f, message, cursor, regress);
+ nfields = pqTraceOutputInt16(f, message, cursor);
+
+ for (int i = 0; i < nfields; i++)
+ pqTraceOutputInt16(f, message, cursor);
+
+ nfields = pqTraceOutputInt16(f, message, cursor);
+
+ for (int i = 0; i < nfields; i++)
+ {
+ nbytes = pqTraceOutputInt32(f, message, cursor, false);
+ if (nbytes == -1)
+ continue;
+ pqTraceOutputNchar(f, nbytes, message, cursor);
+ }
+
+ pqTraceOutputInt16(f, message, cursor);
+}
+
+/* CopyInResponse */
+static void
+pqTraceOutputG(FILE *f, const char *message, int *cursor)
+{
+ int nfields;
+
+ fprintf(f, "CopyInResponse\t");
+ pqTraceOutputByte1(f, message, cursor);
+ nfields = pqTraceOutputInt16(f, message, cursor);
+
+ for (int i = 0; i < nfields; i++)
+ pqTraceOutputInt16(f, message, cursor);
+}
+
+/* CopyOutResponse */
+static void
+pqTraceOutputH(FILE *f, const char *message, int *cursor)
+{
+ int nfields;
+
+ fprintf(f, "CopyOutResponse\t");
+ pqTraceOutputByte1(f, message, cursor);
+ nfields = pqTraceOutputInt16(f, message, cursor);
+
+ for (int i = 0; i < nfields; i++)
+ pqTraceOutputInt16(f, message, cursor);
+}
+
+/* BackendKeyData */
+static void
+pqTraceOutputK(FILE *f, const char *message, int *cursor, bool regress)
+{
+ fprintf(f, "BackendKeyData\t");
+ pqTraceOutputInt32(f, message, cursor, regress);
+ pqTraceOutputInt32(f, message, cursor, regress);
+}
+
+/* Parse */
+static void
+pqTraceOutputP(FILE *f, const char *message, int *cursor, bool regress)
+{
+ int nparams;
+
+ fprintf(f, "Parse\t");
+ pqTraceOutputString(f, message, cursor, false);
+ pqTraceOutputString(f, message, cursor, false);
+ nparams = pqTraceOutputInt16(f, message, cursor);
+
+ for (int i = 0; i < nparams; i++)
+ pqTraceOutputInt32(f, message, cursor, regress);
+}
+
+/* Query */
+static void
+pqTraceOutputQ(FILE *f, const char *message, int *cursor)
+{
+ fprintf(f, "Query\t");
+ pqTraceOutputString(f, message, cursor, false);
+}
+
+/* Authentication */
+static void
+pqTraceOutputR(FILE *f, const char *message, int *cursor)
+{
+ fprintf(f, "Authentication\t");
+ pqTraceOutputInt32(f, message, cursor, false);
+}
+
+/* ParameterStatus */
+static void
+pqTraceOutputS(FILE *f, const char *message, int *cursor)
+{
+ fprintf(f, "ParameterStatus\t");
+ pqTraceOutputString(f, message, cursor, false);
+ pqTraceOutputString(f, message, cursor, false);
+}
+
+/* ParameterDescription */
+static void
+pqTraceOutputt(FILE *f, const char *message, int *cursor, bool regress)
+{
+ int nfields;
+
+ fprintf(f, "ParameterDescription\t");
+ nfields = pqTraceOutputInt16(f, message, cursor);
+
+ for (int i = 0; i < nfields; i++)
+ pqTraceOutputInt32(f, message, cursor, regress);
+}
+
+/* RowDescription */
+static void
+pqTraceOutputT(FILE *f, const char *message, int *cursor, bool regress)
+{
+ int nfields;
+
+ fprintf(f, "RowDescription\t");
+ nfields = pqTraceOutputInt16(f, message, cursor);
+
+ for (int i = 0; i < nfields; i++)
+ {
+ pqTraceOutputString(f, message, cursor, false);
+ pqTraceOutputInt32(f, message, cursor, regress);
+ pqTraceOutputInt16(f, message, cursor);
+ pqTraceOutputInt32(f, message, cursor, regress);
+ pqTraceOutputInt16(f, message, cursor);
+ pqTraceOutputInt32(f, message, cursor, false);
+ pqTraceOutputInt16(f, message, cursor);
+ }
+}
+
+/* NegotiateProtocolVersion */
+static void
+pqTraceOutputv(FILE *f, const char *message, int *cursor)
+{
+ fprintf(f, "NegotiateProtocolVersion\t");
+ pqTraceOutputInt32(f, message, cursor, false);
+ pqTraceOutputInt32(f, message, cursor, false);
+}
+
+/* FunctionCallResponse */
+static void
+pqTraceOutputV(FILE *f, const char *message, int *cursor)
+{
+ int len;
+
+ fprintf(f, "FunctionCallResponse\t");
+ len = pqTraceOutputInt32(f, message, cursor, false);
+ if (len != -1)
+ pqTraceOutputNchar(f, len, message, cursor);
+}
+
+/* CopyBothResponse */
+static void
+pqTraceOutputW(FILE *f, const char *message, int *cursor, int length)
+{
+ fprintf(f, "CopyBothResponse\t");
+ pqTraceOutputByte1(f, message, cursor);
+
+ while (length > *cursor)
+ pqTraceOutputInt16(f, message, cursor);
+}
+
+/* ReadyForQuery */
+static void
+pqTraceOutputZ(FILE *f, const char *message, int *cursor)
+{
+ fprintf(f, "ReadyForQuery\t");
+ pqTraceOutputByte1(f, message, cursor);
+}
+
+/*
+ * Print the given message to the trace output stream.
+ */
+void
+pqTraceOutputMessage(PGconn *conn, const char *message, bool toServer)
+{
+ char id;
+ int length;
+ char *prefix = toServer ? "F" : "B";
+ int logCursor = 0;
+ bool regress;
+
+ if ((conn->traceFlags & PQTRACE_SUPPRESS_TIMESTAMPS) == 0)
+ {
+ char timestr[128];
+
+ pqTraceFormatTimestamp(timestr, sizeof(timestr));
+ fprintf(conn->Pfdebug, "%s\t", timestr);
+ }
+ regress = (conn->traceFlags & PQTRACE_REGRESS_MODE) != 0;
+
+ id = message[logCursor++];
+
+ memcpy(&length, message + logCursor, 4);
+ length = (int) pg_ntoh32(length);
+ logCursor += 4;
+
+ /*
+ * In regress mode, suppress the length of ErrorResponse and
+ * NoticeResponse. The F (file name), L (line number) and R (routine
+ * name) fields can change as server code is modified, and if their
+ * lengths differ from the originals, that would break tests.
+ */
+ if (regress && !toServer && (id == 'E' || id == 'N'))
+ fprintf(conn->Pfdebug, "%s\tNN\t", prefix);
+ else
+ fprintf(conn->Pfdebug, "%s\t%d\t", prefix, length);
+
+ switch (id)
+ {
+ case '1':
+ fprintf(conn->Pfdebug, "ParseComplete");
+ /* No message content */
+ break;
+ case '2':
+ fprintf(conn->Pfdebug, "BindComplete");
+ /* No message content */
+ break;
+ case '3':
+ fprintf(conn->Pfdebug, "CloseComplete");
+ /* No message content */
+ break;
+ case 'A': /* Notification Response */
+ pqTraceOutputA(conn->Pfdebug, message, &logCursor, regress);
+ break;
+ case 'B': /* Bind */
+ pqTraceOutputB(conn->Pfdebug, message, &logCursor);
+ break;
+ case 'c':
+ fprintf(conn->Pfdebug, "CopyDone");
+ /* No message content */
+ break;
+ case 'C': /* Close(F) or Command Complete(B) */
+ pqTraceOutputC(conn->Pfdebug, toServer, message, &logCursor);
+ break;
+ case 'd': /* Copy Data */
+ /* Drop COPY data to reduce the overhead of logging. */
+ break;
+ case 'D': /* Describe(F) or Data Row(B) */
+ pqTraceOutputD(conn->Pfdebug, toServer, message, &logCursor);
+ break;
+ case 'E': /* Execute(F) or Error Response(B) */
+ pqTraceOutputE(conn->Pfdebug, toServer, message, &logCursor,
+ regress);
+ break;
+ case 'f': /* Copy Fail */
+ pqTraceOutputf(conn->Pfdebug, message, &logCursor);
+ break;
+ case 'F': /* Function Call */
+ pqTraceOutputF(conn->Pfdebug, message, &logCursor, regress);
+ break;
+ case 'G': /* Start Copy In */
+ pqTraceOutputG(conn->Pfdebug, message, &logCursor);
+ break;
+ case 'H': /* Flush(F) or Start Copy Out(B) */
+ if (!toServer)
+ pqTraceOutputH(conn->Pfdebug, message, &logCursor);
+ else
+ fprintf(conn->Pfdebug, "Flush"); /* no message content */
+ break;
+ case 'I':
+ fprintf(conn->Pfdebug, "EmptyQueryResponse");
+ /* No message content */
+ break;
+ case 'K': /* secret key data from the backend */
+ pqTraceOutputK(conn->Pfdebug, message, &logCursor, regress);
+ break;
+ case 'n':
+ fprintf(conn->Pfdebug, "NoData");
+ /* No message content */
+ break;
+ case 'N':
+ pqTraceOutputNR(conn->Pfdebug, "NoticeResponse", message,
+ &logCursor, regress);
+ break;
+ case 'P': /* Parse */
+ pqTraceOutputP(conn->Pfdebug, message, &logCursor, regress);
+ break;
+ case 'Q': /* Query */
+ pqTraceOutputQ(conn->Pfdebug, message, &logCursor);
+ break;
+ case 'R': /* Authentication */
+ pqTraceOutputR(conn->Pfdebug, message, &logCursor);
+ break;
+ case 's':
+ fprintf(conn->Pfdebug, "PortalSuspended");
+ /* No message content */
+ break;
+ case 'S': /* Parameter Status(B) or Sync(F) */
+ if (!toServer)
+ pqTraceOutputS(conn->Pfdebug, message, &logCursor);
+ else
+ fprintf(conn->Pfdebug, "Sync"); /* no message content */
+ break;
+ case 't': /* Parameter Description */
+ pqTraceOutputt(conn->Pfdebug, message, &logCursor, regress);
+ break;
+ case 'T': /* Row Description */
+ pqTraceOutputT(conn->Pfdebug, message, &logCursor, regress);
+ break;
+ case 'v': /* Negotiate Protocol Version */
+ pqTraceOutputv(conn->Pfdebug, message, &logCursor);
+ break;
+ case 'V': /* Function Call response */
+ pqTraceOutputV(conn->Pfdebug, message, &logCursor);
+ break;
+ case 'W': /* Start Copy Both */
+ pqTraceOutputW(conn->Pfdebug, message, &logCursor, length);
+ break;
+ case 'X':
+ fprintf(conn->Pfdebug, "Terminate");
+ /* No message content */
+ break;
+ case 'Z': /* Ready For Query */
+ pqTraceOutputZ(conn->Pfdebug, message, &logCursor);
+ break;
+ default:
+ fprintf(conn->Pfdebug, "Unknown message: %02x", id);
+ break;
+ }
+
+ fputc('\n', conn->Pfdebug);
+
+ /*
+ * Verify the printing routine did it right. Note that the one-byte
+ * message identifier is not included in the length, but our cursor does
+ * include it.
+ */
+ if (logCursor - 1 != length)
+ fprintf(conn->Pfdebug,
+ "mismatched message length: consumed %d, expected %d\n",
+ logCursor - 1, length);
+}
+
+/*
+ * Print special messages (those containing no type byte) to the trace output
+ * stream.
+ */
+void
+pqTraceOutputNoTypeByteMessage(PGconn *conn, const char *message)
+{
+ int length;
+ int logCursor = 0;
+
+ if ((conn->traceFlags & PQTRACE_SUPPRESS_TIMESTAMPS) == 0)
+ {
+ char timestr[128];
+
+ pqTraceFormatTimestamp(timestr, sizeof(timestr));
+ fprintf(conn->Pfdebug, "%s\t", timestr);
+ }
+
+ memcpy(&length, message + logCursor, 4);
+ length = (int) pg_ntoh32(length);
+ logCursor += 4;
+
+ fprintf(conn->Pfdebug, "F\t%d\t", length);
+
+ switch (length)
+ {
+ case 16: /* CancelRequest */
+ fprintf(conn->Pfdebug, "CancelRequest\t");
+ pqTraceOutputInt32(conn->Pfdebug, message, &logCursor, false);
+ pqTraceOutputInt32(conn->Pfdebug, message, &logCursor, false);
+ pqTraceOutputInt32(conn->Pfdebug, message, &logCursor, false);
+ break;
+ case 8: /* GSSENCRequest or SSLRequest */
+ /* These messages do not reach here. */
+ default:
+ fprintf(conn->Pfdebug, "Unknown message: length is %d", length);
+ break;
+ }
+
+ fputc('\n', conn->Pfdebug);
+}
diff --git a/contrib/libs/libpq/src/interfaces/libpq/libpq-events.c b/contrib/libs/libpq/src/interfaces/libpq/libpq-events.c
new file mode 100644
index 0000000000..229bed910f
--- /dev/null
+++ b/contrib/libs/libpq/src/interfaces/libpq/libpq-events.c
@@ -0,0 +1,211 @@
+/*-------------------------------------------------------------------------
+ *
+ * libpq-events.c
+ * functions for supporting the libpq "events" API
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/interfaces/libpq/libpq-events.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres_fe.h"
+
+#include "libpq-fe.h"
+#include "libpq-int.h"
+
+
+/*
+ * Registers an event proc with the given PGconn.
+ *
+ * The same proc can't be registered more than once in a PGconn. This
+ * restriction is required because we use the proc address to identify
+ * the event for purposes such as PQinstanceData().
+ *
+ * The name argument is used within error messages to aid in debugging.
+ * A name must be supplied, but it needn't be unique. The string is
+ * copied, so the passed value needn't be long-lived.
+ *
+ * The passThrough argument is an application specific pointer and can be set
+ * to NULL if not required. It is passed through to the event proc whenever
+ * the event proc is called, and is not otherwise touched by libpq.
+ *
+ * The function returns a non-zero if successful. If the function fails,
+ * zero is returned.
+ */
+int
+PQregisterEventProc(PGconn *conn, PGEventProc proc,
+ const char *name, void *passThrough)
+{
+ int i;
+ PGEventRegister regevt;
+
+ if (!proc || !conn || !name || !*name)
+ return false; /* bad arguments */
+
+ for (i = 0; i < conn->nEvents; i++)
+ {
+ if (conn->events[i].proc == proc)
+ return false; /* already registered */
+ }
+
+ if (conn->nEvents >= conn->eventArraySize)
+ {
+ PGEvent *e;
+ int newSize;
+
+ newSize = conn->eventArraySize ? conn->eventArraySize * 2 : 8;
+ if (conn->events)
+ e = (PGEvent *) realloc(conn->events, newSize * sizeof(PGEvent));
+ else
+ e = (PGEvent *) malloc(newSize * sizeof(PGEvent));
+
+ if (!e)
+ return false;
+
+ conn->eventArraySize = newSize;
+ conn->events = e;
+ }
+
+ conn->events[conn->nEvents].proc = proc;
+ conn->events[conn->nEvents].name = strdup(name);
+ if (!conn->events[conn->nEvents].name)
+ return false;
+ conn->events[conn->nEvents].passThrough = passThrough;
+ conn->events[conn->nEvents].data = NULL;
+ conn->events[conn->nEvents].resultInitialized = false;
+ conn->nEvents++;
+
+ regevt.conn = conn;
+ if (!proc(PGEVT_REGISTER, &regevt, passThrough))
+ {
+ conn->nEvents--;
+ free(conn->events[conn->nEvents].name);
+ return false;
+ }
+
+ return true;
+}
+
+/*
+ * Set some "instance data" for an event within a PGconn.
+ * Returns nonzero on success, zero on failure.
+ */
+int
+PQsetInstanceData(PGconn *conn, PGEventProc proc, void *data)
+{
+ int i;
+
+ if (!conn || !proc)
+ return false;
+
+ for (i = 0; i < conn->nEvents; i++)
+ {
+ if (conn->events[i].proc == proc)
+ {
+ conn->events[i].data = data;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/*
+ * Obtain the "instance data", if any, for the event.
+ */
+void *
+PQinstanceData(const PGconn *conn, PGEventProc proc)
+{
+ int i;
+
+ if (!conn || !proc)
+ return NULL;
+
+ for (i = 0; i < conn->nEvents; i++)
+ {
+ if (conn->events[i].proc == proc)
+ return conn->events[i].data;
+ }
+
+ return NULL;
+}
+
+/*
+ * Set some "instance data" for an event within a PGresult.
+ * Returns nonzero on success, zero on failure.
+ */
+int
+PQresultSetInstanceData(PGresult *result, PGEventProc proc, void *data)
+{
+ int i;
+
+ if (!result || !proc)
+ return false;
+
+ for (i = 0; i < result->nEvents; i++)
+ {
+ if (result->events[i].proc == proc)
+ {
+ result->events[i].data = data;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/*
+ * Obtain the "instance data", if any, for the event.
+ */
+void *
+PQresultInstanceData(const PGresult *result, PGEventProc proc)
+{
+ int i;
+
+ if (!result || !proc)
+ return NULL;
+
+ for (i = 0; i < result->nEvents; i++)
+ if (result->events[i].proc == proc)
+ return result->events[i].data;
+
+ return NULL;
+}
+
+/*
+ * Fire RESULTCREATE events for an application-created PGresult.
+ *
+ * The conn argument can be NULL if event procedures won't use it.
+ */
+int
+PQfireResultCreateEvents(PGconn *conn, PGresult *res)
+{
+ int result = true;
+ int i;
+
+ if (!res)
+ return false;
+
+ for (i = 0; i < res->nEvents; i++)
+ {
+ /* It's possible event was already fired, if so don't repeat it */
+ if (!res->events[i].resultInitialized)
+ {
+ PGEventResultCreate evt;
+
+ evt.conn = conn;
+ evt.result = res;
+ if (res->events[i].proc(PGEVT_RESULTCREATE, &evt,
+ res->events[i].passThrough))
+ res->events[i].resultInitialized = true;
+ else
+ result = false;
+ }
+ }
+
+ return result;
+}
diff --git a/contrib/libs/libpq/src/interfaces/libpq/libpq-events.h b/contrib/libs/libpq/src/interfaces/libpq/libpq-events.h
new file mode 100644
index 0000000000..b9d5137634
--- /dev/null
+++ b/contrib/libs/libpq/src/interfaces/libpq/libpq-events.h
@@ -0,0 +1,94 @@
+/*-------------------------------------------------------------------------
+ *
+ * libpq-events.h
+ * This file contains definitions that are useful to applications
+ * that invoke the libpq "events" API, but are not interesting to
+ * ordinary users of libpq.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/interfaces/libpq/libpq-events.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef LIBPQ_EVENTS_H
+#define LIBPQ_EVENTS_H
+
+#include "libpq-fe.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* Callback Event Ids */
+typedef enum
+{
+ PGEVT_REGISTER,
+ PGEVT_CONNRESET,
+ PGEVT_CONNDESTROY,
+ PGEVT_RESULTCREATE,
+ PGEVT_RESULTCOPY,
+ PGEVT_RESULTDESTROY
+} PGEventId;
+
+typedef struct
+{
+ PGconn *conn;
+} PGEventRegister;
+
+typedef struct
+{
+ PGconn *conn;
+} PGEventConnReset;
+
+typedef struct
+{
+ PGconn *conn;
+} PGEventConnDestroy;
+
+typedef struct
+{
+ PGconn *conn;
+ PGresult *result;
+} PGEventResultCreate;
+
+typedef struct
+{
+ const PGresult *src;
+ PGresult *dest;
+} PGEventResultCopy;
+
+typedef struct
+{
+ PGresult *result;
+} PGEventResultDestroy;
+
+typedef int (*PGEventProc) (PGEventId evtId, void *evtInfo, void *passThrough);
+
+/* Registers an event proc with the given PGconn. */
+extern int PQregisterEventProc(PGconn *conn, PGEventProc proc,
+ const char *name, void *passThrough);
+
+/* Sets the PGconn instance data for the provided proc to data. */
+extern int PQsetInstanceData(PGconn *conn, PGEventProc proc, void *data);
+
+/* Gets the PGconn instance data for the provided proc. */
+extern void *PQinstanceData(const PGconn *conn, PGEventProc proc);
+
+/* Sets the PGresult instance data for the provided proc to data. */
+extern int PQresultSetInstanceData(PGresult *result, PGEventProc proc, void *data);
+
+/* Gets the PGresult instance data for the provided proc. */
+extern void *PQresultInstanceData(const PGresult *result, PGEventProc proc);
+
+/* Fires RESULTCREATE events for an application-created PGresult. */
+extern int PQfireResultCreateEvents(PGconn *conn, PGresult *res);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LIBPQ_EVENTS_H */
diff --git a/contrib/libs/libpq/src/interfaces/libpq/libpq-fe.h b/contrib/libs/libpq/src/interfaces/libpq/libpq-fe.h
new file mode 100644
index 0000000000..7476dbe0e9
--- /dev/null
+++ b/contrib/libs/libpq/src/interfaces/libpq/libpq-fe.h
@@ -0,0 +1,675 @@
+/*-------------------------------------------------------------------------
+ *
+ * libpq-fe.h
+ * This file contains definitions for structures and
+ * externs for functions used by frontend postgres applications.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/interfaces/libpq/libpq-fe.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef LIBPQ_FE_H
+#define LIBPQ_FE_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <stdio.h>
+
+/*
+ * postgres_ext.h defines the backend's externally visible types,
+ * such as Oid.
+ */
+#include "postgres_ext.h"
+
+/*
+ * These symbols may be used in compile-time #ifdef tests for the availability
+ * of newer libpq features.
+ */
+/* Indicates presence of PQenterPipelineMode and friends */
+#define LIBPQ_HAS_PIPELINING 1
+/* Indicates presence of PQsetTraceFlags; also new PQtrace output format */
+#define LIBPQ_HAS_TRACE_FLAGS 1
+/* Indicates that PQsslAttribute(NULL, "library") is useful */
+#define LIBPQ_HAS_SSL_LIBRARY_DETECTION 1
+
+/*
+ * Option flags for PQcopyResult
+ */
+#define PG_COPYRES_ATTRS 0x01
+#define PG_COPYRES_TUPLES 0x02 /* Implies PG_COPYRES_ATTRS */
+#define PG_COPYRES_EVENTS 0x04
+#define PG_COPYRES_NOTICEHOOKS 0x08
+
+/* Application-visible enum types */
+
+/*
+ * Although it is okay to add to these lists, values which become unused
+ * should never be removed, nor should constants be redefined - that would
+ * break compatibility with existing code.
+ */
+
+typedef enum
+{
+ CONNECTION_OK,
+ CONNECTION_BAD,
+ /* Non-blocking mode only below here */
+
+ /*
+ * The existence of these should never be relied upon - they should only
+ * be used for user feedback or similar purposes.
+ */
+ CONNECTION_STARTED, /* Waiting for connection to be made. */
+ CONNECTION_MADE, /* Connection OK; waiting to send. */
+ CONNECTION_AWAITING_RESPONSE, /* Waiting for a response from the
+ * postmaster. */
+ CONNECTION_AUTH_OK, /* Received authentication; waiting for
+ * backend startup. */
+ CONNECTION_SETENV, /* This state is no longer used. */
+ CONNECTION_SSL_STARTUP, /* Negotiating SSL. */
+ CONNECTION_NEEDED, /* Internal state: connect() needed */
+ CONNECTION_CHECK_WRITABLE, /* Checking if session is read-write. */
+ CONNECTION_CONSUME, /* Consuming any extra messages. */
+ CONNECTION_GSS_STARTUP, /* Negotiating GSSAPI. */
+ CONNECTION_CHECK_TARGET, /* Checking target server properties. */
+ CONNECTION_CHECK_STANDBY /* Checking if server is in standby mode. */
+} ConnStatusType;
+
+typedef enum
+{
+ PGRES_POLLING_FAILED = 0,
+ PGRES_POLLING_READING, /* These two indicate that one may */
+ PGRES_POLLING_WRITING, /* use select before polling again. */
+ PGRES_POLLING_OK,
+ PGRES_POLLING_ACTIVE /* unused; keep for awhile for backwards
+ * compatibility */
+} PostgresPollingStatusType;
+
+typedef enum
+{
+ PGRES_EMPTY_QUERY = 0, /* empty query string was executed */
+ PGRES_COMMAND_OK, /* a query command that doesn't return
+ * anything was executed properly by the
+ * backend */
+ PGRES_TUPLES_OK, /* a query command that returns tuples was
+ * executed properly by the backend, PGresult
+ * contains the result tuples */
+ PGRES_COPY_OUT, /* Copy Out data transfer in progress */
+ PGRES_COPY_IN, /* Copy In data transfer in progress */
+ PGRES_BAD_RESPONSE, /* an unexpected response was recv'd from the
+ * backend */
+ PGRES_NONFATAL_ERROR, /* notice or warning message */
+ PGRES_FATAL_ERROR, /* query failed */
+ PGRES_COPY_BOTH, /* Copy In/Out data transfer in progress */
+ PGRES_SINGLE_TUPLE, /* single tuple from larger resultset */
+ PGRES_PIPELINE_SYNC, /* pipeline synchronization point */
+ PGRES_PIPELINE_ABORTED /* Command didn't run because of an abort
+ * earlier in a pipeline */
+} ExecStatusType;
+
+typedef enum
+{
+ PQTRANS_IDLE, /* connection idle */
+ PQTRANS_ACTIVE, /* command in progress */
+ PQTRANS_INTRANS, /* idle, within transaction block */
+ PQTRANS_INERROR, /* idle, within failed transaction */
+ PQTRANS_UNKNOWN /* cannot determine status */
+} PGTransactionStatusType;
+
+typedef enum
+{
+ PQERRORS_TERSE, /* single-line error messages */
+ PQERRORS_DEFAULT, /* recommended style */
+ PQERRORS_VERBOSE, /* all the facts, ma'am */
+ PQERRORS_SQLSTATE /* only error severity and SQLSTATE code */
+} PGVerbosity;
+
+typedef enum
+{
+ PQSHOW_CONTEXT_NEVER, /* never show CONTEXT field */
+ PQSHOW_CONTEXT_ERRORS, /* show CONTEXT for errors only (default) */
+ PQSHOW_CONTEXT_ALWAYS /* always show CONTEXT field */
+} PGContextVisibility;
+
+/*
+ * PGPing - The ordering of this enum should not be altered because the
+ * values are exposed externally via pg_isready.
+ */
+
+typedef enum
+{
+ PQPING_OK, /* server is accepting connections */
+ PQPING_REJECT, /* server is alive but rejecting connections */
+ PQPING_NO_RESPONSE, /* could not establish connection */
+ PQPING_NO_ATTEMPT /* connection not attempted (bad params) */
+} PGPing;
+
+/*
+ * PGpipelineStatus - Current status of pipeline mode
+ */
+typedef enum
+{
+ PQ_PIPELINE_OFF,
+ PQ_PIPELINE_ON,
+ PQ_PIPELINE_ABORTED
+} PGpipelineStatus;
+
+/* PGconn encapsulates a connection to the backend.
+ * The contents of this struct are not supposed to be known to applications.
+ */
+typedef struct pg_conn PGconn;
+
+/* PGresult encapsulates the result of a query (or more precisely, of a single
+ * SQL command --- a query string given to PQsendQuery can contain multiple
+ * commands and thus return multiple PGresult objects).
+ * The contents of this struct are not supposed to be known to applications.
+ */
+typedef struct pg_result PGresult;
+
+/* PGcancel encapsulates the information needed to cancel a running
+ * query on an existing connection.
+ * The contents of this struct are not supposed to be known to applications.
+ */
+typedef struct pg_cancel PGcancel;
+
+/* PGnotify represents the occurrence of a NOTIFY message.
+ * Ideally this would be an opaque typedef, but it's so simple that it's
+ * unlikely to change.
+ * NOTE: in Postgres 6.4 and later, the be_pid is the notifying backend's,
+ * whereas in earlier versions it was always your own backend's PID.
+ */
+typedef struct pgNotify
+{
+ char *relname; /* notification condition name */
+ int be_pid; /* process ID of notifying server process */
+ char *extra; /* notification parameter */
+ /* Fields below here are private to libpq; apps should not use 'em */
+ struct pgNotify *next; /* list link */
+} PGnotify;
+
+/* Function types for notice-handling callbacks */
+typedef void (*PQnoticeReceiver) (void *arg, const PGresult *res);
+typedef void (*PQnoticeProcessor) (void *arg, const char *message);
+
+/* Print options for PQprint() */
+typedef char pqbool;
+
+typedef struct _PQprintOpt
+{
+ pqbool header; /* print output field headings and row count */
+ pqbool align; /* fill align the fields */
+ pqbool standard; /* old brain dead format */
+ pqbool html3; /* output html tables */
+ pqbool expanded; /* expand tables */
+ pqbool pager; /* use pager for output if needed */
+ char *fieldSep; /* field separator */
+ char *tableOpt; /* insert to HTML <table ...> */
+ char *caption; /* HTML <caption> */
+ char **fieldName; /* null terminated array of replacement field
+ * names */
+} PQprintOpt;
+
+/* ----------------
+ * Structure for the conninfo parameter definitions returned by PQconndefaults
+ * or PQconninfoParse.
+ *
+ * All fields except "val" point at static strings which must not be altered.
+ * "val" is either NULL or a malloc'd current-value string. PQconninfoFree()
+ * will release both the val strings and the PQconninfoOption array itself.
+ * ----------------
+ */
+typedef struct _PQconninfoOption
+{
+ char *keyword; /* The keyword of the option */
+ char *envvar; /* Fallback environment variable name */
+ char *compiled; /* Fallback compiled in default value */
+ char *val; /* Option's current value, or NULL */
+ char *label; /* Label for field in connect dialog */
+ char *dispchar; /* Indicates how to display this field in a
+ * connect dialog. Values are: "" Display
+ * entered value as is "*" Password field -
+ * hide value "D" Debug option - don't show
+ * by default */
+ int dispsize; /* Field size in characters for dialog */
+} PQconninfoOption;
+
+/* ----------------
+ * PQArgBlock -- structure for PQfn() arguments
+ * ----------------
+ */
+typedef struct
+{
+ int len;
+ int isint;
+ union
+ {
+ int *ptr; /* can't use void (dec compiler barfs) */
+ int integer;
+ } u;
+} PQArgBlock;
+
+/* ----------------
+ * PGresAttDesc -- Data about a single attribute (column) of a query result
+ * ----------------
+ */
+typedef struct pgresAttDesc
+{
+ char *name; /* column name */
+ Oid tableid; /* source table, if known */
+ int columnid; /* source column, if known */
+ int format; /* format code for value (text/binary) */
+ Oid typid; /* type id */
+ int typlen; /* type size */
+ int atttypmod; /* type-specific modifier info */
+} PGresAttDesc;
+
+/* ----------------
+ * Exported functions of libpq
+ * ----------------
+ */
+
+/* === in fe-connect.c === */
+
+/* make a new client connection to the backend */
+/* Asynchronous (non-blocking) */
+extern PGconn *PQconnectStart(const char *conninfo);
+extern PGconn *PQconnectStartParams(const char *const *keywords,
+ const char *const *values, int expand_dbname);
+extern PostgresPollingStatusType PQconnectPoll(PGconn *conn);
+
+/* Synchronous (blocking) */
+extern PGconn *PQconnectdb(const char *conninfo);
+extern PGconn *PQconnectdbParams(const char *const *keywords,
+ const char *const *values, int expand_dbname);
+extern PGconn *PQsetdbLogin(const char *pghost, const char *pgport,
+ const char *pgoptions, const char *pgtty,
+ const char *dbName,
+ const char *login, const char *pwd);
+
+#define PQsetdb(M_PGHOST,M_PGPORT,M_PGOPT,M_PGTTY,M_DBNAME) \
+ PQsetdbLogin(M_PGHOST, M_PGPORT, M_PGOPT, M_PGTTY, M_DBNAME, NULL, NULL)
+
+/* close the current connection and free the PGconn data structure */
+extern void PQfinish(PGconn *conn);
+
+/* get info about connection options known to PQconnectdb */
+extern PQconninfoOption *PQconndefaults(void);
+
+/* parse connection options in same way as PQconnectdb */
+extern PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg);
+
+/* return the connection options used by a live connection */
+extern PQconninfoOption *PQconninfo(PGconn *conn);
+
+/* free the data structure returned by PQconndefaults() or PQconninfoParse() */
+extern void PQconninfoFree(PQconninfoOption *connOptions);
+
+/*
+ * close the current connection and reestablish a new one with the same
+ * parameters
+ */
+/* Asynchronous (non-blocking) */
+extern int PQresetStart(PGconn *conn);
+extern PostgresPollingStatusType PQresetPoll(PGconn *conn);
+
+/* Synchronous (blocking) */
+extern void PQreset(PGconn *conn);
+
+/* request a cancel structure */
+extern PGcancel *PQgetCancel(PGconn *conn);
+
+/* free a cancel structure */
+extern void PQfreeCancel(PGcancel *cancel);
+
+/* issue a cancel request */
+extern int PQcancel(PGcancel *cancel, char *errbuf, int errbufsize);
+
+/* backwards compatible version of PQcancel; not thread-safe */
+extern int PQrequestCancel(PGconn *conn);
+
+/* Accessor functions for PGconn objects */
+extern char *PQdb(const PGconn *conn);
+extern char *PQuser(const PGconn *conn);
+extern char *PQpass(const PGconn *conn);
+extern char *PQhost(const PGconn *conn);
+extern char *PQhostaddr(const PGconn *conn);
+extern char *PQport(const PGconn *conn);
+extern char *PQtty(const PGconn *conn);
+extern char *PQoptions(const PGconn *conn);
+extern ConnStatusType PQstatus(const PGconn *conn);
+extern PGTransactionStatusType PQtransactionStatus(const PGconn *conn);
+extern const char *PQparameterStatus(const PGconn *conn,
+ const char *paramName);
+extern int PQprotocolVersion(const PGconn *conn);
+extern int PQserverVersion(const PGconn *conn);
+extern char *PQerrorMessage(const PGconn *conn);
+extern int PQsocket(const PGconn *conn);
+extern int PQbackendPID(const PGconn *conn);
+extern PGpipelineStatus PQpipelineStatus(const PGconn *conn);
+extern int PQconnectionNeedsPassword(const PGconn *conn);
+extern int PQconnectionUsedPassword(const PGconn *conn);
+extern int PQconnectionUsedGSSAPI(const PGconn *conn);
+extern int PQclientEncoding(const PGconn *conn);
+extern int PQsetClientEncoding(PGconn *conn, const char *encoding);
+
+/* SSL information functions */
+extern int PQsslInUse(PGconn *conn);
+extern void *PQsslStruct(PGconn *conn, const char *struct_name);
+extern const char *PQsslAttribute(PGconn *conn, const char *attribute_name);
+extern const char *const *PQsslAttributeNames(PGconn *conn);
+
+/* Get the OpenSSL structure associated with a connection. Returns NULL for
+ * unencrypted connections or if any other TLS library is in use. */
+extern void *PQgetssl(PGconn *conn);
+
+/* Tell libpq whether it needs to initialize OpenSSL */
+extern void PQinitSSL(int do_init);
+
+/* More detailed way to tell libpq whether it needs to initialize OpenSSL */
+extern void PQinitOpenSSL(int do_ssl, int do_crypto);
+
+/* Return true if GSSAPI encryption is in use */
+extern int PQgssEncInUse(PGconn *conn);
+
+/* Returns GSSAPI context if GSSAPI is in use */
+extern void *PQgetgssctx(PGconn *conn);
+
+/* Set verbosity for PQerrorMessage and PQresultErrorMessage */
+extern PGVerbosity PQsetErrorVerbosity(PGconn *conn, PGVerbosity verbosity);
+
+/* Set CONTEXT visibility for PQerrorMessage and PQresultErrorMessage */
+extern PGContextVisibility PQsetErrorContextVisibility(PGconn *conn,
+ PGContextVisibility show_context);
+
+/* Override default notice handling routines */
+extern PQnoticeReceiver PQsetNoticeReceiver(PGconn *conn,
+ PQnoticeReceiver proc,
+ void *arg);
+extern PQnoticeProcessor PQsetNoticeProcessor(PGconn *conn,
+ PQnoticeProcessor proc,
+ void *arg);
+
+/*
+ * Used to set callback that prevents concurrent access to
+ * non-thread safe functions that libpq needs.
+ * The default implementation uses a libpq internal mutex.
+ * Only required for multithreaded apps that use kerberos
+ * both within their app and for postgresql connections.
+ */
+typedef void (*pgthreadlock_t) (int acquire);
+
+extern pgthreadlock_t PQregisterThreadLock(pgthreadlock_t newhandler);
+
+/* === in fe-trace.c === */
+extern void PQtrace(PGconn *conn, FILE *debug_port);
+extern void PQuntrace(PGconn *conn);
+
+/* flags controlling trace output: */
+/* omit timestamps from each line */
+#define PQTRACE_SUPPRESS_TIMESTAMPS (1<<0)
+/* redact portions of some messages, for testing frameworks */
+#define PQTRACE_REGRESS_MODE (1<<1)
+extern void PQsetTraceFlags(PGconn *conn, int flags);
+
+/* === in fe-exec.c === */
+
+/* Simple synchronous query */
+extern PGresult *PQexec(PGconn *conn, const char *query);
+extern PGresult *PQexecParams(PGconn *conn,
+ const char *command,
+ int nParams,
+ const Oid *paramTypes,
+ const char *const *paramValues,
+ const int *paramLengths,
+ const int *paramFormats,
+ int resultFormat);
+extern PGresult *PQprepare(PGconn *conn, const char *stmtName,
+ const char *query, int nParams,
+ const Oid *paramTypes);
+extern PGresult *PQexecPrepared(PGconn *conn,
+ const char *stmtName,
+ int nParams,
+ const char *const *paramValues,
+ const int *paramLengths,
+ const int *paramFormats,
+ int resultFormat);
+
+/* Interface for multiple-result or asynchronous queries */
+#define PQ_QUERY_PARAM_MAX_LIMIT 65535
+
+extern int PQsendQuery(PGconn *conn, const char *query);
+extern int PQsendQueryParams(PGconn *conn,
+ const char *command,
+ int nParams,
+ const Oid *paramTypes,
+ const char *const *paramValues,
+ const int *paramLengths,
+ const int *paramFormats,
+ int resultFormat);
+extern int PQsendPrepare(PGconn *conn, const char *stmtName,
+ const char *query, int nParams,
+ const Oid *paramTypes);
+extern int PQsendQueryPrepared(PGconn *conn,
+ const char *stmtName,
+ int nParams,
+ const char *const *paramValues,
+ const int *paramLengths,
+ const int *paramFormats,
+ int resultFormat);
+extern int PQsetSingleRowMode(PGconn *conn);
+extern PGresult *PQgetResult(PGconn *conn);
+
+/* Routines for managing an asynchronous query */
+extern int PQisBusy(PGconn *conn);
+extern int PQconsumeInput(PGconn *conn);
+
+/* Routines for pipeline mode management */
+extern int PQenterPipelineMode(PGconn *conn);
+extern int PQexitPipelineMode(PGconn *conn);
+extern int PQpipelineSync(PGconn *conn);
+extern int PQsendFlushRequest(PGconn *conn);
+
+/* LISTEN/NOTIFY support */
+extern PGnotify *PQnotifies(PGconn *conn);
+
+/* Routines for copy in/out */
+extern int PQputCopyData(PGconn *conn, const char *buffer, int nbytes);
+extern int PQputCopyEnd(PGconn *conn, const char *errormsg);
+extern int PQgetCopyData(PGconn *conn, char **buffer, int async);
+
+/* Deprecated routines for copy in/out */
+extern int PQgetline(PGconn *conn, char *buffer, int length);
+extern int PQputline(PGconn *conn, const char *string);
+extern int PQgetlineAsync(PGconn *conn, char *buffer, int bufsize);
+extern int PQputnbytes(PGconn *conn, const char *buffer, int nbytes);
+extern int PQendcopy(PGconn *conn);
+
+/* Set blocking/nonblocking connection to the backend */
+extern int PQsetnonblocking(PGconn *conn, int arg);
+extern int PQisnonblocking(const PGconn *conn);
+extern int PQisthreadsafe(void);
+extern PGPing PQping(const char *conninfo);
+extern PGPing PQpingParams(const char *const *keywords,
+ const char *const *values, int expand_dbname);
+
+/* Force the write buffer to be written (or at least try) */
+extern int PQflush(PGconn *conn);
+
+/*
+ * "Fast path" interface --- not really recommended for application
+ * use
+ */
+extern PGresult *PQfn(PGconn *conn,
+ int fnid,
+ int *result_buf,
+ int *result_len,
+ int result_is_int,
+ const PQArgBlock *args,
+ int nargs);
+
+/* Accessor functions for PGresult objects */
+extern ExecStatusType PQresultStatus(const PGresult *res);
+extern char *PQresStatus(ExecStatusType status);
+extern char *PQresultErrorMessage(const PGresult *res);
+extern char *PQresultVerboseErrorMessage(const PGresult *res,
+ PGVerbosity verbosity,
+ PGContextVisibility show_context);
+extern char *PQresultErrorField(const PGresult *res, int fieldcode);
+extern int PQntuples(const PGresult *res);
+extern int PQnfields(const PGresult *res);
+extern int PQbinaryTuples(const PGresult *res);
+extern char *PQfname(const PGresult *res, int field_num);
+extern int PQfnumber(const PGresult *res, const char *field_name);
+extern Oid PQftable(const PGresult *res, int field_num);
+extern int PQftablecol(const PGresult *res, int field_num);
+extern int PQfformat(const PGresult *res, int field_num);
+extern Oid PQftype(const PGresult *res, int field_num);
+extern int PQfsize(const PGresult *res, int field_num);
+extern int PQfmod(const PGresult *res, int field_num);
+extern char *PQcmdStatus(PGresult *res);
+extern char *PQoidStatus(const PGresult *res); /* old and ugly */
+extern Oid PQoidValue(const PGresult *res); /* new and improved */
+extern char *PQcmdTuples(PGresult *res);
+extern char *PQgetvalue(const PGresult *res, int tup_num, int field_num);
+extern int PQgetlength(const PGresult *res, int tup_num, int field_num);
+extern int PQgetisnull(const PGresult *res, int tup_num, int field_num);
+extern int PQnparams(const PGresult *res);
+extern Oid PQparamtype(const PGresult *res, int param_num);
+
+/* Describe prepared statements and portals */
+extern PGresult *PQdescribePrepared(PGconn *conn, const char *stmt);
+extern PGresult *PQdescribePortal(PGconn *conn, const char *portal);
+extern int PQsendDescribePrepared(PGconn *conn, const char *stmt);
+extern int PQsendDescribePortal(PGconn *conn, const char *portal);
+
+/* Delete a PGresult */
+extern void PQclear(PGresult *res);
+
+/* For freeing other alloc'd results, such as PGnotify structs */
+extern void PQfreemem(void *ptr);
+
+/* Exists for backward compatibility. bjm 2003-03-24 */
+#define PQfreeNotify(ptr) PQfreemem(ptr)
+
+/* Error when no password was given. */
+/* Note: depending on this is deprecated; use PQconnectionNeedsPassword(). */
+#define PQnoPasswordSupplied "fe_sendauth: no password supplied\n"
+
+/* Create and manipulate PGresults */
+extern PGresult *PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status);
+extern PGresult *PQcopyResult(const PGresult *src, int flags);
+extern int PQsetResultAttrs(PGresult *res, int numAttributes, PGresAttDesc *attDescs);
+extern void *PQresultAlloc(PGresult *res, size_t nBytes);
+extern size_t PQresultMemorySize(const PGresult *res);
+extern int PQsetvalue(PGresult *res, int tup_num, int field_num, char *value, int len);
+
+/* Quoting strings before inclusion in queries. */
+extern size_t PQescapeStringConn(PGconn *conn,
+ char *to, const char *from, size_t length,
+ int *error);
+extern char *PQescapeLiteral(PGconn *conn, const char *str, size_t len);
+extern char *PQescapeIdentifier(PGconn *conn, const char *str, size_t len);
+extern unsigned char *PQescapeByteaConn(PGconn *conn,
+ const unsigned char *from, size_t from_length,
+ size_t *to_length);
+extern unsigned char *PQunescapeBytea(const unsigned char *strtext,
+ size_t *retbuflen);
+
+/* These forms are deprecated! */
+extern size_t PQescapeString(char *to, const char *from, size_t length);
+extern unsigned char *PQescapeBytea(const unsigned char *from, size_t from_length,
+ size_t *to_length);
+
+
+
+/* === in fe-print.c === */
+
+extern void PQprint(FILE *fout, /* output stream */
+ const PGresult *res,
+ const PQprintOpt *po); /* option structure */
+
+/*
+ * really old printing routines
+ */
+extern void PQdisplayTuples(const PGresult *res,
+ FILE *fp, /* where to send the output */
+ int fillAlign, /* pad the fields with spaces */
+ const char *fieldSep, /* field separator */
+ int printHeader, /* display headers? */
+ int quiet);
+
+extern void PQprintTuples(const PGresult *res,
+ FILE *fout, /* output stream */
+ int PrintAttNames, /* print attribute names */
+ int TerseOutput, /* delimiter bars */
+ int colWidth); /* width of column, if 0, use
+ * variable width */
+
+
+/* === in fe-lobj.c === */
+
+/* Large-object access routines */
+extern int lo_open(PGconn *conn, Oid lobjId, int mode);
+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 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 int lo_truncate(PGconn *conn, int fd, size_t len);
+extern int lo_truncate64(PGconn *conn, int fd, pg_int64 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);
+extern int lo_export(PGconn *conn, Oid lobjId, const char *filename);
+
+/* === in fe-misc.c === */
+
+/* Get the version of the libpq library in use */
+extern int PQlibVersion(void);
+
+/* Determine length of multibyte encoded char at *s */
+extern int PQmblen(const char *s, int encoding);
+
+/* Same, but not more than the distance to the end of string s */
+extern int PQmblenBounded(const char *s, int encoding);
+
+/* Determine display length of multibyte encoded char at *s */
+extern int PQdsplen(const char *s, int encoding);
+
+/* Get encoding id from environment variable PGCLIENTENCODING */
+extern int PQenv2encoding(void);
+
+/* === in fe-auth.c === */
+
+extern char *PQencryptPassword(const char *passwd, const char *user);
+extern char *PQencryptPasswordConn(PGconn *conn, const char *passwd, const char *user, const char *algorithm);
+
+/* === in encnames.c === */
+
+extern int pg_char_to_encoding(const char *name);
+extern const char *pg_encoding_to_char(int encoding);
+extern int pg_valid_server_encoding_id(int encoding);
+
+/* === in fe-secure-openssl.c === */
+
+/* Support for overriding sslpassword handling with a callback */
+typedef int (*PQsslKeyPassHook_OpenSSL_type) (char *buf, int size, PGconn *conn);
+extern PQsslKeyPassHook_OpenSSL_type PQgetSSLKeyPassHook_OpenSSL(void);
+extern void PQsetSSLKeyPassHook_OpenSSL(PQsslKeyPassHook_OpenSSL_type hook);
+extern int PQdefaultSSLKeyPassHook_OpenSSL(char *buf, int size, PGconn *conn);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LIBPQ_FE_H */
diff --git a/contrib/libs/libpq/src/interfaces/libpq/libpq-int.h b/contrib/libs/libpq/src/interfaces/libpq/libpq-int.h
new file mode 100644
index 0000000000..0045f83cbf
--- /dev/null
+++ b/contrib/libs/libpq/src/interfaces/libpq/libpq-int.h
@@ -0,0 +1,939 @@
+/*-------------------------------------------------------------------------
+ *
+ * libpq-int.h
+ * This file contains internal definitions meant to be used only by
+ * the frontend libpq library, not by applications that call it.
+ *
+ * An application can include this file if it wants to bypass the
+ * official API defined by libpq-fe.h, but code that does so is much
+ * more likely to break across PostgreSQL releases than code that uses
+ * only the official API.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/interfaces/libpq/libpq-int.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef LIBPQ_INT_H
+#define LIBPQ_INT_H
+
+/* We assume libpq-fe.h has already been included. */
+#include "libpq-events.h"
+
+#include <netdb.h>
+#include <sys/socket.h>
+#include <time.h>
+/* MinGW has sys/time.h, but MSVC doesn't */
+#ifndef _MSC_VER
+#include <sys/time.h>
+#endif
+
+#ifdef ENABLE_THREAD_SAFETY
+#ifdef WIN32
+#include "pthread-win32.h"
+#else
+#include <pthread.h>
+#endif
+#include <signal.h>
+#endif
+
+/* include stuff common to fe and be */
+#include "libpq/pqcomm.h"
+/* include stuff found in fe only */
+#include "fe-auth-sasl.h"
+#include "pqexpbuffer.h"
+
+#ifdef ENABLE_GSS
+#if defined(HAVE_GSSAPI_H)
+#include <gssapi.h>
+#else
+#include <gssapi/gssapi.h>
+#endif
+#endif
+
+#ifdef ENABLE_SSPI
+#define SECURITY_WIN32
+#if defined(WIN32) && !defined(_MSC_VER)
+#include <ntsecapi.h>
+#endif
+#include <security.h>
+#undef SECURITY_WIN32
+
+#ifndef ENABLE_GSS
+/*
+ * Define a fake structure compatible with GSSAPI on Unix.
+ */
+typedef struct
+{
+ void *value;
+ int length;
+} gss_buffer_desc;
+#endif
+#endif /* ENABLE_SSPI */
+
+#ifdef USE_OPENSSL
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+
+#ifndef OPENSSL_NO_ENGINE
+#define USE_SSL_ENGINE
+#endif
+#endif /* USE_OPENSSL */
+
+#include "common/pg_prng.h"
+
+/*
+ * POSTGRES backend dependent Constants.
+ */
+#define CMDSTATUS_LEN 64 /* should match COMPLETION_TAG_BUFSIZE */
+
+/*
+ * PGresult and the subsidiary types PGresAttDesc, PGresAttValue
+ * represent the result of a query (or more precisely, of a single SQL
+ * command --- a query string given to PQexec can contain multiple commands).
+ * Note we assume that a single command can return at most one tuple group,
+ * hence there is no need for multiple descriptor sets.
+ */
+
+/* Subsidiary-storage management structure for PGresult.
+ * See space management routines in fe-exec.c for details.
+ * Note that space[k] refers to the k'th byte starting from the physical
+ * head of the block --- it's a union, not a struct!
+ */
+typedef union pgresult_data PGresult_data;
+
+union pgresult_data
+{
+ PGresult_data *next; /* link to next block, or NULL */
+ char space[1]; /* dummy for accessing block as bytes */
+};
+
+/* Data about a single parameter of a prepared statement */
+typedef struct pgresParamDesc
+{
+ Oid typid; /* type id */
+} PGresParamDesc;
+
+/*
+ * Data for a single attribute of a single tuple
+ *
+ * We use char* for Attribute values.
+ *
+ * The value pointer always points to a null-terminated area; we add a
+ * null (zero) byte after whatever the backend sends us. This is only
+ * particularly useful for text values ... with a binary value, the
+ * value might have embedded nulls, so the application can't use C string
+ * operators on it. But we add a null anyway for consistency.
+ * Note that the value itself does not contain a length word.
+ *
+ * A NULL attribute is a special case in two ways: its len field is NULL_LEN
+ * and its value field points to null_field in the owning PGresult. All the
+ * NULL attributes in a query result point to the same place (there's no need
+ * to store a null string separately for each one).
+ */
+
+#define NULL_LEN (-1) /* pg_result len for NULL value */
+
+typedef struct pgresAttValue
+{
+ int len; /* length in bytes of the value */
+ char *value; /* actual value, plus terminating zero byte */
+} PGresAttValue;
+
+/* Typedef for message-field list entries */
+typedef struct pgMessageField
+{
+ struct pgMessageField *next; /* list link */
+ char code; /* field code */
+ char contents[FLEXIBLE_ARRAY_MEMBER]; /* value, nul-terminated */
+} PGMessageField;
+
+/* Fields needed for notice handling */
+typedef struct
+{
+ PQnoticeReceiver noticeRec; /* notice message receiver */
+ void *noticeRecArg;
+ PQnoticeProcessor noticeProc; /* notice message processor */
+ void *noticeProcArg;
+} PGNoticeHooks;
+
+typedef struct PGEvent
+{
+ PGEventProc proc; /* the function to call on events */
+ char *name; /* used only for error messages */
+ void *passThrough; /* pointer supplied at registration time */
+ void *data; /* optional state (instance) data */
+ bool resultInitialized; /* T if RESULTCREATE/COPY succeeded */
+} PGEvent;
+
+struct pg_result
+{
+ int ntups;
+ int numAttributes;
+ PGresAttDesc *attDescs;
+ PGresAttValue **tuples; /* each PGresult tuple is an array of
+ * PGresAttValue's */
+ int tupArrSize; /* allocated size of tuples array */
+ int numParameters;
+ PGresParamDesc *paramDescs;
+ ExecStatusType resultStatus;
+ char cmdStatus[CMDSTATUS_LEN]; /* cmd status from the query */
+ int binary; /* binary tuple values if binary == 1,
+ * otherwise text */
+
+ /*
+ * These fields are copied from the originating PGconn, so that operations
+ * on the PGresult don't have to reference the PGconn.
+ */
+ PGNoticeHooks noticeHooks;
+ PGEvent *events;
+ int nEvents;
+ int client_encoding; /* encoding id */
+
+ /*
+ * Error information (all NULL if not an error result). errMsg is the
+ * "overall" error message returned by PQresultErrorMessage. If we have
+ * per-field info then it is stored in a linked list.
+ */
+ char *errMsg; /* error message, or NULL if no error */
+ PGMessageField *errFields; /* message broken into fields */
+ char *errQuery; /* text of triggering query, if available */
+
+ /* All NULL attributes in the query result point to this null string */
+ char null_field[1];
+
+ /*
+ * Space management information. Note that attDescs and error stuff, if
+ * not null, point into allocated blocks. But tuples points to a
+ * separately malloc'd block, so that we can realloc it.
+ */
+ PGresult_data *curBlock; /* most recently allocated block */
+ int curOffset; /* start offset of free space in block */
+ int spaceLeft; /* number of free bytes remaining in block */
+
+ size_t memorySize; /* total space allocated for this PGresult */
+};
+
+/* PGAsyncStatusType defines the state of the query-execution state machine */
+typedef enum
+{
+ PGASYNC_IDLE, /* nothing's happening, dude */
+ PGASYNC_BUSY, /* query in progress */
+ PGASYNC_READY, /* query done, waiting for client to fetch
+ * result */
+ PGASYNC_READY_MORE, /* query done, waiting for client to fetch
+ * result, more results expected from this
+ * query */
+ PGASYNC_COPY_IN, /* Copy In data transfer in progress */
+ PGASYNC_COPY_OUT, /* Copy Out data transfer in progress */
+ PGASYNC_COPY_BOTH, /* Copy In/Out data transfer in progress */
+ PGASYNC_PIPELINE_IDLE, /* "Idle" between commands in pipeline mode */
+} PGAsyncStatusType;
+
+/* Target server type (decoded value of target_session_attrs) */
+typedef enum
+{
+ SERVER_TYPE_ANY = 0, /* Any server (default) */
+ SERVER_TYPE_READ_WRITE, /* Read-write server */
+ SERVER_TYPE_READ_ONLY, /* Read-only server */
+ SERVER_TYPE_PRIMARY, /* Primary server */
+ SERVER_TYPE_STANDBY, /* Standby server */
+ SERVER_TYPE_PREFER_STANDBY, /* Prefer standby server */
+ SERVER_TYPE_PREFER_STANDBY_PASS2 /* second pass - behaves same as ANY */
+} PGTargetServerType;
+
+/* Target server type (decoded value of load_balance_hosts) */
+typedef enum
+{
+ LOAD_BALANCE_DISABLE = 0, /* Use the existing host order (default) */
+ LOAD_BALANCE_RANDOM, /* Randomly shuffle the hosts */
+} PGLoadBalanceType;
+
+/* Boolean value plus a not-known state, for GUCs we might have to fetch */
+typedef enum
+{
+ PG_BOOL_UNKNOWN = 0, /* Currently unknown */
+ PG_BOOL_YES, /* Yes (true) */
+ PG_BOOL_NO /* No (false) */
+} PGTernaryBool;
+
+/* Typedef for the EnvironmentOptions[] array */
+typedef struct PQEnvironmentOption
+{
+ const char *envName, /* name of an environment variable */
+ *pgName; /* name of corresponding SET variable */
+} PQEnvironmentOption;
+
+/* Typedef for parameter-status list entries */
+typedef struct pgParameterStatus
+{
+ struct pgParameterStatus *next; /* list link */
+ char *name; /* parameter name */
+ char *value; /* parameter value */
+ /* Note: name and value are stored in same malloc block as struct is */
+} pgParameterStatus;
+
+/* large-object-access data ... allocated only if large-object code is used. */
+typedef struct pgLobjfuncs
+{
+ Oid fn_lo_open; /* OID of backend function lo_open */
+ Oid fn_lo_close; /* OID of backend function lo_close */
+ Oid fn_lo_creat; /* OID of backend function lo_creat */
+ Oid fn_lo_create; /* OID of backend function lo_create */
+ Oid fn_lo_unlink; /* OID of backend function lo_unlink */
+ Oid fn_lo_lseek; /* OID of backend function lo_lseek */
+ Oid fn_lo_lseek64; /* OID of backend function lo_lseek64 */
+ Oid fn_lo_tell; /* OID of backend function lo_tell */
+ Oid fn_lo_tell64; /* OID of backend function lo_tell64 */
+ Oid fn_lo_truncate; /* OID of backend function lo_truncate */
+ Oid fn_lo_truncate64; /* OID of function lo_truncate64 */
+ Oid fn_lo_read; /* OID of backend function LOread */
+ Oid fn_lo_write; /* OID of backend function LOwrite */
+} PGlobjfuncs;
+
+/* PGdataValue represents a data field value being passed to a row processor.
+ * It could be either text or binary data; text data is not zero-terminated.
+ * A SQL NULL is represented by len < 0; then value is still valid but there
+ * are no data bytes there.
+ */
+typedef struct pgDataValue
+{
+ int len; /* data length in bytes, or <0 if NULL */
+ const char *value; /* data value, without zero-termination */
+} PGdataValue;
+
+/* Host address type enum for struct pg_conn_host */
+typedef enum pg_conn_host_type
+{
+ CHT_HOST_NAME,
+ CHT_HOST_ADDRESS,
+ CHT_UNIX_SOCKET
+} pg_conn_host_type;
+
+/*
+ * PGQueryClass tracks which query protocol is in use for each command queue
+ * entry, or special operation in execution
+ */
+typedef enum
+{
+ PGQUERY_SIMPLE, /* simple Query protocol (PQexec) */
+ PGQUERY_EXTENDED, /* full Extended protocol (PQexecParams) */
+ PGQUERY_PREPARE, /* Parse only (PQprepare) */
+ PGQUERY_DESCRIBE, /* Describe Statement or Portal */
+ PGQUERY_SYNC, /* Sync (at end of a pipeline) */
+ PGQUERY_CLOSE
+} PGQueryClass;
+
+/*
+ * An entry in the pending command queue.
+ */
+typedef struct PGcmdQueueEntry
+{
+ PGQueryClass queryclass; /* Query type */
+ char *query; /* SQL command, or NULL if none/unknown/OOM */
+ struct PGcmdQueueEntry *next; /* list link */
+} PGcmdQueueEntry;
+
+/*
+ * pg_conn_host stores all information about each of possibly several hosts
+ * mentioned in the connection string. Most fields are derived by splitting
+ * the relevant connection parameter (e.g., pghost) at commas.
+ */
+typedef struct pg_conn_host
+{
+ pg_conn_host_type type; /* type of host address */
+ char *host; /* host name or socket path */
+ char *hostaddr; /* host numeric IP address */
+ char *port; /* port number (always provided) */
+ char *password; /* password for this host, read from the
+ * password file; NULL if not sought or not
+ * found in password file. */
+} pg_conn_host;
+
+/*
+ * PGconn stores all the state data associated with a single connection
+ * to a backend.
+ */
+struct pg_conn
+{
+ /* Saved values of connection options */
+ char *pghost; /* the machine on which the server is running,
+ * or a path to a UNIX-domain socket, or a
+ * comma-separated list of machines and/or
+ * paths; if NULL, use DEFAULT_PGSOCKET_DIR */
+ char *pghostaddr; /* the numeric IP address of the machine on
+ * which the server is running, or a
+ * comma-separated list of same. Takes
+ * precedence over pghost. */
+ char *pgport; /* the server's communication port number, or
+ * a comma-separated list of ports */
+ char *connect_timeout; /* connection timeout (numeric string) */
+ char *pgtcp_user_timeout; /* tcp user timeout (numeric string) */
+ char *client_encoding_initial; /* encoding to use */
+ char *pgoptions; /* options to start the backend with */
+ char *appname; /* application name */
+ char *fbappname; /* fallback application name */
+ char *dbName; /* database name */
+ char *replication; /* connect as the replication standby? */
+ char *pguser; /* Postgres username and password, if any */
+ char *pgpass;
+ char *pgpassfile; /* path to a file containing password(s) */
+ char *channel_binding; /* channel binding mode
+ * (require,prefer,disable) */
+ char *keepalives; /* use TCP keepalives? */
+ char *keepalives_idle; /* time between TCP keepalives */
+ char *keepalives_interval; /* time between TCP keepalive
+ * retransmits */
+ char *keepalives_count; /* maximum number of TCP keepalive
+ * retransmits */
+ char *sslmode; /* SSL mode (require,prefer,allow,disable) */
+ char *sslcompression; /* SSL compression (0 or 1) */
+ char *sslkey; /* client key filename */
+ char *sslcert; /* client certificate filename */
+ char *sslpassword; /* client key file password */
+ char *sslcertmode; /* client cert mode (require,allow,disable) */
+ char *sslrootcert; /* root certificate filename */
+ char *sslcrl; /* certificate revocation list filename */
+ char *sslcrldir; /* certificate revocation list directory name */
+ char *sslsni; /* use SSL SNI extension (0 or 1) */
+ char *requirepeer; /* required peer credentials for local sockets */
+ char *gssencmode; /* GSS mode (require,prefer,disable) */
+ char *krbsrvname; /* Kerberos service name */
+ char *gsslib; /* What GSS library to use ("gssapi" or
+ * "sspi") */
+ char *gssdelegation; /* Try to delegate GSS credentials? (0 or 1) */
+ char *ssl_min_protocol_version; /* minimum TLS protocol version */
+ char *ssl_max_protocol_version; /* maximum TLS protocol version */
+ char *target_session_attrs; /* desired session properties */
+ char *require_auth; /* name of the expected auth method */
+ char *load_balance_hosts; /* load balance over hosts */
+
+ /* Optional file to write trace info to */
+ FILE *Pfdebug;
+ int traceFlags;
+
+ /* Callback procedures for notice message processing */
+ PGNoticeHooks noticeHooks;
+
+ /* Event procs registered via PQregisterEventProc */
+ PGEvent *events; /* expandable array of event data */
+ int nEvents; /* number of active events */
+ int eventArraySize; /* allocated array size */
+
+ /* Status indicators */
+ ConnStatusType status;
+ PGAsyncStatusType asyncStatus;
+ PGTransactionStatusType xactStatus; /* never changes to ACTIVE */
+ char last_sqlstate[6]; /* last reported SQLSTATE */
+ bool options_valid; /* true if OK to attempt connection */
+ bool nonblocking; /* whether this connection is using nonblock
+ * sending semantics */
+ PGpipelineStatus pipelineStatus; /* status of pipeline mode */
+ bool singleRowMode; /* return current query result row-by-row? */
+ char copy_is_binary; /* 1 = copy binary, 0 = copy text */
+ int copy_already_done; /* # bytes already returned in COPY OUT */
+ PGnotify *notifyHead; /* oldest unreported Notify msg */
+ PGnotify *notifyTail; /* newest unreported Notify msg */
+
+ /* Support for multiple hosts in connection string */
+ int nconnhost; /* # of hosts named in conn string */
+ int whichhost; /* host we're currently trying/connected to */
+ pg_conn_host *connhost; /* details about each named host */
+ char *connip; /* IP address for current network connection */
+
+ /*
+ * The pending command queue as a singly-linked list. Head is the command
+ * currently in execution, tail is where new commands are added.
+ */
+ PGcmdQueueEntry *cmd_queue_head;
+ PGcmdQueueEntry *cmd_queue_tail;
+
+ /*
+ * To save malloc traffic, we don't free entries right away; instead we
+ * save them in this list for possible reuse.
+ */
+ PGcmdQueueEntry *cmd_queue_recycle;
+
+ /* Connection data */
+ pgsocket sock; /* FD for socket, PGINVALID_SOCKET if
+ * unconnected */
+ SockAddr laddr; /* Local address */
+ SockAddr raddr; /* Remote address */
+ ProtocolVersion pversion; /* FE/BE protocol version in use */
+ int sversion; /* server version, e.g. 70401 for 7.4.1 */
+ bool auth_req_received; /* true if any type of auth req received */
+ bool password_needed; /* true if server demanded a password */
+ bool gssapi_used; /* true if authenticated via gssapi */
+ bool sigpipe_so; /* have we masked SIGPIPE via SO_NOSIGPIPE? */
+ bool sigpipe_flag; /* can we mask SIGPIPE via MSG_NOSIGNAL? */
+ bool write_failed; /* have we had a write failure on sock? */
+ char *write_err_msg; /* write error message, or NULL if OOM */
+
+ bool auth_required; /* require an authentication challenge from
+ * the server? */
+ uint32 allowed_auth_methods; /* bitmask of acceptable AuthRequest
+ * codes */
+ bool client_finished_auth; /* have we finished our half of the
+ * authentication exchange? */
+
+
+ /* Transient state needed while establishing connection */
+ PGTargetServerType target_server_type; /* desired session properties */
+ PGLoadBalanceType load_balance_type; /* desired load balancing
+ * algorithm */
+ bool try_next_addr; /* time to advance to next address/host? */
+ bool try_next_host; /* time to advance to next connhost[]? */
+ int naddr; /* number of addresses returned by getaddrinfo */
+ int whichaddr; /* the address currently being tried */
+ AddrInfo *addr; /* the array of addresses for the currently
+ * tried host */
+ bool send_appname; /* okay to send application_name? */
+
+ /* Miscellaneous stuff */
+ int be_pid; /* PID of backend --- needed for cancels */
+ int be_key; /* key of backend --- needed for cancels */
+ pgParameterStatus *pstatus; /* ParameterStatus data */
+ int client_encoding; /* encoding id */
+ bool std_strings; /* standard_conforming_strings */
+ PGTernaryBool default_transaction_read_only; /* default_transaction_read_only */
+ PGTernaryBool in_hot_standby; /* in_hot_standby */
+ PGVerbosity verbosity; /* error/notice message verbosity */
+ PGContextVisibility show_context; /* whether to show CONTEXT field */
+ PGlobjfuncs *lobjfuncs; /* private state for large-object access fns */
+ pg_prng_state prng_state; /* prng state for load balancing connections */
+
+
+ /* Buffer for data received from backend and not yet processed */
+ char *inBuffer; /* currently allocated buffer */
+ int inBufSize; /* allocated size of buffer */
+ int inStart; /* offset to first unconsumed data in buffer */
+ int inCursor; /* next byte to tentatively consume */
+ int inEnd; /* offset to first position after avail data */
+
+ /* Buffer for data not yet sent to backend */
+ char *outBuffer; /* currently allocated buffer */
+ int outBufSize; /* allocated size of buffer */
+ int outCount; /* number of chars waiting in buffer */
+
+ /* State for constructing messages in outBuffer */
+ int outMsgStart; /* offset to msg start (length word); if -1,
+ * msg has no length word */
+ int outMsgEnd; /* offset to msg end (so far) */
+
+ /* Row processor interface workspace */
+ PGdataValue *rowBuf; /* array for passing values to rowProcessor */
+ int rowBufLen; /* number of entries allocated in rowBuf */
+
+ /*
+ * Status for asynchronous result construction. If result isn't NULL, it
+ * is a result being constructed or ready to return. If result is NULL
+ * and error_result is true, then we need to return a PGRES_FATAL_ERROR
+ * result, but haven't yet constructed it; text for the error has been
+ * appended to conn->errorMessage. (Delaying construction simplifies
+ * dealing with out-of-memory cases.) If next_result isn't NULL, it is a
+ * PGresult that will replace "result" after we return that one.
+ */
+ PGresult *result; /* result being constructed */
+ bool error_result; /* do we need to make an ERROR result? */
+ PGresult *next_result; /* next result (used in single-row mode) */
+
+ /* Assorted state for SASL, SSL, GSS, etc */
+ const pg_fe_sasl_mech *sasl;
+ void *sasl_state;
+ int scram_sha_256_iterations;
+
+ /* SSL structures */
+ bool ssl_in_use;
+ bool ssl_cert_requested; /* Did the server ask us for a cert? */
+ bool ssl_cert_sent; /* Did we send one in reply? */
+
+#ifdef USE_SSL
+ bool allow_ssl_try; /* Allowed to try SSL negotiation */
+ bool wait_ssl_try; /* Delay SSL negotiation until after
+ * attempting normal connection */
+#ifdef USE_OPENSSL
+ SSL *ssl; /* SSL status, if have SSL connection */
+ X509 *peer; /* X509 cert of server */
+#ifdef USE_SSL_ENGINE
+ ENGINE *engine; /* SSL engine, if any */
+#else
+ void *engine; /* dummy field to keep struct the same if
+ * OpenSSL version changes */
+#endif
+ bool crypto_loaded; /* Track if libcrypto locking callbacks have
+ * been done for this connection. This can be
+ * removed once support for OpenSSL 1.0.2 is
+ * removed as this locking is handled
+ * internally in OpenSSL >= 1.1.0. */
+#endif /* USE_OPENSSL */
+#endif /* USE_SSL */
+
+#ifdef ENABLE_GSS
+ gss_ctx_id_t gctx; /* GSS context */
+ gss_name_t gtarg_nam; /* GSS target name */
+
+ /* The following are encryption-only */
+ bool try_gss; /* GSS attempting permitted */
+ bool gssenc; /* GSS encryption is usable */
+ gss_cred_id_t gcred; /* GSS credential temp storage. */
+
+ /* GSS encryption I/O state --- see fe-secure-gssapi.c */
+ char *gss_SendBuffer; /* Encrypted data waiting to be sent */
+ int gss_SendLength; /* End of data available in gss_SendBuffer */
+ int gss_SendNext; /* Next index to send a byte from
+ * gss_SendBuffer */
+ int gss_SendConsumed; /* Number of *unencrypted* bytes consumed
+ * for current contents of gss_SendBuffer */
+ char *gss_RecvBuffer; /* Received, encrypted data */
+ int gss_RecvLength; /* End of data available in gss_RecvBuffer */
+ char *gss_ResultBuffer; /* Decryption of data in gss_RecvBuffer */
+ int gss_ResultLength; /* End of data available in
+ * gss_ResultBuffer */
+ int gss_ResultNext; /* Next index to read a byte from
+ * gss_ResultBuffer */
+ uint32 gss_MaxPktSize; /* Maximum size we can encrypt and fit the
+ * results into our output buffer */
+#endif
+
+#ifdef ENABLE_SSPI
+ CredHandle *sspicred; /* SSPI credentials handle */
+ CtxtHandle *sspictx; /* SSPI context */
+ char *sspitarget; /* SSPI target name */
+ int usesspi; /* Indicate if SSPI is in use on the
+ * connection */
+#endif
+
+ /*
+ * Buffer for current error message. This is cleared at the start of any
+ * connection attempt or query cycle; after that, all code should append
+ * messages to it, never overwrite.
+ *
+ * In some situations we might report an error more than once in a query
+ * cycle. If so, errorMessage accumulates text from all the errors, and
+ * errorReported tracks how much we've already reported, so that the
+ * individual error PGresult objects don't contain duplicative text.
+ */
+ PQExpBufferData errorMessage; /* expansible string */
+ int errorReported; /* # bytes of string already reported */
+
+ /* Buffer for receiving various parts of messages */
+ PQExpBufferData workBuffer; /* expansible string */
+};
+
+/* PGcancel stores all data necessary to cancel a connection. A copy of this
+ * data is required to safely cancel a connection running on a different
+ * thread.
+ */
+struct pg_cancel
+{
+ SockAddr raddr; /* Remote address */
+ int be_pid; /* PID of backend --- needed for cancels */
+ int be_key; /* key of backend --- needed for cancels */
+ int pgtcp_user_timeout; /* tcp user timeout */
+ int keepalives; /* use TCP keepalives? */
+ int keepalives_idle; /* time between TCP keepalives */
+ int keepalives_interval; /* time between TCP keepalive
+ * retransmits */
+ int keepalives_count; /* maximum number of TCP keepalive
+ * retransmits */
+};
+
+
+/* String descriptions of the ExecStatusTypes.
+ * direct use of this array is deprecated; call PQresStatus() instead.
+ */
+extern char *const pgresStatus[];
+
+
+#ifdef USE_SSL
+
+#ifndef WIN32
+#define USER_CERT_FILE ".postgresql/postgresql.crt"
+#define USER_KEY_FILE ".postgresql/postgresql.key"
+#define ROOT_CERT_FILE ".postgresql/root.crt"
+#define ROOT_CRL_FILE ".postgresql/root.crl"
+#else
+/* On Windows, the "home" directory is already PostgreSQL-specific */
+#define USER_CERT_FILE "postgresql.crt"
+#define USER_KEY_FILE "postgresql.key"
+#define ROOT_CERT_FILE "root.crt"
+#define ROOT_CRL_FILE "root.crl"
+#endif
+
+#endif /* USE_SSL */
+
+/* ----------------
+ * Internal functions of libpq
+ * Functions declared here need to be visible across files of libpq,
+ * but are not intended to be called by applications. We use the
+ * convention "pqXXX" for internal functions, vs. the "PQxxx" names
+ * used for application-visible routines.
+ * ----------------
+ */
+
+/* === in fe-connect.c === */
+
+extern void pqDropConnection(PGconn *conn, bool flushInput);
+extern int pqPacketSend(PGconn *conn, char pack_type,
+ const void *buf, size_t buf_len);
+extern bool pqGetHomeDirectory(char *buf, int bufsize);
+
+#ifdef ENABLE_THREAD_SAFETY
+extern pgthreadlock_t pg_g_threadlock;
+
+#define pglock_thread() pg_g_threadlock(true)
+#define pgunlock_thread() pg_g_threadlock(false)
+#else
+#define pglock_thread() ((void) 0)
+#define pgunlock_thread() ((void) 0)
+#endif
+
+/* === in fe-exec.c === */
+
+extern void pqSetResultError(PGresult *res, PQExpBuffer errorMessage, int offset);
+extern void *pqResultAlloc(PGresult *res, size_t nBytes, bool isBinary);
+extern char *pqResultStrdup(PGresult *res, const char *str);
+extern void pqClearAsyncResult(PGconn *conn);
+extern void pqSaveErrorResult(PGconn *conn);
+extern PGresult *pqPrepareAsyncResult(PGconn *conn);
+extern void pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt,...) pg_attribute_printf(2, 3);
+extern void pqSaveMessageField(PGresult *res, char code,
+ const char *value);
+extern void pqSaveParameterStatus(PGconn *conn, const char *name,
+ const char *value);
+extern int pqRowProcessor(PGconn *conn, const char **errmsgp);
+extern void pqCommandQueueAdvance(PGconn *conn);
+extern int PQsendQueryContinue(PGconn *conn, const char *query);
+
+/* === in fe-protocol3.c === */
+
+extern char *pqBuildStartupPacket3(PGconn *conn, int *packetlen,
+ const PQEnvironmentOption *options);
+extern void pqParseInput3(PGconn *conn);
+extern int pqGetErrorNotice3(PGconn *conn, bool isError);
+extern void pqBuildErrorMessage3(PQExpBuffer msg, const PGresult *res,
+ PGVerbosity verbosity, PGContextVisibility show_context);
+extern int pqGetNegotiateProtocolVersion3(PGconn *conn);
+extern int pqGetCopyData3(PGconn *conn, char **buffer, int async);
+extern int pqGetline3(PGconn *conn, char *s, int maxlen);
+extern int pqGetlineAsync3(PGconn *conn, char *buffer, int bufsize);
+extern int pqEndcopy3(PGconn *conn);
+extern PGresult *pqFunctionCall3(PGconn *conn, Oid fnid,
+ int *result_buf, int *actual_result_len,
+ int result_is_int,
+ const PQArgBlock *args, int nargs);
+
+/* === in fe-misc.c === */
+
+ /*
+ * "Get" and "Put" routines return 0 if successful, EOF if not. Note that for
+ * Get, EOF merely means the buffer is exhausted, not that there is
+ * necessarily any error.
+ */
+extern int pqCheckOutBufferSpace(size_t bytes_needed, PGconn *conn);
+extern int pqCheckInBufferSpace(size_t bytes_needed, PGconn *conn);
+extern int pqGetc(char *result, PGconn *conn);
+extern int pqPutc(char c, PGconn *conn);
+extern int pqGets(PQExpBuffer buf, PGconn *conn);
+extern int pqGets_append(PQExpBuffer buf, PGconn *conn);
+extern int pqPuts(const char *s, PGconn *conn);
+extern int pqGetnchar(char *s, size_t len, PGconn *conn);
+extern int pqSkipnchar(size_t len, PGconn *conn);
+extern int pqPutnchar(const char *s, size_t len, PGconn *conn);
+extern int pqGetInt(int *result, size_t bytes, PGconn *conn);
+extern int pqPutInt(int value, size_t bytes, PGconn *conn);
+extern int pqPutMsgStart(char msg_type, PGconn *conn);
+extern int pqPutMsgEnd(PGconn *conn);
+extern int pqReadData(PGconn *conn);
+extern int pqFlush(PGconn *conn);
+extern int pqWait(int forRead, int forWrite, PGconn *conn);
+extern int pqWaitTimed(int forRead, int forWrite, PGconn *conn,
+ time_t finish_time);
+extern int pqReadReady(PGconn *conn);
+extern int pqWriteReady(PGconn *conn);
+
+/* === in fe-secure.c === */
+
+extern int pqsecure_initialize(PGconn *, bool, bool);
+extern PostgresPollingStatusType pqsecure_open_client(PGconn *);
+extern void pqsecure_close(PGconn *);
+extern ssize_t pqsecure_read(PGconn *, void *ptr, size_t len);
+extern ssize_t pqsecure_write(PGconn *, const void *ptr, size_t len);
+extern ssize_t pqsecure_raw_read(PGconn *, void *ptr, size_t len);
+extern ssize_t pqsecure_raw_write(PGconn *, const void *ptr, size_t len);
+
+#if defined(ENABLE_THREAD_SAFETY) && !defined(WIN32)
+extern int pq_block_sigpipe(sigset_t *osigset, bool *sigpipe_pending);
+extern void pq_reset_sigpipe(sigset_t *osigset, bool sigpipe_pending,
+ bool got_epipe);
+#endif
+
+/* === SSL === */
+
+/*
+ * The SSL implementation provides these functions.
+ */
+
+/*
+ * Implementation of PQinitSSL().
+ */
+extern void pgtls_init_library(bool do_ssl, int do_crypto);
+
+/*
+ * Initialize SSL library.
+ *
+ * The conn parameter is only used to be able to pass back an error
+ * message - no connection-local setup is made here. do_ssl controls
+ * if SSL is initialized, and do_crypto does the same for the crypto
+ * part.
+ *
+ * Returns 0 if OK, -1 on failure (adding a message to conn->errorMessage).
+ */
+extern int pgtls_init(PGconn *conn, bool do_ssl, bool do_crypto);
+
+/*
+ * Begin or continue negotiating a secure session.
+ */
+extern PostgresPollingStatusType pgtls_open_client(PGconn *conn);
+
+/*
+ * Close SSL connection.
+ */
+extern void pgtls_close(PGconn *conn);
+
+/*
+ * Read data from a secure connection.
+ *
+ * On failure, this function is responsible for appending a suitable message
+ * to conn->errorMessage. The caller must still inspect errno, but only
+ * to determine whether to continue/retry after error.
+ */
+extern ssize_t pgtls_read(PGconn *conn, void *ptr, size_t len);
+
+/*
+ * Is there unread data waiting in the SSL read buffer?
+ */
+extern bool pgtls_read_pending(PGconn *conn);
+
+/*
+ * Write data to a secure connection.
+ *
+ * On failure, this function is responsible for appending a suitable message
+ * to conn->errorMessage. The caller must still inspect errno, but only
+ * to determine whether to continue/retry after error.
+ */
+extern ssize_t pgtls_write(PGconn *conn, const void *ptr, size_t len);
+
+/*
+ * Get the hash of the server certificate, for SCRAM channel binding type
+ * tls-server-end-point.
+ *
+ * NULL is sent back to the caller in the event of an error, with an
+ * error message for the caller to consume.
+ *
+ * This is not supported with old versions of OpenSSL that don't have
+ * the X509_get_signature_nid() function.
+ */
+#if defined(USE_OPENSSL) && (defined(HAVE_X509_GET_SIGNATURE_NID) || defined(HAVE_X509_GET_SIGNATURE_INFO))
+#define HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH
+extern char *pgtls_get_peer_certificate_hash(PGconn *conn, size_t *len);
+#endif
+
+/*
+ * Verify that the server certificate matches the host name we connected to.
+ *
+ * The certificate's Common Name and Subject Alternative Names are considered.
+ *
+ * Returns 1 if the name matches, and 0 if it does not. On error, returns
+ * -1, and sets the libpq error message.
+ *
+ */
+extern int pgtls_verify_peer_name_matches_certificate_guts(PGconn *conn,
+ int *names_examined,
+ char **first_name);
+
+/* === GSSAPI === */
+
+#ifdef ENABLE_GSS
+
+/*
+ * Establish a GSSAPI-encrypted connection.
+ */
+extern PostgresPollingStatusType pqsecure_open_gss(PGconn *conn);
+
+/*
+ * Read and write functions for GSSAPI-encrypted connections, with internal
+ * buffering to handle nonblocking sockets.
+ */
+extern ssize_t pg_GSS_write(PGconn *conn, const void *ptr, size_t len);
+extern ssize_t pg_GSS_read(PGconn *conn, void *ptr, size_t len);
+#endif
+
+/* === in fe-trace.c === */
+
+extern void pqTraceOutputMessage(PGconn *conn, const char *message,
+ bool toServer);
+extern void pqTraceOutputNoTypeByteMessage(PGconn *conn, const char *message);
+
+/* === miscellaneous macros === */
+
+/*
+ * Reset the conn's error-reporting state.
+ */
+#define pqClearConnErrorState(conn) \
+ (resetPQExpBuffer(&(conn)->errorMessage), \
+ (conn)->errorReported = 0)
+
+/*
+ * Check whether we have a PGresult pending to be returned --- either a
+ * constructed one in conn->result, or a "virtual" error result that we
+ * don't intend to materialize until the end of the query cycle.
+ */
+#define pgHavePendingResult(conn) \
+ ((conn)->result != NULL || (conn)->error_result)
+
+/*
+ * this is so that we can check if a connection is non-blocking internally
+ * without the overhead of a function call
+ */
+#define pqIsnonblocking(conn) ((conn)->nonblocking)
+
+/*
+ * Connection's outbuffer threshold, for pipeline mode.
+ */
+#define OUTBUFFER_THRESHOLD 65536
+
+#ifdef ENABLE_NLS
+extern char *libpq_gettext(const char *msgid) pg_attribute_format_arg(1);
+extern char *libpq_ngettext(const char *msgid, const char *msgid_plural, unsigned long n) pg_attribute_format_arg(1) pg_attribute_format_arg(2);
+#else
+#define libpq_gettext(x) (x)
+#define libpq_ngettext(s, p, n) ((n) == 1 ? (s) : (p))
+#endif
+/*
+ * libpq code should use the above, not _(), since that would use the
+ * surrounding programs's message catalog.
+ */
+#undef _
+
+extern void libpq_append_error(PQExpBuffer errorMessage, const char *fmt,...) pg_attribute_printf(2, 3);
+extern void libpq_append_conn_error(PGconn *conn, const char *fmt,...) pg_attribute_printf(2, 3);
+
+/*
+ * These macros are needed to let error-handling code be portable between
+ * Unix and Windows. (ugh)
+ */
+#ifdef WIN32
+#define SOCK_ERRNO (WSAGetLastError())
+#define SOCK_STRERROR winsock_strerror
+#define SOCK_ERRNO_SET(e) WSASetLastError(e)
+#else
+#define SOCK_ERRNO errno
+#define SOCK_STRERROR strerror_r
+#define SOCK_ERRNO_SET(e) (errno = (e))
+#endif
+
+#endif /* LIBPQ_INT_H */
diff --git a/contrib/libs/libpq/src/interfaces/libpq/pqexpbuffer.c b/contrib/libs/libpq/src/interfaces/libpq/pqexpbuffer.c
new file mode 100644
index 0000000000..de7e0328db
--- /dev/null
+++ b/contrib/libs/libpq/src/interfaces/libpq/pqexpbuffer.c
@@ -0,0 +1,412 @@
+/*-------------------------------------------------------------------------
+ *
+ * pqexpbuffer.c
+ *
+ * PQExpBuffer provides an indefinitely-extensible string data type.
+ * It can be used to buffer either ordinary C strings (null-terminated text)
+ * or arbitrary binary data. All storage is allocated with malloc().
+ *
+ * This module is essentially the same as the backend's StringInfo data type,
+ * but it is intended for use in frontend libpq and client applications.
+ * Thus, it does not rely on palloc() nor elog(), nor psprintf.c which
+ * will exit() on error.
+ *
+ * It does rely on vsnprintf(); if configure finds that libc doesn't provide
+ * a usable vsnprintf(), then a copy of our own implementation of it will
+ * be linked into libpq.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/interfaces/libpq/pqexpbuffer.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres_fe.h"
+
+#include <limits.h>
+
+#include "pqexpbuffer.h"
+
+#ifdef WIN32
+#include "win32.h"
+#endif
+
+
+/* All "broken" PQExpBuffers point to this string. */
+static const char oom_buffer[1] = "";
+
+/* Need a char * for unconstify() compatibility */
+static const char *oom_buffer_ptr = oom_buffer;
+
+
+/*
+ * markPQExpBufferBroken
+ *
+ * Put a PQExpBuffer in "broken" state if it isn't already.
+ */
+static void
+markPQExpBufferBroken(PQExpBuffer str)
+{
+ if (str->data != oom_buffer)
+ free(str->data);
+
+ /*
+ * Casting away const here is a bit ugly, but it seems preferable to not
+ * marking oom_buffer const. We want to do that to encourage the compiler
+ * to put oom_buffer in read-only storage, so that anyone who tries to
+ * scribble on a broken PQExpBuffer will get a failure.
+ */
+ str->data = unconstify(char *, oom_buffer_ptr);
+ str->len = 0;
+ str->maxlen = 0;
+}
+
+/*
+ * createPQExpBuffer
+ *
+ * Create an empty 'PQExpBufferData' & return a pointer to it.
+ */
+PQExpBuffer
+createPQExpBuffer(void)
+{
+ PQExpBuffer res;
+
+ res = (PQExpBuffer) malloc(sizeof(PQExpBufferData));
+ if (res != NULL)
+ initPQExpBuffer(res);
+
+ return res;
+}
+
+/*
+ * initPQExpBuffer
+ *
+ * Initialize a PQExpBufferData struct (with previously undefined contents)
+ * to describe an empty string.
+ */
+void
+initPQExpBuffer(PQExpBuffer str)
+{
+ str->data = (char *) malloc(INITIAL_EXPBUFFER_SIZE);
+ if (str->data == NULL)
+ {
+ str->data = unconstify(char *, oom_buffer_ptr); /* see comment above */
+ str->maxlen = 0;
+ str->len = 0;
+ }
+ else
+ {
+ str->maxlen = INITIAL_EXPBUFFER_SIZE;
+ str->len = 0;
+ str->data[0] = '\0';
+ }
+}
+
+/*
+ * destroyPQExpBuffer(str);
+ *
+ * free()s both the data buffer and the PQExpBufferData.
+ * This is the inverse of createPQExpBuffer().
+ */
+void
+destroyPQExpBuffer(PQExpBuffer str)
+{
+ if (str)
+ {
+ termPQExpBuffer(str);
+ free(str);
+ }
+}
+
+/*
+ * termPQExpBuffer(str)
+ * free()s the data buffer but not the PQExpBufferData itself.
+ * This is the inverse of initPQExpBuffer().
+ */
+void
+termPQExpBuffer(PQExpBuffer str)
+{
+ if (str->data != oom_buffer)
+ free(str->data);
+ /* just for luck, make the buffer validly empty. */
+ str->data = unconstify(char *, oom_buffer_ptr); /* see comment above */
+ str->maxlen = 0;
+ str->len = 0;
+}
+
+/*
+ * resetPQExpBuffer
+ * Reset a PQExpBuffer to empty
+ *
+ * Note: if possible, a "broken" PQExpBuffer is returned to normal.
+ */
+void
+resetPQExpBuffer(PQExpBuffer str)
+{
+ if (str)
+ {
+ if (str->data != oom_buffer)
+ {
+ str->len = 0;
+ str->data[0] = '\0';
+ }
+ else
+ {
+ /* try to reinitialize to valid state */
+ initPQExpBuffer(str);
+ }
+ }
+}
+
+/*
+ * enlargePQExpBuffer
+ * Make sure there is enough space for 'needed' more bytes in the buffer
+ * ('needed' does not include the terminating null).
+ *
+ * Returns 1 if OK, 0 if failed to enlarge buffer. (In the latter case
+ * the buffer is left in "broken" state.)
+ */
+int
+enlargePQExpBuffer(PQExpBuffer str, size_t needed)
+{
+ size_t newlen;
+ char *newdata;
+
+ if (PQExpBufferBroken(str))
+ return 0; /* already failed */
+
+ /*
+ * Guard against ridiculous "needed" values, which can occur if we're fed
+ * bogus data. Without this, we can get an overflow or infinite loop in
+ * the following.
+ */
+ if (needed >= ((size_t) INT_MAX - str->len))
+ {
+ markPQExpBufferBroken(str);
+ return 0;
+ }
+
+ needed += str->len + 1; /* total space required now */
+
+ /* Because of the above test, we now have needed <= INT_MAX */
+
+ if (needed <= str->maxlen)
+ return 1; /* got enough space already */
+
+ /*
+ * We don't want to allocate just a little more space with each append;
+ * for efficiency, double the buffer size each time it overflows.
+ * Actually, we might need to more than double it if 'needed' is big...
+ */
+ newlen = (str->maxlen > 0) ? (2 * str->maxlen) : 64;
+ while (needed > newlen)
+ newlen = 2 * newlen;
+
+ /*
+ * Clamp to INT_MAX in case we went past it. Note we are assuming here
+ * that INT_MAX <= UINT_MAX/2, else the above loop could overflow. We
+ * will still have newlen >= needed.
+ */
+ if (newlen > (size_t) INT_MAX)
+ newlen = (size_t) INT_MAX;
+
+ newdata = (char *) realloc(str->data, newlen);
+ if (newdata != NULL)
+ {
+ str->data = newdata;
+ str->maxlen = newlen;
+ return 1;
+ }
+
+ markPQExpBufferBroken(str);
+ return 0;
+}
+
+/*
+ * printfPQExpBuffer
+ * Format text data under the control of fmt (an sprintf-like format string)
+ * and insert it into str. More space is allocated to str if necessary.
+ * This is a convenience routine that does the same thing as
+ * resetPQExpBuffer() followed by appendPQExpBuffer().
+ */
+void
+printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
+{
+ int save_errno = errno;
+ va_list args;
+ bool done;
+
+ resetPQExpBuffer(str);
+
+ if (PQExpBufferBroken(str))
+ return; /* already failed */
+
+ /* Loop in case we have to retry after enlarging the buffer. */
+ do
+ {
+ errno = save_errno;
+ va_start(args, fmt);
+ done = appendPQExpBufferVA(str, fmt, args);
+ va_end(args);
+ } while (!done);
+}
+
+/*
+ * appendPQExpBuffer
+ *
+ * Format text data under the control of fmt (an sprintf-like format string)
+ * and append it to whatever is already in str. More space is allocated
+ * to str if necessary. This is sort of like a combination of sprintf and
+ * strcat.
+ */
+void
+appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
+{
+ int save_errno = errno;
+ va_list args;
+ bool done;
+
+ if (PQExpBufferBroken(str))
+ return; /* already failed */
+
+ /* Loop in case we have to retry after enlarging the buffer. */
+ do
+ {
+ errno = save_errno;
+ va_start(args, fmt);
+ done = appendPQExpBufferVA(str, fmt, args);
+ va_end(args);
+ } while (!done);
+}
+
+/*
+ * appendPQExpBufferVA
+ * Shared guts of printfPQExpBuffer/appendPQExpBuffer.
+ * Attempt to format data and append it to str. Returns true if done
+ * (either successful or hard failure), false if need to retry.
+ *
+ * Caution: callers must be sure to preserve their entry-time errno
+ * when looping, in case the fmt contains "%m".
+ */
+bool
+appendPQExpBufferVA(PQExpBuffer str, const char *fmt, va_list args)
+{
+ size_t avail;
+ size_t needed;
+ int nprinted;
+
+ /*
+ * Try to format the given string into the available space; but if there's
+ * hardly any space, don't bother trying, just enlarge the buffer first.
+ */
+ if (str->maxlen > str->len + 16)
+ {
+ avail = str->maxlen - str->len;
+
+ nprinted = vsnprintf(str->data + str->len, avail, fmt, args);
+
+ /*
+ * If vsnprintf reports an error, fail (we assume this means there's
+ * something wrong with the format string).
+ */
+ if (unlikely(nprinted < 0))
+ {
+ markPQExpBufferBroken(str);
+ return true;
+ }
+
+ if ((size_t) nprinted < avail)
+ {
+ /* Success. Note nprinted does not include trailing null. */
+ str->len += nprinted;
+ return true;
+ }
+
+ /*
+ * We assume a C99-compliant vsnprintf, so believe its estimate of the
+ * required space, and add one for the trailing null. (If it's wrong,
+ * the logic will still work, but we may loop multiple times.)
+ *
+ * Choke if the required space would exceed INT_MAX, since str->maxlen
+ * can't represent more than that.
+ */
+ if (unlikely(nprinted > INT_MAX - 1))
+ {
+ markPQExpBufferBroken(str);
+ return true;
+ }
+ needed = nprinted + 1;
+ }
+ else
+ {
+ /*
+ * We have to guess at how much to enlarge, since we're skipping the
+ * formatting work. Fortunately, because of enlargePQExpBuffer's
+ * preference for power-of-2 sizes, this number isn't very sensitive;
+ * the net effect is that we'll double the buffer size before trying
+ * to run vsnprintf, which seems sensible.
+ */
+ needed = 32;
+ }
+
+ /* Increase the buffer size and try again. */
+ if (!enlargePQExpBuffer(str, needed))
+ return true; /* oops, out of memory */
+
+ return false;
+}
+
+/*
+ * appendPQExpBufferStr
+ * Append the given string to a PQExpBuffer, allocating more space
+ * if necessary.
+ */
+void
+appendPQExpBufferStr(PQExpBuffer str, const char *data)
+{
+ appendBinaryPQExpBuffer(str, data, strlen(data));
+}
+
+/*
+ * appendPQExpBufferChar
+ * Append a single byte to str.
+ * Like appendPQExpBuffer(str, "%c", ch) but much faster.
+ */
+void
+appendPQExpBufferChar(PQExpBuffer str, char ch)
+{
+ /* Make more room if needed */
+ if (!enlargePQExpBuffer(str, 1))
+ return;
+
+ /* OK, append the character */
+ str->data[str->len] = ch;
+ str->len++;
+ str->data[str->len] = '\0';
+}
+
+/*
+ * appendBinaryPQExpBuffer
+ *
+ * Append arbitrary binary data to a PQExpBuffer, allocating more space
+ * if necessary.
+ */
+void
+appendBinaryPQExpBuffer(PQExpBuffer str, const char *data, size_t datalen)
+{
+ /* Make more room if needed */
+ if (!enlargePQExpBuffer(str, datalen))
+ return;
+
+ /* OK, append the data */
+ memcpy(str->data + str->len, data, datalen);
+ str->len += datalen;
+
+ /*
+ * Keep a trailing null in place, even though it's probably useless for
+ * binary data...
+ */
+ str->data[str->len] = '\0';
+}
diff --git a/contrib/libs/libpq/src/interfaces/libpq/pqexpbuffer.h b/contrib/libs/libpq/src/interfaces/libpq/pqexpbuffer.h
new file mode 100644
index 0000000000..020e94e357
--- /dev/null
+++ b/contrib/libs/libpq/src/interfaces/libpq/pqexpbuffer.h
@@ -0,0 +1,192 @@
+/*-------------------------------------------------------------------------
+ *
+ * pqexpbuffer.h
+ * Declarations/definitions for "PQExpBuffer" functions.
+ *
+ * PQExpBuffer provides an indefinitely-extensible string data type.
+ * It can be used to buffer either ordinary C strings (null-terminated text)
+ * or arbitrary binary data. All storage is allocated with malloc().
+ *
+ * This module is essentially the same as the backend's StringInfo data type,
+ * but it is intended for use in frontend libpq and client applications.
+ * Thus, it does not rely on palloc() nor elog().
+ *
+ * It does rely on vsnprintf(); if configure finds that libc doesn't provide
+ * a usable vsnprintf(), then a copy of our own implementation of it will
+ * be linked into libpq.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/interfaces/libpq/pqexpbuffer.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PQEXPBUFFER_H
+#define PQEXPBUFFER_H
+
+/*-------------------------
+ * PQExpBufferData holds information about an extensible string.
+ * data is the current buffer for the string (allocated with malloc).
+ * len is the current string length. There is guaranteed to be
+ * a terminating '\0' at data[len], although this is not very
+ * useful when the string holds binary data rather than text.
+ * maxlen is the allocated size in bytes of 'data', i.e. the maximum
+ * string size (including the terminating '\0' char) that we can
+ * currently store in 'data' without having to reallocate
+ * more space. We must always have maxlen > len.
+ *
+ * An exception occurs if we failed to allocate enough memory for the string
+ * buffer. In that case data points to a statically allocated empty string,
+ * and len = maxlen = 0.
+ *-------------------------
+ */
+typedef struct PQExpBufferData
+{
+ char *data;
+ size_t len;
+ size_t maxlen;
+} PQExpBufferData;
+
+typedef PQExpBufferData *PQExpBuffer;
+
+/*------------------------
+ * Test for a broken (out of memory) PQExpBuffer.
+ * When a buffer is "broken", all operations except resetting or deleting it
+ * are no-ops.
+ *------------------------
+ */
+#define PQExpBufferBroken(str) \
+ ((str) == NULL || (str)->maxlen == 0)
+
+/*------------------------
+ * Same, but for use when using a static or local PQExpBufferData struct.
+ * For that, a null-pointer test is useless and may draw compiler warnings.
+ *------------------------
+ */
+#define PQExpBufferDataBroken(buf) \
+ ((buf).maxlen == 0)
+
+/*------------------------
+ * Initial size of the data buffer in a PQExpBuffer.
+ * NB: this must be large enough to hold error messages that might
+ * be returned by PQrequestCancel().
+ *------------------------
+ */
+#define INITIAL_EXPBUFFER_SIZE 256
+
+/*------------------------
+ * There are two ways to create a PQExpBuffer object initially:
+ *
+ * PQExpBuffer stringptr = createPQExpBuffer();
+ * Both the PQExpBufferData and the data buffer are malloc'd.
+ *
+ * PQExpBufferData string;
+ * initPQExpBuffer(&string);
+ * The data buffer is malloc'd but the PQExpBufferData is presupplied.
+ * This is appropriate if the PQExpBufferData is a field of another
+ * struct.
+ *-------------------------
+ */
+
+/*------------------------
+ * createPQExpBuffer
+ * Create an empty 'PQExpBufferData' & return a pointer to it.
+ */
+extern PQExpBuffer createPQExpBuffer(void);
+
+/*------------------------
+ * initPQExpBuffer
+ * Initialize a PQExpBufferData struct (with previously undefined contents)
+ * to describe an empty string.
+ */
+extern void initPQExpBuffer(PQExpBuffer str);
+
+/*------------------------
+ * To destroy a PQExpBuffer, use either:
+ *
+ * destroyPQExpBuffer(str);
+ * free()s both the data buffer and the PQExpBufferData.
+ * This is the inverse of createPQExpBuffer().
+ *
+ * termPQExpBuffer(str)
+ * free()s the data buffer but not the PQExpBufferData itself.
+ * This is the inverse of initPQExpBuffer().
+ *
+ * NOTE: some routines build up a string using PQExpBuffer, and then
+ * release the PQExpBufferData but return the data string itself to their
+ * caller. At that point the data string looks like a plain malloc'd
+ * string.
+ */
+extern void destroyPQExpBuffer(PQExpBuffer str);
+extern void termPQExpBuffer(PQExpBuffer str);
+
+/*------------------------
+ * resetPQExpBuffer
+ * Reset a PQExpBuffer to empty
+ *
+ * Note: if possible, a "broken" PQExpBuffer is returned to normal.
+ */
+extern void resetPQExpBuffer(PQExpBuffer str);
+
+/*------------------------
+ * enlargePQExpBuffer
+ * Make sure there is enough space for 'needed' more bytes in the buffer
+ * ('needed' does not include the terminating null).
+ *
+ * Returns 1 if OK, 0 if failed to enlarge buffer. (In the latter case
+ * the buffer is left in "broken" state.)
+ */
+extern int enlargePQExpBuffer(PQExpBuffer str, size_t needed);
+
+/*------------------------
+ * printfPQExpBuffer
+ * Format text data under the control of fmt (an sprintf-like format string)
+ * and insert it into str. More space is allocated to str if necessary.
+ * This is a convenience routine that does the same thing as
+ * resetPQExpBuffer() followed by appendPQExpBuffer().
+ */
+extern void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...) pg_attribute_printf(2, 3);
+
+/*------------------------
+ * appendPQExpBuffer
+ * Format text data under the control of fmt (an sprintf-like format string)
+ * and append it to whatever is already in str. More space is allocated
+ * to str if necessary. This is sort of like a combination of sprintf and
+ * strcat.
+ */
+extern void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...) pg_attribute_printf(2, 3);
+
+/*------------------------
+ * appendPQExpBufferVA
+ * Attempt to format data and append it to str. Returns true if done
+ * (either successful or hard failure), false if need to retry.
+ *
+ * Caution: callers must be sure to preserve their entry-time errno
+ * when looping, in case the fmt contains "%m".
+ */
+extern bool appendPQExpBufferVA(PQExpBuffer str, const char *fmt, va_list args) pg_attribute_printf(2, 0);
+
+/*------------------------
+ * appendPQExpBufferStr
+ * Append the given string to a PQExpBuffer, allocating more space
+ * if necessary.
+ */
+extern void appendPQExpBufferStr(PQExpBuffer str, const char *data);
+
+/*------------------------
+ * appendPQExpBufferChar
+ * Append a single byte to str.
+ * Like appendPQExpBuffer(str, "%c", ch) but much faster.
+ */
+extern void appendPQExpBufferChar(PQExpBuffer str, char ch);
+
+/*------------------------
+ * appendBinaryPQExpBuffer
+ * Append arbitrary binary data to a PQExpBuffer, allocating more space
+ * if necessary.
+ */
+extern void appendBinaryPQExpBuffer(PQExpBuffer str,
+ const char *data, size_t datalen);
+
+#endif /* PQEXPBUFFER_H */
diff --git a/contrib/libs/libpq/src/interfaces/libpq/pthread-win32.c b/contrib/libs/libpq/src/interfaces/libpq/pthread-win32.c
new file mode 100644
index 0000000000..8e65637387
--- /dev/null
+++ b/contrib/libs/libpq/src/interfaces/libpq/pthread-win32.c
@@ -0,0 +1,60 @@
+/*-------------------------------------------------------------------------
+*
+* pthread-win32.c
+* partial pthread implementation for win32
+*
+* Copyright (c) 2004-2023, PostgreSQL Global Development Group
+* IDENTIFICATION
+* src/interfaces/libpq/pthread-win32.c
+*
+*-------------------------------------------------------------------------
+*/
+
+#include "postgres_fe.h"
+
+#include "pthread-win32.h"
+
+DWORD
+pthread_self(void)
+{
+ return GetCurrentThreadId();
+}
+
+void
+pthread_setspecific(pthread_key_t key, void *val)
+{
+}
+
+void *
+pthread_getspecific(pthread_key_t key)
+{
+ return NULL;
+}
+
+int
+pthread_mutex_init(pthread_mutex_t *mp, void *attr)
+{
+ *mp = (CRITICAL_SECTION *) malloc(sizeof(CRITICAL_SECTION));
+ if (!*mp)
+ return 1;
+ InitializeCriticalSection(*mp);
+ return 0;
+}
+
+int
+pthread_mutex_lock(pthread_mutex_t *mp)
+{
+ if (!*mp)
+ return 1;
+ EnterCriticalSection(*mp);
+ return 0;
+}
+
+int
+pthread_mutex_unlock(pthread_mutex_t *mp)
+{
+ if (!*mp)
+ return 1;
+ LeaveCriticalSection(*mp);
+ return 0;
+}
diff --git a/contrib/libs/libpq/src/interfaces/libpq/win32.c b/contrib/libs/libpq/src/interfaces/libpq/win32.c
new file mode 100644
index 0000000000..e4d29eefa6
--- /dev/null
+++ b/contrib/libs/libpq/src/interfaces/libpq/win32.c
@@ -0,0 +1,320 @@
+/*
+ * src/interfaces/libpq/win32.c
+ *
+ *
+ * FILE
+ * win32.c
+ *
+ * DESCRIPTION
+ * Win32 support functions.
+ *
+ * Contains table and functions for looking up win32 socket error
+ * descriptions. But will/may contain other win32 helper functions
+ * for libpq.
+ *
+ * The error constants are taken from the Frambak Bakfram LGSOCKET
+ * library guys who in turn took them from the Winsock FAQ.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ */
+
+/* Make stuff compile faster by excluding not used stuff */
+
+#define VC_EXTRALEAN
+#ifndef __MINGW32__
+#define NOGDI
+#endif
+#define NOCRYPT
+
+#include "postgres_fe.h"
+
+#include "win32.h"
+
+/* Declared here to avoid pulling in all includes, which causes name collisions */
+#ifdef ENABLE_NLS
+extern char *libpq_gettext(const char *msgid) pg_attribute_format_arg(1);
+#else
+#define libpq_gettext(x) (x)
+#endif
+
+
+static struct WSErrorEntry
+{
+ DWORD error;
+ const char *description;
+} WSErrors[] =
+
+{
+ {
+ 0, "No error"
+ },
+ {
+ WSAEINTR, "Interrupted system call"
+ },
+ {
+ WSAEBADF, "Bad file number"
+ },
+ {
+ WSAEACCES, "Permission denied"
+ },
+ {
+ WSAEFAULT, "Bad address"
+ },
+ {
+ WSAEINVAL, "Invalid argument"
+ },
+ {
+ WSAEMFILE, "Too many open sockets"
+ },
+ {
+ WSAEWOULDBLOCK, "Operation would block"
+ },
+ {
+ WSAEINPROGRESS, "Operation now in progress"
+ },
+ {
+ WSAEALREADY, "Operation already in progress"
+ },
+ {
+ WSAENOTSOCK, "Socket operation on non-socket"
+ },
+ {
+ WSAEDESTADDRREQ, "Destination address required"
+ },
+ {
+ WSAEMSGSIZE, "Message too long"
+ },
+ {
+ WSAEPROTOTYPE, "Protocol wrong type for socket"
+ },
+ {
+ WSAENOPROTOOPT, "Bad protocol option"
+ },
+ {
+ WSAEPROTONOSUPPORT, "Protocol not supported"
+ },
+ {
+ WSAESOCKTNOSUPPORT, "Socket type not supported"
+ },
+ {
+ WSAEOPNOTSUPP, "Operation not supported on socket"
+ },
+ {
+ WSAEPFNOSUPPORT, "Protocol family not supported"
+ },
+ {
+ WSAEAFNOSUPPORT, "Address family not supported"
+ },
+ {
+ WSAEADDRINUSE, "Address already in use"
+ },
+ {
+ WSAEADDRNOTAVAIL, "Cannot assign requested address"
+ },
+ {
+ WSAENETDOWN, "Network is down"
+ },
+ {
+ WSAENETUNREACH, "Network is unreachable"
+ },
+ {
+ WSAENETRESET, "Net connection reset"
+ },
+ {
+ WSAECONNABORTED, "Software caused connection abort"
+ },
+ {
+ WSAECONNRESET, "Connection reset by peer"
+ },
+ {
+ WSAENOBUFS, "No buffer space available"
+ },
+ {
+ WSAEISCONN, "Socket is already connected"
+ },
+ {
+ WSAENOTCONN, "Socket is not connected"
+ },
+ {
+ WSAESHUTDOWN, "Cannot send after socket shutdown"
+ },
+ {
+ WSAETOOMANYREFS, "Too many references, cannot splice"
+ },
+ {
+ WSAETIMEDOUT, "Connection timed out"
+ },
+ {
+ WSAECONNREFUSED, "Connection refused"
+ },
+ {
+ WSAELOOP, "Too many levels of symbolic links"
+ },
+ {
+ WSAENAMETOOLONG, "File name too long"
+ },
+ {
+ WSAEHOSTDOWN, "Host is down"
+ },
+ {
+ WSAEHOSTUNREACH, "No route to host"
+ },
+ {
+ WSAENOTEMPTY, "Directory not empty"
+ },
+ {
+ WSAEPROCLIM, "Too many processes"
+ },
+ {
+ WSAEUSERS, "Too many users"
+ },
+ {
+ WSAEDQUOT, "Disc quota exceeded"
+ },
+ {
+ WSAESTALE, "Stale NFS file handle"
+ },
+ {
+ WSAEREMOTE, "Too many levels of remote in path"
+ },
+ {
+ WSASYSNOTREADY, "Network system is unavailable"
+ },
+ {
+ WSAVERNOTSUPPORTED, "Winsock version out of range"
+ },
+ {
+ WSANOTINITIALISED, "WSAStartup not yet called"
+ },
+ {
+ WSAEDISCON, "Graceful shutdown in progress"
+ },
+ {
+ WSAHOST_NOT_FOUND, "Host not found"
+ },
+ {
+ WSATRY_AGAIN, "NA Host not found / SERVFAIL"
+ },
+ {
+ WSANO_RECOVERY, "Non recoverable FORMERR||REFUSED||NOTIMP"
+ },
+ {
+ WSANO_DATA, "No host data of that type was found"
+ },
+ {
+ 0, 0
+ } /* End of table */
+};
+
+
+/*
+ * Returns 0 if not found, linear but who cares, at this moment
+ * we're already in pain :)
+ */
+
+static int
+LookupWSErrorMessage(DWORD err, char *dest)
+{
+ struct WSErrorEntry *e;
+
+ for (e = WSErrors; e->description; e++)
+ {
+ if (e->error == err)
+ {
+ strcpy(dest, e->description);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+struct MessageDLL
+{
+ const char *dll_name;
+ void *handle;
+ int loaded; /* BOOL */
+} dlls[] =
+
+{
+ {
+ "netmsg.dll", 0, 0
+ },
+ {
+ "winsock.dll", 0, 0
+ },
+ {
+ "ws2_32.dll", 0, 0
+ },
+ {
+ "wsock32n.dll", 0, 0
+ },
+ {
+ "mswsock.dll", 0, 0
+ },
+ {
+ "ws2help.dll", 0, 0
+ },
+ {
+ "ws2thk.dll", 0, 0
+ },
+ {
+ 0, 0, 1
+ } /* Last one, no dll, always loaded */
+};
+
+#define DLLS_SIZE (sizeof(dlls)/sizeof(struct MessageDLL))
+
+/*
+ * Returns a description of the socket error by first trying
+ * to find it in the lookup table, and if that fails, tries
+ * to load any of the winsock dlls to find that message.
+ */
+
+const char *
+winsock_strerror(int err, char *strerrbuf, size_t buflen)
+{
+ unsigned long flags;
+ int offs,
+ i;
+ int success = LookupWSErrorMessage(err, strerrbuf);
+
+ for (i = 0; !success && i < DLLS_SIZE; i++)
+ {
+
+ if (!dlls[i].loaded)
+ {
+ dlls[i].loaded = 1; /* Only load once */
+ dlls[i].handle = (void *) LoadLibraryEx(dlls[i].dll_name,
+ 0,
+ LOAD_LIBRARY_AS_DATAFILE);
+ }
+
+ if (dlls[i].dll_name && !dlls[i].handle)
+ continue; /* Didn't load */
+
+ flags = FORMAT_MESSAGE_FROM_SYSTEM
+ | FORMAT_MESSAGE_IGNORE_INSERTS
+ | (dlls[i].handle ? FORMAT_MESSAGE_FROM_HMODULE : 0);
+
+ success = 0 != FormatMessage(flags,
+ dlls[i].handle, err,
+ MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
+ strerrbuf, buflen - 64,
+ 0);
+ }
+
+ if (!success)
+ sprintf(strerrbuf, libpq_gettext("unrecognized socket error: 0x%08X/%d"), err, err);
+ else
+ {
+ strerrbuf[buflen - 1] = '\0';
+ offs = strlen(strerrbuf);
+ if (offs > (int) buflen - 64)
+ offs = buflen - 64;
+ sprintf(strerrbuf + offs, " (0x%08X/%d)", err, err);
+ }
+ return strerrbuf;
+}
diff --git a/contrib/libs/libpq/src/port/README b/contrib/libs/libpq/src/port/README
new file mode 100644
index 0000000000..97f18a6233
--- /dev/null
+++ b/contrib/libs/libpq/src/port/README
@@ -0,0 +1,32 @@
+src/port/README
+
+libpgport
+=========
+
+libpgport must have special behavior. It supplies functions to both
+libraries and applications. However, there are two complexities:
+
+1) Libraries need to use object files that are compiled with exactly
+the same flags as the library. libpgport might not use the same flags,
+so it is necessary to recompile the object files for individual
+libraries. This is done by removing -lpgport from the link line:
+
+ # Need to recompile any libpgport object files
+ LIBS := $(filter-out -lpgport, $(LIBS))
+
+and adding infrastructure to recompile the object files:
+
+ OBJS= execute.o typename.o descriptor.o data.o error.o prepare.o memory.o \
+ connect.o misc.o path.o exec.o \
+ $(filter strlcat.o, $(LIBOBJS))
+
+The problem is that there is no testing of which object files need to be
+added, but missing functions usually show up when linking user
+applications.
+
+2) For applications, we use -lpgport before -lpq, so the static files
+from libpgport are linked first. This avoids having applications
+dependent on symbols that are _used_ by libpq, but not intended to be
+exported by libpq. libpq's libpgport usage changes over time, so such a
+dependency is a problem. Windows, Linux, AIX, and macOS use an export
+list to control the symbols exported by libpq.
diff --git a/contrib/libs/libpq/src/port/bsearch_arg.c b/contrib/libs/libpq/src/port/bsearch_arg.c
new file mode 100644
index 0000000000..641b40c353
--- /dev/null
+++ b/contrib/libs/libpq/src/port/bsearch_arg.c
@@ -0,0 +1,78 @@
+/*
+ * bsearch_arg.c: bsearch variant with a user-supplied pointer
+ *
+ * Copyright (c) 2021-2023, PostgreSQL Global Development Group
+ * Copyright (c) 1990 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. [rescinded 22 July 1999]
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * src/port/bsearch_arg.c
+ */
+
+#include "c.h"
+
+/*
+ * Perform a binary search.
+ *
+ * The code below is a bit sneaky. After a comparison fails, we
+ * divide the work in half by moving either left or right. If lim
+ * is odd, moving left simply involves halving lim: e.g., when lim
+ * is 5 we look at item 2, so we change lim to 2 so that we will
+ * look at items 0 & 1. If lim is even, the same applies. If lim
+ * is odd, moving right again involves halving lim, this time moving
+ * the base up one item past p: e.g., when lim is 5 we change base
+ * to item 3 and make lim 2 so that we will look at items 3 and 4.
+ * If lim is even, however, we have to shrink it by one before
+ * halving: e.g., when lim is 4, we still looked at item 2, so we
+ * have to make lim 3, then halve, obtaining 1, so that we will only
+ * look at item 3.
+ */
+void *
+bsearch_arg(const void *key, const void *base0,
+ size_t nmemb, size_t size,
+ int (*compar) (const void *, const void *, void *),
+ void *arg)
+{
+ const char *base = (const char *) base0;
+ int lim,
+ cmp;
+ const void *p;
+
+ for (lim = nmemb; lim != 0; lim >>= 1)
+ {
+ p = base + (lim >> 1) * size;
+ cmp = (*compar) (key, p, arg);
+ if (cmp == 0)
+ return (void *) p;
+ if (cmp > 0)
+ { /* key > p: move right */
+ base = (const char *) p + size;
+ lim--;
+ } /* else move left */
+ }
+ return (NULL);
+}
diff --git a/contrib/libs/libpq/src/port/chklocale.c b/contrib/libs/libpq/src/port/chklocale.c
new file mode 100644
index 0000000000..6fa6810a46
--- /dev/null
+++ b/contrib/libs/libpq/src/port/chklocale.c
@@ -0,0 +1,433 @@
+/*-------------------------------------------------------------------------
+ *
+ * chklocale.c
+ * Functions for handling locale-related info
+ *
+ *
+ * Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ *
+ *
+ * IDENTIFICATION
+ * src/port/chklocale.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#ifdef HAVE_LANGINFO_H
+#include <langinfo.h>
+#endif
+
+#include "mb/pg_wchar.h"
+
+
+/*
+ * This table needs to recognize all the CODESET spellings for supported
+ * backend encodings, as well as frontend-only encodings where possible
+ * (the latter case is currently only needed for initdb to recognize
+ * error situations). On Windows, we rely on entries for codepage
+ * numbers (CPnnn).
+ *
+ * Note that we search the table with pg_strcasecmp(), so variant
+ * capitalizations don't need their own entries.
+ */
+struct encoding_match
+{
+ enum pg_enc pg_enc_code;
+ const char *system_enc_name;
+};
+
+static const struct encoding_match encoding_match_list[] = {
+ {PG_EUC_JP, "EUC-JP"},
+ {PG_EUC_JP, "eucJP"},
+ {PG_EUC_JP, "IBM-eucJP"},
+ {PG_EUC_JP, "sdeckanji"},
+ {PG_EUC_JP, "CP20932"},
+
+ {PG_EUC_CN, "EUC-CN"},
+ {PG_EUC_CN, "eucCN"},
+ {PG_EUC_CN, "IBM-eucCN"},
+ {PG_EUC_CN, "GB2312"},
+ {PG_EUC_CN, "dechanzi"},
+ {PG_EUC_CN, "CP20936"},
+
+ {PG_EUC_KR, "EUC-KR"},
+ {PG_EUC_KR, "eucKR"},
+ {PG_EUC_KR, "IBM-eucKR"},
+ {PG_EUC_KR, "deckorean"},
+ {PG_EUC_KR, "5601"},
+ {PG_EUC_KR, "CP51949"},
+
+ {PG_EUC_TW, "EUC-TW"},
+ {PG_EUC_TW, "eucTW"},
+ {PG_EUC_TW, "IBM-eucTW"},
+ {PG_EUC_TW, "cns11643"},
+ /* No codepage for EUC-TW ? */
+
+ {PG_UTF8, "UTF-8"},
+ {PG_UTF8, "utf8"},
+ {PG_UTF8, "CP65001"},
+
+ {PG_LATIN1, "ISO-8859-1"},
+ {PG_LATIN1, "ISO8859-1"},
+ {PG_LATIN1, "iso88591"},
+ {PG_LATIN1, "CP28591"},
+
+ {PG_LATIN2, "ISO-8859-2"},
+ {PG_LATIN2, "ISO8859-2"},
+ {PG_LATIN2, "iso88592"},
+ {PG_LATIN2, "CP28592"},
+
+ {PG_LATIN3, "ISO-8859-3"},
+ {PG_LATIN3, "ISO8859-3"},
+ {PG_LATIN3, "iso88593"},
+ {PG_LATIN3, "CP28593"},
+
+ {PG_LATIN4, "ISO-8859-4"},
+ {PG_LATIN4, "ISO8859-4"},
+ {PG_LATIN4, "iso88594"},
+ {PG_LATIN4, "CP28594"},
+
+ {PG_LATIN5, "ISO-8859-9"},
+ {PG_LATIN5, "ISO8859-9"},
+ {PG_LATIN5, "iso88599"},
+ {PG_LATIN5, "CP28599"},
+
+ {PG_LATIN6, "ISO-8859-10"},
+ {PG_LATIN6, "ISO8859-10"},
+ {PG_LATIN6, "iso885910"},
+
+ {PG_LATIN7, "ISO-8859-13"},
+ {PG_LATIN7, "ISO8859-13"},
+ {PG_LATIN7, "iso885913"},
+
+ {PG_LATIN8, "ISO-8859-14"},
+ {PG_LATIN8, "ISO8859-14"},
+ {PG_LATIN8, "iso885914"},
+
+ {PG_LATIN9, "ISO-8859-15"},
+ {PG_LATIN9, "ISO8859-15"},
+ {PG_LATIN9, "iso885915"},
+ {PG_LATIN9, "CP28605"},
+
+ {PG_LATIN10, "ISO-8859-16"},
+ {PG_LATIN10, "ISO8859-16"},
+ {PG_LATIN10, "iso885916"},
+
+ {PG_KOI8R, "KOI8-R"},
+ {PG_KOI8R, "CP20866"},
+
+ {PG_KOI8U, "KOI8-U"},
+ {PG_KOI8U, "CP21866"},
+
+ {PG_WIN866, "CP866"},
+ {PG_WIN874, "CP874"},
+ {PG_WIN1250, "CP1250"},
+ {PG_WIN1251, "CP1251"},
+ {PG_WIN1251, "ansi-1251"},
+ {PG_WIN1252, "CP1252"},
+ {PG_WIN1253, "CP1253"},
+ {PG_WIN1254, "CP1254"},
+ {PG_WIN1255, "CP1255"},
+ {PG_WIN1256, "CP1256"},
+ {PG_WIN1257, "CP1257"},
+ {PG_WIN1258, "CP1258"},
+
+ {PG_ISO_8859_5, "ISO-8859-5"},
+ {PG_ISO_8859_5, "ISO8859-5"},
+ {PG_ISO_8859_5, "iso88595"},
+ {PG_ISO_8859_5, "CP28595"},
+
+ {PG_ISO_8859_6, "ISO-8859-6"},
+ {PG_ISO_8859_6, "ISO8859-6"},
+ {PG_ISO_8859_6, "iso88596"},
+ {PG_ISO_8859_6, "CP28596"},
+
+ {PG_ISO_8859_7, "ISO-8859-7"},
+ {PG_ISO_8859_7, "ISO8859-7"},
+ {PG_ISO_8859_7, "iso88597"},
+ {PG_ISO_8859_7, "CP28597"},
+
+ {PG_ISO_8859_8, "ISO-8859-8"},
+ {PG_ISO_8859_8, "ISO8859-8"},
+ {PG_ISO_8859_8, "iso88598"},
+ {PG_ISO_8859_8, "CP28598"},
+
+ {PG_SJIS, "SJIS"},
+ {PG_SJIS, "PCK"},
+ {PG_SJIS, "CP932"},
+ {PG_SJIS, "SHIFT_JIS"},
+
+ {PG_BIG5, "BIG5"},
+ {PG_BIG5, "BIG5HKSCS"},
+ {PG_BIG5, "Big5-HKSCS"},
+ {PG_BIG5, "CP950"},
+
+ {PG_GBK, "GBK"},
+ {PG_GBK, "CP936"},
+
+ {PG_UHC, "UHC"},
+ {PG_UHC, "CP949"},
+
+ {PG_JOHAB, "JOHAB"},
+ {PG_JOHAB, "CP1361"},
+
+ {PG_GB18030, "GB18030"},
+ {PG_GB18030, "CP54936"},
+
+ {PG_SHIFT_JIS_2004, "SJIS_2004"},
+
+ {PG_SQL_ASCII, "US-ASCII"},
+
+ {PG_SQL_ASCII, NULL} /* end marker */
+};
+
+#ifdef WIN32
+/*
+ * On Windows, use CP<code page number> instead of the nl_langinfo() result
+ *
+ * This routine uses GetLocaleInfoEx() to parse short locale names like
+ * "de-DE", "fr-FR", etc. If those cannot be parsed correctly process falls
+ * back to the pre-VS-2010 manual parsing done with using
+ * <Language>_<Country>.<CodePage> as a base.
+ *
+ * Returns a malloc()'d string for the caller to free.
+ */
+static char *
+win32_langinfo(const char *ctype)
+{
+ char *r = NULL;
+ char *codepage;
+
+#if defined(_MSC_VER)
+ uint32 cp;
+ WCHAR wctype[LOCALE_NAME_MAX_LENGTH];
+
+ memset(wctype, 0, sizeof(wctype));
+ MultiByteToWideChar(CP_ACP, 0, ctype, -1, wctype, LOCALE_NAME_MAX_LENGTH);
+
+ if (GetLocaleInfoEx(wctype,
+ LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER,
+ (LPWSTR) &cp, sizeof(cp) / sizeof(WCHAR)) > 0)
+ {
+ r = malloc(16); /* excess */
+ if (r != NULL)
+ {
+ /*
+ * If the return value is CP_ACP that means no ANSI code page is
+ * available, so only Unicode can be used for the locale.
+ */
+ if (cp == CP_ACP)
+ strcpy(r, "utf8");
+ else
+ sprintf(r, "CP%u", cp);
+ }
+ }
+ else
+#endif
+ {
+ /*
+ * Locale format on Win32 is <Language>_<Country>.<CodePage>. For
+ * example, English_United States.1252. If we see digits after the
+ * last dot, assume it's a codepage number. Otherwise, we might be
+ * dealing with a Unix-style locale string; Windows' setlocale() will
+ * take those even though GetLocaleInfoEx() won't, so we end up here.
+ * In that case, just return what's after the last dot and hope we can
+ * find it in our table.
+ */
+ codepage = strrchr(ctype, '.');
+ if (codepage != NULL)
+ {
+ size_t ln;
+
+ codepage++;
+ ln = strlen(codepage);
+ r = malloc(ln + 3);
+ if (r != NULL)
+ {
+ if (strspn(codepage, "0123456789") == ln)
+ sprintf(r, "CP%s", codepage);
+ else
+ strcpy(r, codepage);
+ }
+ }
+ }
+
+ return r;
+}
+
+#ifndef FRONTEND
+/*
+ * Given a Windows code page identifier, find the corresponding PostgreSQL
+ * encoding. Issue a warning and return -1 if none found.
+ */
+int
+pg_codepage_to_encoding(UINT cp)
+{
+ char sys[16];
+ int i;
+
+ sprintf(sys, "CP%u", cp);
+
+ /* Check the table */
+ for (i = 0; encoding_match_list[i].system_enc_name; i++)
+ if (pg_strcasecmp(sys, encoding_match_list[i].system_enc_name) == 0)
+ return encoding_match_list[i].pg_enc_code;
+
+ ereport(WARNING,
+ (errmsg("could not determine encoding for codeset \"%s\"", sys)));
+
+ return -1;
+}
+#endif
+#endif /* WIN32 */
+
+#if (defined(HAVE_LANGINFO_H) && defined(CODESET)) || defined(WIN32)
+
+/*
+ * Given a setting for LC_CTYPE, return the Postgres ID of the associated
+ * encoding, if we can determine it. Return -1 if we can't determine it.
+ *
+ * Pass in NULL to get the encoding for the current locale setting.
+ * Pass "" to get the encoding selected by the server's environment.
+ *
+ * If the result is PG_SQL_ASCII, callers should treat it as being compatible
+ * with any desired encoding.
+ *
+ * If running in the backend and write_message is false, this function must
+ * cope with the possibility that elog() and palloc() are not yet usable.
+ */
+int
+pg_get_encoding_from_locale(const char *ctype, bool write_message)
+{
+ char *sys;
+ int i;
+
+ /* Get the CODESET property, and also LC_CTYPE if not passed in */
+ if (ctype)
+ {
+ char *save;
+ char *name;
+
+ /* If locale is C or POSIX, we can allow all encodings */
+ if (pg_strcasecmp(ctype, "C") == 0 ||
+ pg_strcasecmp(ctype, "POSIX") == 0)
+ return PG_SQL_ASCII;
+
+ save = setlocale(LC_CTYPE, NULL);
+ if (!save)
+ return -1; /* setlocale() broken? */
+ /* must copy result, or it might change after setlocale */
+ save = strdup(save);
+ if (!save)
+ return -1; /* out of memory; unlikely */
+
+ name = setlocale(LC_CTYPE, ctype);
+ if (!name)
+ {
+ free(save);
+ return -1; /* bogus ctype passed in? */
+ }
+
+#ifndef WIN32
+ sys = nl_langinfo(CODESET);
+ if (sys)
+ sys = strdup(sys);
+#else
+ sys = win32_langinfo(name);
+#endif
+
+ setlocale(LC_CTYPE, save);
+ free(save);
+ }
+ else
+ {
+ /* much easier... */
+ ctype = setlocale(LC_CTYPE, NULL);
+ if (!ctype)
+ return -1; /* setlocale() broken? */
+
+ /* If locale is C or POSIX, we can allow all encodings */
+ if (pg_strcasecmp(ctype, "C") == 0 ||
+ pg_strcasecmp(ctype, "POSIX") == 0)
+ return PG_SQL_ASCII;
+
+#ifndef WIN32
+ sys = nl_langinfo(CODESET);
+ if (sys)
+ sys = strdup(sys);
+#else
+ sys = win32_langinfo(ctype);
+#endif
+ }
+
+ if (!sys)
+ return -1; /* out of memory; unlikely */
+
+ /* Check the table */
+ for (i = 0; encoding_match_list[i].system_enc_name; i++)
+ {
+ if (pg_strcasecmp(sys, encoding_match_list[i].system_enc_name) == 0)
+ {
+ free(sys);
+ return encoding_match_list[i].pg_enc_code;
+ }
+ }
+
+ /* Special-case kluges for particular platforms go here */
+
+#ifdef __darwin__
+
+ /*
+ * Current macOS has many locales that report an empty string for CODESET,
+ * but they all seem to actually use UTF-8.
+ */
+ if (strlen(sys) == 0)
+ {
+ free(sys);
+ return PG_UTF8;
+ }
+#endif
+
+ /*
+ * We print a warning if we got a CODESET string but couldn't recognize
+ * it. This means we need another entry in the table.
+ */
+ if (write_message)
+ {
+#ifdef FRONTEND
+ fprintf(stderr, _("could not determine encoding for locale \"%s\": codeset is \"%s\""),
+ ctype, sys);
+ /* keep newline separate so there's only one translatable string */
+ fputc('\n', stderr);
+#else
+ ereport(WARNING,
+ (errmsg("could not determine encoding for locale \"%s\": codeset is \"%s\"",
+ ctype, sys)));
+#endif
+ }
+
+ free(sys);
+ return -1;
+}
+#else /* (HAVE_LANGINFO_H && CODESET) || WIN32 */
+
+/*
+ * stub if no multi-language platform support
+ *
+ * Note: we could return -1 here, but that would have the effect of
+ * forcing users to specify an encoding to initdb on such platforms.
+ * It seems better to silently default to SQL_ASCII.
+ */
+int
+pg_get_encoding_from_locale(const char *ctype, bool write_message)
+{
+ return PG_SQL_ASCII;
+}
+
+#endif /* (HAVE_LANGINFO_H && CODESET) || WIN32 */
diff --git a/contrib/libs/libpq/src/port/dirmod.c b/contrib/libs/libpq/src/port/dirmod.c
new file mode 100644
index 0000000000..07dd190cbc
--- /dev/null
+++ b/contrib/libs/libpq/src/port/dirmod.c
@@ -0,0 +1,422 @@
+/*-------------------------------------------------------------------------
+ *
+ * dirmod.c
+ * directory handling functions
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * This includes replacement versions of functions that work on
+ * Windows.
+ *
+ * IDENTIFICATION
+ * src/port/dirmod.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+/* Don't modify declarations in system headers */
+#if defined(WIN32) || defined(__CYGWIN__)
+#undef rename
+#undef unlink
+#endif
+
+#include <unistd.h>
+#include <sys/stat.h>
+
+#if defined(WIN32) || defined(__CYGWIN__)
+#ifndef __CYGWIN__
+#include <winioctl.h>
+#else
+#include <windows.h>
+#include <w32api/winioctl.h>
+#endif
+#endif
+
+#if defined(WIN32) && !defined(__CYGWIN__)
+#include "port/win32ntdll.h"
+#endif
+
+#if defined(WIN32) || defined(__CYGWIN__)
+
+/*
+ * pgrename
+ */
+int
+pgrename(const char *from, const char *to)
+{
+ int loops = 0;
+
+ /*
+ * We need to loop because even though PostgreSQL uses flags that allow
+ * rename while the file is open, other applications might have the file
+ * open without those flags. However, we won't wait indefinitely for
+ * someone else to close the file, as the caller might be holding locks
+ * and blocking other backends.
+ */
+#if defined(WIN32) && !defined(__CYGWIN__)
+ while (!MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING))
+#else
+ while (rename(from, to) < 0)
+#endif
+ {
+#if defined(WIN32) && !defined(__CYGWIN__)
+ DWORD err = GetLastError();
+
+ _dosmaperr(err);
+
+ /*
+ * Modern NT-based Windows versions return ERROR_SHARING_VIOLATION if
+ * another process has the file open without FILE_SHARE_DELETE.
+ * ERROR_LOCK_VIOLATION has also been seen with some anti-virus
+ * software. This used to check for just ERROR_ACCESS_DENIED, so
+ * presumably you can get that too with some OS versions. We don't
+ * expect real permission errors where we currently use rename().
+ */
+ if (err != ERROR_ACCESS_DENIED &&
+ err != ERROR_SHARING_VIOLATION &&
+ err != ERROR_LOCK_VIOLATION)
+ return -1;
+#else
+ if (errno != EACCES)
+ return -1;
+#endif
+
+ if (++loops > 100) /* time out after 10 sec */
+ return -1;
+ pg_usleep(100000); /* us */
+ }
+ return 0;
+}
+
+/*
+ * Check if _pglstat64()'s reason for failure was STATUS_DELETE_PENDING.
+ * This doesn't apply to Cygwin, which has its own lstat() that would report
+ * the case as EACCES.
+*/
+static bool
+lstat_error_was_status_delete_pending(void)
+{
+ if (errno != ENOENT)
+ return false;
+#if defined(WIN32) && !defined(__CYGWIN__)
+ if (pg_RtlGetLastNtStatus() == STATUS_DELETE_PENDING)
+ return true;
+#endif
+ return false;
+}
+
+/*
+ * pgunlink
+ */
+int
+pgunlink(const char *path)
+{
+ bool is_lnk;
+ int loops = 0;
+ struct stat st;
+
+ /*
+ * This function might be called for a regular file or for a junction
+ * point (which we use to emulate symlinks). The latter must be unlinked
+ * with rmdir() on Windows. Before we worry about any of that, let's see
+ * if we can unlink directly, since that's expected to be the most common
+ * case.
+ */
+ if (unlink(path) == 0)
+ return 0;
+ if (errno != EACCES)
+ return -1;
+
+ /*
+ * EACCES is reported for many reasons including unlink() of a junction
+ * point. Check if that's the case so we can redirect to rmdir().
+ *
+ * Note that by checking only once, we can't cope with a path that changes
+ * from regular file to junction point underneath us while we're retrying
+ * due to sharing violations, but that seems unlikely. We could perhaps
+ * prevent that by holding a file handle ourselves across the lstat() and
+ * the retry loop, but that seems like over-engineering for now.
+ *
+ * In the special case of a STATUS_DELETE_PENDING error (file already
+ * unlinked, but someone still has it open), we don't want to report
+ * ENOENT to the caller immediately, because rmdir(parent) would probably
+ * fail. We want to wait until the file truly goes away so that simple
+ * recursive directory unlink algorithms work.
+ */
+ if (lstat(path, &st) < 0)
+ {
+ if (lstat_error_was_status_delete_pending())
+ is_lnk = false;
+ else
+ return -1;
+ }
+ else
+ is_lnk = S_ISLNK(st.st_mode);
+
+ /*
+ * We need to loop because even though PostgreSQL uses flags that allow
+ * unlink while the file is open, other applications might have the file
+ * open without those flags. However, we won't wait indefinitely for
+ * someone else to close the file, as the caller might be holding locks
+ * and blocking other backends.
+ */
+ while ((is_lnk ? rmdir(path) : unlink(path)) < 0)
+ {
+ if (errno != EACCES)
+ return -1;
+ if (++loops > 100) /* time out after 10 sec */
+ return -1;
+ pg_usleep(100000); /* us */
+ }
+ return 0;
+}
+
+/* We undefined these above; now redefine for possible use below */
+#define rename(from, to) pgrename(from, to)
+#define unlink(path) pgunlink(path)
+#endif /* defined(WIN32) || defined(__CYGWIN__) */
+
+
+#if defined(WIN32) && !defined(__CYGWIN__) /* Cygwin has its own symlinks */
+
+/*
+ * pgsymlink support:
+ *
+ * This struct is a replacement for REPARSE_DATA_BUFFER which is defined in VC6 winnt.h
+ * but omitted in later SDK functions.
+ * We only need the SymbolicLinkReparseBuffer part of the original struct's union.
+ */
+typedef struct
+{
+ DWORD ReparseTag;
+ WORD ReparseDataLength;
+ WORD Reserved;
+ /* SymbolicLinkReparseBuffer */
+ WORD SubstituteNameOffset;
+ WORD SubstituteNameLength;
+ WORD PrintNameOffset;
+ WORD PrintNameLength;
+ WCHAR PathBuffer[FLEXIBLE_ARRAY_MEMBER];
+} REPARSE_JUNCTION_DATA_BUFFER;
+
+#define REPARSE_JUNCTION_DATA_BUFFER_HEADER_SIZE \
+ FIELD_OFFSET(REPARSE_JUNCTION_DATA_BUFFER, SubstituteNameOffset)
+
+
+/*
+ * pgsymlink - uses Win32 junction points
+ *
+ * For reference: http://www.codeproject.com/KB/winsdk/junctionpoints.aspx
+ */
+int
+pgsymlink(const char *oldpath, const char *newpath)
+{
+ HANDLE dirhandle;
+ DWORD len;
+ char buffer[MAX_PATH * sizeof(WCHAR) + offsetof(REPARSE_JUNCTION_DATA_BUFFER, PathBuffer)];
+ char nativeTarget[MAX_PATH];
+ char *p = nativeTarget;
+ REPARSE_JUNCTION_DATA_BUFFER *reparseBuf = (REPARSE_JUNCTION_DATA_BUFFER *) buffer;
+
+ CreateDirectory(newpath, 0);
+ dirhandle = CreateFile(newpath, GENERIC_READ | GENERIC_WRITE,
+ 0, 0, OPEN_EXISTING,
+ FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, 0);
+
+ if (dirhandle == INVALID_HANDLE_VALUE)
+ {
+ _dosmaperr(GetLastError());
+ return -1;
+ }
+
+ /* make sure we have an unparsed native win32 path */
+ if (memcmp("\\??\\", oldpath, 4) != 0)
+ snprintf(nativeTarget, sizeof(nativeTarget), "\\??\\%s", oldpath);
+ else
+ strlcpy(nativeTarget, oldpath, sizeof(nativeTarget));
+
+ while ((p = strchr(p, '/')) != NULL)
+ *p++ = '\\';
+
+ len = strlen(nativeTarget) * sizeof(WCHAR);
+ reparseBuf->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
+ reparseBuf->ReparseDataLength = len + 12;
+ reparseBuf->Reserved = 0;
+ reparseBuf->SubstituteNameOffset = 0;
+ reparseBuf->SubstituteNameLength = len;
+ reparseBuf->PrintNameOffset = len + sizeof(WCHAR);
+ reparseBuf->PrintNameLength = 0;
+ MultiByteToWideChar(CP_ACP, 0, nativeTarget, -1,
+ reparseBuf->PathBuffer, MAX_PATH);
+
+ /*
+ * FSCTL_SET_REPARSE_POINT is coded differently depending on SDK version;
+ * we use our own definition
+ */
+ if (!DeviceIoControl(dirhandle,
+ CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 41, METHOD_BUFFERED, FILE_ANY_ACCESS),
+ reparseBuf,
+ reparseBuf->ReparseDataLength + REPARSE_JUNCTION_DATA_BUFFER_HEADER_SIZE,
+ 0, 0, &len, 0))
+ {
+ LPSTR msg;
+ int save_errno;
+
+ _dosmaperr(GetLastError());
+ save_errno = errno;
+
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_IGNORE_INSERTS |
+ FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, GetLastError(),
+ MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
+ (LPSTR) &msg, 0, NULL);
+#ifndef FRONTEND
+ ereport(ERROR,
+ (errcode_for_file_access(),
+ errmsg("could not set junction for \"%s\": %s",
+ nativeTarget, msg)));
+#else
+ fprintf(stderr, _("could not set junction for \"%s\": %s\n"),
+ nativeTarget, msg);
+#endif
+ LocalFree(msg);
+
+ CloseHandle(dirhandle);
+ RemoveDirectory(newpath);
+
+ errno = save_errno;
+
+ return -1;
+ }
+
+ CloseHandle(dirhandle);
+
+ return 0;
+}
+
+/*
+ * pgreadlink - uses Win32 junction points
+ */
+int
+pgreadlink(const char *path, char *buf, size_t size)
+{
+ DWORD attr;
+ HANDLE h;
+ char buffer[MAX_PATH * sizeof(WCHAR) + offsetof(REPARSE_JUNCTION_DATA_BUFFER, PathBuffer)];
+ REPARSE_JUNCTION_DATA_BUFFER *reparseBuf = (REPARSE_JUNCTION_DATA_BUFFER *) buffer;
+ DWORD len;
+ int r;
+
+ attr = GetFileAttributes(path);
+ if (attr == INVALID_FILE_ATTRIBUTES)
+ {
+ _dosmaperr(GetLastError());
+ return -1;
+ }
+ if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) == 0)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ h = CreateFile(path,
+ GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
+ 0);
+ if (h == INVALID_HANDLE_VALUE)
+ {
+ _dosmaperr(GetLastError());
+ return -1;
+ }
+
+ if (!DeviceIoControl(h,
+ FSCTL_GET_REPARSE_POINT,
+ NULL,
+ 0,
+ (LPVOID) reparseBuf,
+ sizeof(buffer),
+ &len,
+ NULL))
+ {
+ LPSTR msg;
+
+ errno = 0;
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_IGNORE_INSERTS |
+ FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, GetLastError(),
+ MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
+ (LPSTR) &msg, 0, NULL);
+#ifndef FRONTEND
+ ereport(ERROR,
+ (errcode_for_file_access(),
+ errmsg("could not get junction for \"%s\": %s",
+ path, msg)));
+#else
+ fprintf(stderr, _("could not get junction for \"%s\": %s\n"),
+ path, msg);
+#endif
+ LocalFree(msg);
+ CloseHandle(h);
+ errno = EINVAL;
+ return -1;
+ }
+ CloseHandle(h);
+
+ /* Got it, let's get some results from this */
+ if (reparseBuf->ReparseTag != IO_REPARSE_TAG_MOUNT_POINT)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ r = WideCharToMultiByte(CP_ACP, 0,
+ reparseBuf->PathBuffer, -1,
+ buf,
+ size,
+ NULL, NULL);
+
+ if (r <= 0)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* r includes the null terminator */
+ r -= 1;
+
+ /*
+ * If the path starts with "\??\" followed by a "drive absolute" path
+ * (known to Windows APIs as RtlPathTypeDriveAbsolute), then strip that
+ * prefix. This undoes some of the transformation performed by
+ * pgsymlink(), to get back to a format that users are used to seeing. We
+ * don't know how to transform other path types that might be encountered
+ * outside PGDATA, so we just return them directly.
+ */
+ if (r >= 7 &&
+ buf[0] == '\\' &&
+ buf[1] == '?' &&
+ buf[2] == '?' &&
+ buf[3] == '\\' &&
+ isalpha(buf[4]) &&
+ buf[5] == ':' &&
+ buf[6] == '\\')
+ {
+ memmove(buf, buf + 4, strlen(buf + 4) + 1);
+ r -= 4;
+ }
+ return r;
+}
+
+#endif /* defined(WIN32) && !defined(__CYGWIN__) */
diff --git a/contrib/libs/libpq/src/port/getpeereid.c b/contrib/libs/libpq/src/port/getpeereid.c
new file mode 100644
index 0000000000..3b040e076b
--- /dev/null
+++ b/contrib/libs/libpq/src/port/getpeereid.c
@@ -0,0 +1,78 @@
+/*-------------------------------------------------------------------------
+ *
+ * getpeereid.c
+ * get peer userid for UNIX-domain socket connection
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ *
+ *
+ * IDENTIFICATION
+ * src/port/getpeereid.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "c.h"
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+#ifdef HAVE_UCRED_H
+#include <ucred.h>
+#endif
+#ifdef HAVE_SYS_UCRED_H
+#include <sys/ucred.h>
+#endif
+
+
+/*
+ * BSD-style getpeereid() for platforms that lack it.
+ */
+int
+getpeereid(int sock, uid_t *uid, gid_t *gid)
+{
+#if defined(SO_PEERCRED)
+ /* Linux: use getsockopt(SO_PEERCRED) */
+ struct ucred peercred;
+ socklen_t so_len = sizeof(peercred);
+
+ if (getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) != 0 ||
+ so_len != sizeof(peercred))
+ return -1;
+ *uid = peercred.uid;
+ *gid = peercred.gid;
+ return 0;
+#elif defined(LOCAL_PEERCRED)
+ /* Debian with FreeBSD kernel: use getsockopt(LOCAL_PEERCRED) */
+ struct xucred peercred;
+ socklen_t so_len = sizeof(peercred);
+
+ if (getsockopt(sock, 0, LOCAL_PEERCRED, &peercred, &so_len) != 0 ||
+ so_len != sizeof(peercred) ||
+ peercred.cr_version != XUCRED_VERSION)
+ return -1;
+ *uid = peercred.cr_uid;
+ *gid = peercred.cr_gid;
+ return 0;
+#elif defined(HAVE_GETPEERUCRED)
+ /* Solaris: use getpeerucred() */
+ ucred_t *ucred;
+
+ ucred = NULL; /* must be initialized to NULL */
+ if (getpeerucred(sock, &ucred) == -1)
+ return -1;
+
+ *uid = ucred_geteuid(ucred);
+ *gid = ucred_getegid(ucred);
+ ucred_free(ucred);
+
+ if (*uid == (uid_t) (-1) || *gid == (gid_t) (-1))
+ return -1;
+ return 0;
+#else
+ /* No implementation available on this platform */
+ errno = ENOSYS;
+ return -1;
+#endif
+}
diff --git a/contrib/libs/libpq/src/port/inet_aton.c b/contrib/libs/libpq/src/port/inet_aton.c
new file mode 100644
index 0000000000..adaf18adb3
--- /dev/null
+++ b/contrib/libs/libpq/src/port/inet_aton.c
@@ -0,0 +1,149 @@
+/* src/port/inet_aton.c
+ *
+ * This inet_aton() function was taken from the GNU C library and
+ * incorporated into Postgres for those systems which do not have this
+ * routine in their standard C libraries.
+ *
+ * The function was been extracted whole from the file inet_aton.c in
+ * Release 5.3.12 of the Linux C library, which is derived from the
+ * GNU C library, by Bryan Henderson in October 1996. The copyright
+ * notice from that file is below.
+ */
+
+/*
+ * Copyright (c) 1983, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE. */
+
+#include "c.h"
+
+#include <netinet/in.h>
+#include <ctype.h>
+
+#include "port/pg_bswap.h"
+
+/*
+ * Check whether "cp" is a valid ascii representation
+ * of an Internet address and convert to a binary address.
+ * Returns 1 if the address is valid, 0 if not.
+ * This replaces inet_addr, the return value from which
+ * cannot distinguish between failure and a local broadcast address.
+ */
+int
+inet_aton(const char *cp, struct in_addr *addr)
+{
+ unsigned int val;
+ int base,
+ n;
+ char c;
+ u_int parts[4];
+ u_int *pp = parts;
+
+ for (;;)
+ {
+ /*
+ * Collect number up to ``.''. Values are specified as for C: 0x=hex,
+ * 0=octal, other=decimal.
+ */
+ val = 0;
+ base = 10;
+ if (*cp == '0')
+ {
+ if (*++cp == 'x' || *cp == 'X')
+ base = 16, cp++;
+ else
+ base = 8;
+ }
+ while ((c = *cp) != '\0')
+ {
+ if (isdigit((unsigned char) c))
+ {
+ val = (val * base) + (c - '0');
+ cp++;
+ continue;
+ }
+ if (base == 16 && isxdigit((unsigned char) c))
+ {
+ val = (val << 4) +
+ (c + 10 - (islower((unsigned char) c) ? 'a' : 'A'));
+ cp++;
+ continue;
+ }
+ break;
+ }
+ if (*cp == '.')
+ {
+ /*
+ * Internet format: a.b.c.d a.b.c (with c treated as 16-bits)
+ * a.b (with b treated as 24 bits)
+ */
+ if (pp >= parts + 3 || val > 0xff)
+ return 0;
+ *pp++ = val, cp++;
+ }
+ else
+ break;
+ }
+
+ /*
+ * Check for trailing junk.
+ */
+ while (*cp)
+ if (!isspace((unsigned char) *cp++))
+ return 0;
+
+ /*
+ * Concoct the address according to the number of parts specified.
+ */
+ n = pp - parts + 1;
+ switch (n)
+ {
+
+ case 1: /* a -- 32 bits */
+ break;
+
+ case 2: /* a.b -- 8.24 bits */
+ if (val > 0xffffff)
+ return 0;
+ val |= parts[0] << 24;
+ break;
+
+ case 3: /* a.b.c -- 8.8.16 bits */
+ if (val > 0xffff)
+ return 0;
+ val |= (parts[0] << 24) | (parts[1] << 16);
+ break;
+
+ case 4: /* a.b.c.d -- 8.8.8.8 bits */
+ if (val > 0xff)
+ return 0;
+ val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
+ break;
+ }
+ if (addr)
+ addr->s_addr = pg_hton32(val);
+ return 1;
+}
diff --git a/contrib/libs/libpq/src/port/inet_net_ntop.c b/contrib/libs/libpq/src/port/inet_net_ntop.c
new file mode 100644
index 0000000000..4044f22450
--- /dev/null
+++ b/contrib/libs/libpq/src/port/inet_net_ntop.c
@@ -0,0 +1,296 @@
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * src/port/inet_net_ntop.c
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "Id: inet_net_ntop.c,v 1.1.2.2 2004/03/09 09:17:27 marka Exp $";
+#endif
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#ifndef FRONTEND
+#error #include "utils/inet.h"
+#else
+/*
+ * In a frontend build, we can't include inet.h, but we still need to have
+ * sensible definitions of these two constants. Note that pg_inet_net_ntop()
+ * assumes that PGSQL_AF_INET is equal to AF_INET.
+ */
+#define PGSQL_AF_INET (AF_INET + 0)
+#define PGSQL_AF_INET6 (AF_INET + 1)
+#endif
+
+
+#define NS_IN6ADDRSZ 16
+#define NS_INT16SZ 2
+
+#ifdef SPRINTF_CHAR
+#define SPRINTF(x) strlen(sprintf/**/x)
+#else
+#define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+static char *inet_net_ntop_ipv4(const u_char *src, int bits,
+ char *dst, size_t size);
+static char *inet_net_ntop_ipv6(const u_char *src, int bits,
+ char *dst, size_t size);
+
+
+/*
+ * char *
+ * pg_inet_net_ntop(af, src, bits, dst, size)
+ * convert host/network address from network to presentation format.
+ * "src"'s size is determined from its "af".
+ * return:
+ * pointer to dst, or NULL if an error occurred (check errno).
+ * note:
+ * 192.5.5.1/28 has a nonzero host part, which means it isn't a network
+ * as called for by pg_inet_net_pton() but it can be a host address with
+ * an included netmask.
+ * author:
+ * Paul Vixie (ISC), October 1998
+ */
+char *
+pg_inet_net_ntop(int af, const void *src, int bits, char *dst, size_t size)
+{
+ /*
+ * We need to cover both the address family constants used by the PG inet
+ * type (PGSQL_AF_INET and PGSQL_AF_INET6) and those used by the system
+ * libraries (AF_INET and AF_INET6). We can safely assume PGSQL_AF_INET
+ * == AF_INET, but the INET6 constants are very likely to be different.
+ */
+ switch (af)
+ {
+ case PGSQL_AF_INET:
+ return (inet_net_ntop_ipv4(src, bits, dst, size));
+ case PGSQL_AF_INET6:
+#if AF_INET6 != PGSQL_AF_INET6
+ case AF_INET6:
+#endif
+ return (inet_net_ntop_ipv6(src, bits, dst, size));
+ default:
+ errno = EAFNOSUPPORT;
+ return (NULL);
+ }
+}
+
+/*
+ * static char *
+ * inet_net_ntop_ipv4(src, bits, dst, size)
+ * convert IPv4 network address from network to presentation format.
+ * "src"'s size is determined from its "af".
+ * return:
+ * pointer to dst, or NULL if an error occurred (check errno).
+ * note:
+ * network byte order assumed. this means 192.5.5.240/28 has
+ * 0b11110000 in its fourth octet.
+ * author:
+ * Paul Vixie (ISC), October 1998
+ */
+static char *
+inet_net_ntop_ipv4(const u_char *src, int bits, char *dst, size_t size)
+{
+ char *odst = dst;
+ char *t;
+ int len = 4;
+ int b;
+
+ if (bits < 0 || bits > 32)
+ {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ /* Always format all four octets, regardless of mask length. */
+ for (b = len; b > 0; b--)
+ {
+ if (size <= sizeof ".255")
+ goto emsgsize;
+ t = dst;
+ if (dst != odst)
+ *dst++ = '.';
+ dst += SPRINTF((dst, "%u", *src++));
+ size -= (size_t) (dst - t);
+ }
+
+ /* don't print masklen if 32 bits */
+ if (bits != 32)
+ {
+ if (size <= sizeof "/32")
+ goto emsgsize;
+ dst += SPRINTF((dst, "/%u", bits));
+ }
+
+ return (odst);
+
+emsgsize:
+ errno = EMSGSIZE;
+ return (NULL);
+}
+
+static int
+decoct(const u_char *src, int bytes, char *dst, size_t size)
+{
+ char *odst = dst;
+ char *t;
+ int b;
+
+ for (b = 1; b <= bytes; b++)
+ {
+ if (size <= sizeof "255.")
+ return (0);
+ t = dst;
+ dst += SPRINTF((dst, "%u", *src++));
+ if (b != bytes)
+ {
+ *dst++ = '.';
+ *dst = '\0';
+ }
+ size -= (size_t) (dst - t);
+ }
+ return (dst - odst);
+}
+
+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.
+ */
+ char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255/128"];
+ char *tp;
+ struct
+ {
+ int base,
+ len;
+ } best, cur;
+ u_int words[NS_IN6ADDRSZ / NS_INT16SZ];
+ int i;
+
+ if ((bits < -1) || (bits > 128))
+ {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ /*
+ * Preprocess: Copy the input (bytewise) array into a wordwise array. Find
+ * the longest run of 0x00's in src[] for :: shorthanding.
+ */
+ memset(words, '\0', sizeof words);
+ for (i = 0; i < NS_IN6ADDRSZ; i++)
+ words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
+ best.base = -1;
+ cur.base = -1;
+ best.len = 0;
+ cur.len = 0;
+ for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++)
+ {
+ if (words[i] == 0)
+ {
+ if (cur.base == -1)
+ cur.base = i, cur.len = 1;
+ else
+ cur.len++;
+ }
+ else
+ {
+ if (cur.base != -1)
+ {
+ if (best.base == -1 || cur.len > best.len)
+ best = cur;
+ cur.base = -1;
+ }
+ }
+ }
+ if (cur.base != -1)
+ {
+ if (best.base == -1 || cur.len > best.len)
+ best = cur;
+ }
+ if (best.base != -1 && best.len < 2)
+ best.base = -1;
+
+ /*
+ * Format the result.
+ */
+ tp = tmp;
+ for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++)
+ {
+ /* Are we inside the best run of 0x00's? */
+ if (best.base != -1 && i >= best.base &&
+ i < (best.base + best.len))
+ {
+ if (i == best.base)
+ *tp++ = ':';
+ continue;
+ }
+ /* Are we following an initial run of 0x00s or any real hex? */
+ if (i != 0)
+ *tp++ = ':';
+ /* Is this address an encapsulated IPv4? */
+ if (i == 6 && best.base == 0 && (best.len == 6 ||
+ (best.len == 7 && words[7] != 0x0001) ||
+ (best.len == 5 && words[5] == 0xffff)))
+ {
+ int n;
+
+ n = decoct(src + 12, 4, tp, sizeof tmp - (tp - tmp));
+ if (n == 0)
+ {
+ errno = EMSGSIZE;
+ return (NULL);
+ }
+ tp += strlen(tp);
+ break;
+ }
+ tp += SPRINTF((tp, "%x", words[i]));
+ }
+
+ /* Was it a trailing run of 0x00's? */
+ if (best.base != -1 && (best.base + best.len) ==
+ (NS_IN6ADDRSZ / NS_INT16SZ))
+ *tp++ = ':';
+ *tp = '\0';
+
+ if (bits != -1 && bits != 128)
+ tp += SPRINTF((tp, "/%u", bits));
+
+ /*
+ * Check for overflow, copy, and we're done.
+ */
+ if ((size_t) (tp - tmp) > size)
+ {
+ errno = EMSGSIZE;
+ return (NULL);
+ }
+ strcpy(dst, tmp);
+ return (dst);
+}
diff --git a/contrib/libs/libpq/src/port/noblock.c b/contrib/libs/libpq/src/port/noblock.c
new file mode 100644
index 0000000000..d050a03085
--- /dev/null
+++ b/contrib/libs/libpq/src/port/noblock.c
@@ -0,0 +1,66 @@
+/*-------------------------------------------------------------------------
+ *
+ * noblock.c
+ * set a file descriptor as blocking or non-blocking
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/port/noblock.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "c.h"
+
+#include <fcntl.h>
+
+
+/*
+ * Put socket into nonblock mode.
+ * Returns true on success, false on failure.
+ */
+bool
+pg_set_noblock(pgsocket sock)
+{
+#if !defined(WIN32)
+ int flags;
+
+ flags = fcntl(sock, F_GETFL);
+ if (flags < 0)
+ return false;
+ if (fcntl(sock, F_SETFL, (flags | O_NONBLOCK)) == -1)
+ return false;
+ return true;
+#else
+ unsigned long ioctlsocket_ret = 1;
+
+ /* Returns non-0 on failure, while fcntl() returns -1 on failure */
+ return (ioctlsocket(sock, FIONBIO, &ioctlsocket_ret) == 0);
+#endif
+}
+
+/*
+ * Put socket into blocking mode.
+ * Returns true on success, false on failure.
+ */
+bool
+pg_set_block(pgsocket sock)
+{
+#if !defined(WIN32)
+ int flags;
+
+ flags = fcntl(sock, F_GETFL);
+ if (flags < 0)
+ return false;
+ if (fcntl(sock, F_SETFL, (flags & ~O_NONBLOCK)) == -1)
+ return false;
+ return true;
+#else
+ unsigned long ioctlsocket_ret = 0;
+
+ /* Returns non-0 on failure, while fcntl() returns -1 on failure */
+ return (ioctlsocket(sock, FIONBIO, &ioctlsocket_ret) == 0);
+#endif
+}
diff --git a/contrib/libs/libpq/src/port/open.c b/contrib/libs/libpq/src/port/open.c
new file mode 100644
index 0000000000..0bd9755006
--- /dev/null
+++ b/contrib/libs/libpq/src/port/open.c
@@ -0,0 +1,222 @@
+/*-------------------------------------------------------------------------
+ *
+ * open.c
+ * Win32 open() replacement
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ *
+ * src/port/open.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifdef WIN32
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#include "port/win32ntdll.h"
+
+#include <fcntl.h>
+#include <assert.h>
+#include <sys/stat.h>
+
+static int
+openFlagsToCreateFileFlags(int openFlags)
+{
+ switch (openFlags & (O_CREAT | O_TRUNC | O_EXCL))
+ {
+ /* O_EXCL is meaningless without O_CREAT */
+ case 0:
+ case O_EXCL:
+ return OPEN_EXISTING;
+
+ case O_CREAT:
+ return OPEN_ALWAYS;
+
+ /* O_EXCL is meaningless without O_CREAT */
+ case O_TRUNC:
+ case O_TRUNC | O_EXCL:
+ return TRUNCATE_EXISTING;
+
+ case O_CREAT | O_TRUNC:
+ return CREATE_ALWAYS;
+
+ /* O_TRUNC is meaningless with O_CREAT */
+ case O_CREAT | O_EXCL:
+ case O_CREAT | O_TRUNC | O_EXCL:
+ return CREATE_NEW;
+ }
+
+ /* will never get here */
+ return 0;
+}
+
+/*
+ * Internal function used by pgwin32_open() and _pgstat64(). When
+ * backup_semantics is true, directories may be opened (for limited uses). On
+ * failure, INVALID_HANDLE_VALUE is returned and errno is set.
+ */
+HANDLE
+pgwin32_open_handle(const char *fileName, int fileFlags, bool backup_semantics)
+{
+ HANDLE h;
+ SECURITY_ATTRIBUTES sa;
+ int loops = 0;
+
+ if (initialize_ntdll() < 0)
+ return INVALID_HANDLE_VALUE;
+
+ /* Check that we can handle the request */
+ assert((fileFlags & ((O_RDONLY | O_WRONLY | O_RDWR) | O_APPEND |
+ (O_RANDOM | O_SEQUENTIAL | O_TEMPORARY) |
+ _O_SHORT_LIVED | O_DSYNC | O_DIRECT |
+ (O_CREAT | O_TRUNC | O_EXCL) | (O_TEXT | O_BINARY))) == fileFlags);
+
+ sa.nLength = sizeof(sa);
+ sa.bInheritHandle = TRUE;
+ sa.lpSecurityDescriptor = NULL;
+
+ while ((h = CreateFile(fileName,
+ /* cannot use O_RDONLY, as it == 0 */
+ (fileFlags & O_RDWR) ? (GENERIC_WRITE | GENERIC_READ) :
+ ((fileFlags & O_WRONLY) ? GENERIC_WRITE : GENERIC_READ),
+ /* These flags allow concurrent rename/unlink */
+ (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE),
+ &sa,
+ openFlagsToCreateFileFlags(fileFlags),
+ FILE_ATTRIBUTE_NORMAL |
+ (backup_semantics ? FILE_FLAG_BACKUP_SEMANTICS : 0) |
+ ((fileFlags & O_RANDOM) ? FILE_FLAG_RANDOM_ACCESS : 0) |
+ ((fileFlags & O_SEQUENTIAL) ? FILE_FLAG_SEQUENTIAL_SCAN : 0) |
+ ((fileFlags & _O_SHORT_LIVED) ? FILE_ATTRIBUTE_TEMPORARY : 0) |
+ ((fileFlags & O_TEMPORARY) ? FILE_FLAG_DELETE_ON_CLOSE : 0) |
+ ((fileFlags & O_DIRECT) ? FILE_FLAG_NO_BUFFERING : 0) |
+ ((fileFlags & O_DSYNC) ? FILE_FLAG_WRITE_THROUGH : 0),
+ NULL)) == INVALID_HANDLE_VALUE)
+ {
+ /*
+ * Sharing violation or locking error can indicate antivirus, backup
+ * or similar software that's locking the file. Wait a bit and try
+ * again, giving up after 30 seconds.
+ */
+ DWORD err = GetLastError();
+
+ if (err == ERROR_SHARING_VIOLATION ||
+ err == ERROR_LOCK_VIOLATION)
+ {
+#ifndef FRONTEND
+ if (loops == 50)
+ ereport(LOG,
+ (errmsg("could not open file \"%s\": %s", fileName,
+ (err == ERROR_SHARING_VIOLATION) ? _("sharing violation") : _("lock violation")),
+ errdetail("Continuing to retry for 30 seconds."),
+ errhint("You might have antivirus, backup, or similar software interfering with the database system.")));
+#endif
+
+ if (loops < 300)
+ {
+ pg_usleep(100000);
+ loops++;
+ continue;
+ }
+ }
+
+ /*
+ * ERROR_ACCESS_DENIED is returned if the file is deleted but not yet
+ * gone (Windows NT status code is STATUS_DELETE_PENDING). In that
+ * case, we'd better ask for the NT status too so we can translate it
+ * to a more Unix-like error. We hope that nothing clobbers the NT
+ * status in between the internal NtCreateFile() call and CreateFile()
+ * returning.
+ *
+ * If there's no O_CREAT flag, then we'll pretend the file is
+ * invisible. With O_CREAT, we have no choice but to report that
+ * there's a file in the way (which wouldn't happen on Unix).
+ */
+ if (err == ERROR_ACCESS_DENIED &&
+ pg_RtlGetLastNtStatus() == STATUS_DELETE_PENDING)
+ {
+ if (fileFlags & O_CREAT)
+ err = ERROR_FILE_EXISTS;
+ else
+ err = ERROR_FILE_NOT_FOUND;
+ }
+
+ _dosmaperr(err);
+ return INVALID_HANDLE_VALUE;
+ }
+
+ return h;
+}
+
+int
+pgwin32_open(const char *fileName, int fileFlags,...)
+{
+ HANDLE h;
+ int fd;
+
+ h = pgwin32_open_handle(fileName, fileFlags, false);
+ if (h == INVALID_HANDLE_VALUE)
+ return -1;
+
+#ifdef FRONTEND
+
+ /*
+ * Since PostgreSQL 12, those concurrent-safe versions of open() and
+ * fopen() can be used by frontends, having as side-effect to switch the
+ * file-translation mode from O_TEXT to O_BINARY if none is specified.
+ * Caller may want to enforce the binary or text mode, but if nothing is
+ * defined make sure that the default mode maps with what versions older
+ * than 12 have been doing.
+ */
+ if ((fileFlags & O_BINARY) == 0)
+ fileFlags |= O_TEXT;
+#endif
+
+ /* _open_osfhandle will, on error, set errno accordingly */
+ if ((fd = _open_osfhandle((intptr_t) h, fileFlags & O_APPEND)) < 0)
+ CloseHandle(h); /* will not affect errno */
+ else if (fileFlags & (O_TEXT | O_BINARY) &&
+ _setmode(fd, fileFlags & (O_TEXT | O_BINARY)) < 0)
+ {
+ _close(fd);
+ return -1;
+ }
+
+ return fd;
+}
+
+FILE *
+pgwin32_fopen(const char *fileName, const char *mode)
+{
+ int openmode = 0;
+ int fd;
+
+ if (strstr(mode, "r+"))
+ openmode |= O_RDWR;
+ else if (strchr(mode, 'r'))
+ openmode |= O_RDONLY;
+ if (strstr(mode, "w+"))
+ openmode |= O_RDWR | O_CREAT | O_TRUNC;
+ else if (strchr(mode, 'w'))
+ openmode |= O_WRONLY | O_CREAT | O_TRUNC;
+ if (strchr(mode, 'a'))
+ openmode |= O_WRONLY | O_CREAT | O_APPEND;
+
+ if (strchr(mode, 'b'))
+ openmode |= O_BINARY;
+ if (strchr(mode, 't'))
+ openmode |= O_TEXT;
+
+ fd = pgwin32_open(fileName, openmode);
+ if (fd == -1)
+ return NULL;
+ return _fdopen(fd, mode);
+}
+
+#endif
diff --git a/contrib/libs/libpq/src/port/path.c b/contrib/libs/libpq/src/port/path.c
new file mode 100644
index 0000000000..65c7943fee
--- /dev/null
+++ b/contrib/libs/libpq/src/port/path.c
@@ -0,0 +1,1057 @@
+/*-------------------------------------------------------------------------
+ *
+ * path.c
+ * portable path handling routines
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/port/path.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#include <ctype.h>
+#include <sys/stat.h>
+#ifdef WIN32
+#ifdef _WIN32_IE
+#undef _WIN32_IE
+#endif
+#define _WIN32_IE 0x0500
+#ifdef near
+#undef near
+#endif
+#define near
+#include <shlobj.h>
+#else
+#include <unistd.h>
+#endif
+
+#include "pg_config_paths.h"
+
+
+#ifndef WIN32
+#define IS_PATH_VAR_SEP(ch) ((ch) == ':')
+#else
+#define IS_PATH_VAR_SEP(ch) ((ch) == ';')
+#endif
+
+static void make_relative_path(char *ret_path, const char *target_path,
+ const char *bin_path, const char *my_exec_path);
+static char *trim_directory(char *path);
+static void trim_trailing_separator(char *path);
+static char *append_subdir_to_path(char *path, char *subdir);
+
+
+/*
+ * skip_drive
+ *
+ * On Windows, a path may begin with "C:" or "//network/". Advance over
+ * this and point to the effective start of the path.
+ */
+#ifdef WIN32
+
+static char *
+skip_drive(const char *path)
+{
+ if (IS_DIR_SEP(path[0]) && IS_DIR_SEP(path[1]))
+ {
+ path += 2;
+ while (*path && !IS_DIR_SEP(*path))
+ path++;
+ }
+ else if (isalpha((unsigned char) path[0]) && path[1] == ':')
+ {
+ path += 2;
+ }
+ return (char *) path;
+}
+#else
+
+#define skip_drive(path) (path)
+#endif
+
+/*
+ * has_drive_prefix
+ *
+ * Return true if the given pathname has a drive prefix.
+ */
+bool
+has_drive_prefix(const char *path)
+{
+#ifdef WIN32
+ return skip_drive(path) != path;
+#else
+ return false;
+#endif
+}
+
+/*
+ * first_dir_separator
+ *
+ * Find the location of the first directory separator, return
+ * NULL if not found.
+ */
+char *
+first_dir_separator(const char *filename)
+{
+ const char *p;
+
+ for (p = skip_drive(filename); *p; p++)
+ if (IS_DIR_SEP(*p))
+ return unconstify(char *, p);
+ return NULL;
+}
+
+/*
+ * first_path_var_separator
+ *
+ * Find the location of the first path separator (i.e. ':' on
+ * Unix, ';' on Windows), return NULL if not found.
+ */
+char *
+first_path_var_separator(const char *pathlist)
+{
+ const char *p;
+
+ /* skip_drive is not needed */
+ for (p = pathlist; *p; p++)
+ if (IS_PATH_VAR_SEP(*p))
+ return unconstify(char *, p);
+ return NULL;
+}
+
+/*
+ * last_dir_separator
+ *
+ * Find the location of the last directory separator, return
+ * NULL if not found.
+ */
+char *
+last_dir_separator(const char *filename)
+{
+ const char *p,
+ *ret = NULL;
+
+ for (p = skip_drive(filename); *p; p++)
+ if (IS_DIR_SEP(*p))
+ ret = p;
+ return unconstify(char *, ret);
+}
+
+
+/*
+ * make_native_path - on WIN32, change / to \ in the path
+ *
+ * This effectively undoes canonicalize_path.
+ *
+ * This is required because WIN32 COPY is an internal CMD.EXE
+ * command and doesn't process forward slashes in the same way
+ * as external commands. Quoting the first argument to COPY
+ * does not convert forward to backward slashes, but COPY does
+ * properly process quoted forward slashes in the second argument.
+ *
+ * COPY works with quoted forward slashes in the first argument
+ * only if the current directory is the same as the directory
+ * of the first argument.
+ */
+void
+make_native_path(char *filename)
+{
+#ifdef WIN32
+ char *p;
+
+ for (p = filename; *p; p++)
+ if (*p == '/')
+ *p = '\\';
+#endif
+}
+
+
+/*
+ * This function cleans up the paths for use with either cmd.exe or Msys
+ * on Windows. We need them to use filenames without spaces, for which a
+ * short filename is the safest equivalent, eg:
+ * C:/Progra~1/
+ */
+void
+cleanup_path(char *path)
+{
+#ifdef WIN32
+ char *ptr;
+
+ /*
+ * GetShortPathName() will fail if the path does not exist, or short names
+ * are disabled on this file system. In both cases, we just return the
+ * original path. This is particularly useful for --sysconfdir, which
+ * might not exist.
+ */
+ GetShortPathName(path, path, MAXPGPATH - 1);
+
+ /* Replace '\' with '/' */
+ for (ptr = path; *ptr; ptr++)
+ {
+ if (*ptr == '\\')
+ *ptr = '/';
+ }
+#endif
+}
+
+
+/*
+ * join_path_components - join two path components, inserting a slash
+ *
+ * We omit the slash if either given component is empty.
+ *
+ * ret_path is the output area (must be of size MAXPGPATH)
+ *
+ * ret_path can be the same as head, but not the same as tail.
+ */
+void
+join_path_components(char *ret_path,
+ const char *head, const char *tail)
+{
+ if (ret_path != head)
+ strlcpy(ret_path, head, MAXPGPATH);
+
+ /*
+ * We used to try to simplify some cases involving "." and "..", but now
+ * we just leave that to be done by canonicalize_path() later.
+ */
+
+ if (*tail)
+ {
+ /* only separate with slash if head wasn't empty */
+ snprintf(ret_path + strlen(ret_path), MAXPGPATH - strlen(ret_path),
+ "%s%s",
+ (*(skip_drive(head)) != '\0') ? "/" : "",
+ tail);
+ }
+}
+
+
+/* State-machine states for canonicalize_path */
+typedef enum
+{
+ ABSOLUTE_PATH_INIT, /* Just past the leading '/' (and Windows
+ * drive name if any) of an absolute path */
+ ABSOLUTE_WITH_N_DEPTH, /* We collected 'pathdepth' directories in an
+ * absolute path */
+ RELATIVE_PATH_INIT, /* At start of a relative path */
+ RELATIVE_WITH_N_DEPTH, /* We collected 'pathdepth' directories in a
+ * relative path */
+ RELATIVE_WITH_PARENT_REF /* Relative path containing only double-dots */
+} canonicalize_state;
+
+/*
+ * Clean up path by:
+ * o make Win32 path use Unix slashes
+ * o remove trailing quote on Win32
+ * o remove trailing slash
+ * o remove duplicate (adjacent) separators
+ * o remove '.' (unless path reduces to only '.')
+ * o process '..' ourselves, removing it if possible
+ */
+void
+canonicalize_path(char *path)
+{
+ char *p,
+ *to_p;
+ char *spath;
+ char *parsed;
+ char *unparse;
+ bool was_sep = false;
+ canonicalize_state state;
+ int pathdepth = 0; /* counts collected regular directory names */
+
+#ifdef WIN32
+
+ /*
+ * The Windows command processor will accept suitably quoted paths with
+ * forward slashes, but barfs badly with mixed forward and back slashes.
+ */
+ for (p = path; *p; p++)
+ {
+ if (*p == '\\')
+ *p = '/';
+ }
+
+ /*
+ * In Win32, if you do: prog.exe "a b" "\c\d\" the system will pass \c\d"
+ * as argv[2], so trim off trailing quote.
+ */
+ if (p > path && *(p - 1) == '"')
+ *(p - 1) = '/';
+#endif
+
+ /*
+ * Removing the trailing slash on a path means we never get ugly double
+ * trailing slashes. Also, Win32 can't stat() a directory with a trailing
+ * slash. Don't remove a leading slash, though.
+ */
+ trim_trailing_separator(path);
+
+ /*
+ * Remove duplicate adjacent separators
+ */
+ p = path;
+#ifdef WIN32
+ /* Don't remove leading double-slash on Win32 */
+ if (*p)
+ p++;
+#endif
+ to_p = p;
+ for (; *p; p++, to_p++)
+ {
+ /* Handle many adjacent slashes, like "/a///b" */
+ while (*p == '/' && was_sep)
+ p++;
+ if (to_p != p)
+ *to_p = *p;
+ was_sep = (*p == '/');
+ }
+ *to_p = '\0';
+
+ /*
+ * Remove any uses of "." and process ".." ourselves
+ *
+ * Note that "/../.." should reduce to just "/", while "../.." has to be
+ * kept as-is. Also note that we want a Windows drive spec to be visible
+ * to trim_directory(), but it's not part of the logic that's looking at
+ * the name components; hence distinction between path and spath.
+ *
+ * This loop overwrites the path in-place. This is safe since we'll never
+ * make the path longer. "unparse" points to where we are reading the
+ * path, "parse" to where we are writing.
+ */
+ spath = skip_drive(path);
+ if (*spath == '\0')
+ return; /* empty path is returned as-is */
+
+ if (*spath == '/')
+ {
+ state = ABSOLUTE_PATH_INIT;
+ /* Skip the leading slash for absolute path */
+ parsed = unparse = (spath + 1);
+ }
+ else
+ {
+ state = RELATIVE_PATH_INIT;
+ parsed = unparse = spath;
+ }
+
+ while (*unparse != '\0')
+ {
+ char *unparse_next;
+ bool is_double_dot;
+
+ /* Split off this dir name, and set unparse_next to the next one */
+ unparse_next = unparse;
+ while (*unparse_next && *unparse_next != '/')
+ unparse_next++;
+ if (*unparse_next != '\0')
+ *unparse_next++ = '\0';
+
+ /* Identify type of this dir name */
+ if (strcmp(unparse, ".") == 0)
+ {
+ /* We can ignore "." components in all cases */
+ unparse = unparse_next;
+ continue;
+ }
+
+ if (strcmp(unparse, "..") == 0)
+ is_double_dot = true;
+ else
+ {
+ /* adjacent separators were eliminated above */
+ Assert(*unparse != '\0');
+ is_double_dot = false;
+ }
+
+ switch (state)
+ {
+ case ABSOLUTE_PATH_INIT:
+ /* We can ignore ".." immediately after / */
+ if (!is_double_dot)
+ {
+ /* Append first dir name (we already have leading slash) */
+ parsed = append_subdir_to_path(parsed, unparse);
+ state = ABSOLUTE_WITH_N_DEPTH;
+ pathdepth++;
+ }
+ break;
+ case ABSOLUTE_WITH_N_DEPTH:
+ if (is_double_dot)
+ {
+ /* Remove last parsed dir */
+ /* (trim_directory won't remove the leading slash) */
+ *parsed = '\0';
+ parsed = trim_directory(path);
+ if (--pathdepth == 0)
+ state = ABSOLUTE_PATH_INIT;
+ }
+ else
+ {
+ /* Append normal dir */
+ *parsed++ = '/';
+ parsed = append_subdir_to_path(parsed, unparse);
+ pathdepth++;
+ }
+ break;
+ case RELATIVE_PATH_INIT:
+ if (is_double_dot)
+ {
+ /* Append irreducible double-dot (..) */
+ parsed = append_subdir_to_path(parsed, unparse);
+ state = RELATIVE_WITH_PARENT_REF;
+ }
+ else
+ {
+ /* Append normal dir */
+ parsed = append_subdir_to_path(parsed, unparse);
+ state = RELATIVE_WITH_N_DEPTH;
+ pathdepth++;
+ }
+ break;
+ case RELATIVE_WITH_N_DEPTH:
+ if (is_double_dot)
+ {
+ /* Remove last parsed dir */
+ *parsed = '\0';
+ parsed = trim_directory(path);
+ if (--pathdepth == 0)
+ {
+ /*
+ * If the output path is now empty, we're back to the
+ * INIT state. However, we could have processed a
+ * path like "../dir/.." and now be down to "..", in
+ * which case enter the correct state for that.
+ */
+ if (parsed == spath)
+ state = RELATIVE_PATH_INIT;
+ else
+ state = RELATIVE_WITH_PARENT_REF;
+ }
+ }
+ else
+ {
+ /* Append normal dir */
+ *parsed++ = '/';
+ parsed = append_subdir_to_path(parsed, unparse);
+ pathdepth++;
+ }
+ break;
+ case RELATIVE_WITH_PARENT_REF:
+ if (is_double_dot)
+ {
+ /* Append next irreducible double-dot (..) */
+ *parsed++ = '/';
+ parsed = append_subdir_to_path(parsed, unparse);
+ }
+ else
+ {
+ /* Append normal dir */
+ *parsed++ = '/';
+ parsed = append_subdir_to_path(parsed, unparse);
+
+ /*
+ * We can now start counting normal dirs. But if later
+ * double-dots make us remove this dir again, we'd better
+ * revert to RELATIVE_WITH_PARENT_REF not INIT state.
+ */
+ state = RELATIVE_WITH_N_DEPTH;
+ pathdepth = 1;
+ }
+ break;
+ }
+
+ unparse = unparse_next;
+ }
+
+ /*
+ * If our output path is empty at this point, insert ".". We don't want
+ * to do this any earlier because it'd result in an extra dot in corner
+ * cases such as "../dir/..". Since we rejected the wholly-empty-path
+ * case above, there is certainly room.
+ */
+ if (parsed == spath)
+ *parsed++ = '.';
+
+ /* And finally, ensure the output path is nul-terminated. */
+ *parsed = '\0';
+}
+
+/*
+ * Detect whether a path contains any parent-directory references ("..")
+ *
+ * The input *must* have been put through canonicalize_path previously.
+ */
+bool
+path_contains_parent_reference(const char *path)
+{
+ /*
+ * Once canonicalized, an absolute path cannot contain any ".." at all,
+ * while a relative path could contain ".."(s) only at the start. So it
+ * is sufficient to check the start of the path, after skipping any
+ * Windows drive/network specifier.
+ */
+ path = skip_drive(path); /* C: shouldn't affect our conclusion */
+
+ if (path[0] == '.' &&
+ path[1] == '.' &&
+ (path[2] == '\0' || path[2] == '/'))
+ return true;
+
+ return false;
+}
+
+/*
+ * Detect whether a path is only in or below the current working directory.
+ *
+ * The input *must* have been put through canonicalize_path previously.
+ *
+ * An absolute path that matches the current working directory should
+ * return false (we only want relative to the cwd).
+ */
+bool
+path_is_relative_and_below_cwd(const char *path)
+{
+ if (is_absolute_path(path))
+ return false;
+ /* don't allow anything above the cwd */
+ else if (path_contains_parent_reference(path))
+ return false;
+#ifdef WIN32
+
+ /*
+ * On Win32, a drive letter _not_ followed by a slash, e.g. 'E:abc', is
+ * relative to the cwd on that drive, or the drive's root directory if
+ * that drive has no cwd. Because the path itself cannot tell us which is
+ * the case, we have to assume the worst, i.e. that it is not below the
+ * cwd. We could use GetFullPathName() to find the full path but that
+ * could change if the current directory for the drive changes underneath
+ * us, so we just disallow it.
+ */
+ else if (isalpha((unsigned char) path[0]) && path[1] == ':' &&
+ !IS_DIR_SEP(path[2]))
+ return false;
+#endif
+ else
+ return true;
+}
+
+/*
+ * Detect whether path1 is a prefix of path2 (including equality).
+ *
+ * This is pretty trivial, but it seems better to export a function than
+ * to export IS_DIR_SEP.
+ */
+bool
+path_is_prefix_of_path(const char *path1, const char *path2)
+{
+ int path1_len = strlen(path1);
+
+ if (strncmp(path1, path2, path1_len) == 0 &&
+ (IS_DIR_SEP(path2[path1_len]) || path2[path1_len] == '\0'))
+ return true;
+ return false;
+}
+
+/*
+ * Extracts the actual name of the program as called -
+ * stripped of .exe suffix if any
+ */
+const char *
+get_progname(const char *argv0)
+{
+ const char *nodir_name;
+ char *progname;
+
+ nodir_name = last_dir_separator(argv0);
+ if (nodir_name)
+ nodir_name++;
+ else
+ nodir_name = skip_drive(argv0);
+
+ /*
+ * Make a copy in case argv[0] is modified by ps_status. Leaks memory, but
+ * called only once.
+ */
+ progname = strdup(nodir_name);
+ if (progname == NULL)
+ {
+ fprintf(stderr, "%s: out of memory\n", nodir_name);
+ abort(); /* This could exit the postmaster */
+ }
+
+#if defined(__CYGWIN__) || defined(WIN32)
+ /* strip ".exe" suffix, regardless of case */
+ if (strlen(progname) > sizeof(EXE) - 1 &&
+ pg_strcasecmp(progname + strlen(progname) - (sizeof(EXE) - 1), EXE) == 0)
+ progname[strlen(progname) - (sizeof(EXE) - 1)] = '\0';
+#endif
+
+ return progname;
+}
+
+
+/*
+ * dir_strcmp: strcmp except any two DIR_SEP characters are considered equal,
+ * and we honor filesystem case insensitivity if known
+ */
+static int
+dir_strcmp(const char *s1, const char *s2)
+{
+ while (*s1 && *s2)
+ {
+ if (
+#ifndef WIN32
+ *s1 != *s2
+#else
+ /* On windows, paths are case-insensitive */
+ pg_tolower((unsigned char) *s1) != pg_tolower((unsigned char) *s2)
+#endif
+ && !(IS_DIR_SEP(*s1) && IS_DIR_SEP(*s2)))
+ return (int) *s1 - (int) *s2;
+ s1++, s2++;
+ }
+ if (*s1)
+ return 1; /* s1 longer */
+ if (*s2)
+ return -1; /* s2 longer */
+ return 0;
+}
+
+
+/*
+ * make_relative_path - make a path relative to the actual binary location
+ *
+ * This function exists to support relocation of installation trees.
+ *
+ * ret_path is the output area (must be of size MAXPGPATH)
+ * target_path is the compiled-in path to the directory we want to find
+ * bin_path is the compiled-in path to the directory of executables
+ * my_exec_path is the actual location of my executable
+ *
+ * We determine the common prefix of target_path and bin_path, then compare
+ * the remainder of bin_path to the last directory component(s) of
+ * my_exec_path. If they match, build the result as the part of my_exec_path
+ * preceding the match, joined to the remainder of target_path. If no match,
+ * return target_path as-is.
+ *
+ * For example:
+ * target_path = '/usr/local/share/postgresql'
+ * bin_path = '/usr/local/bin'
+ * my_exec_path = '/opt/pgsql/bin/postgres'
+ * Given these inputs, the common prefix is '/usr/local/', the tail of
+ * bin_path is 'bin' which does match the last directory component of
+ * my_exec_path, so we would return '/opt/pgsql/share/postgresql'
+ */
+static void
+make_relative_path(char *ret_path, const char *target_path,
+ const char *bin_path, const char *my_exec_path)
+{
+ int prefix_len;
+ int tail_start;
+ int tail_len;
+ int i;
+
+ /*
+ * Determine the common prefix --- note we require it to end on a
+ * directory separator, consider eg '/usr/lib' and '/usr/libexec'.
+ */
+ prefix_len = 0;
+ for (i = 0; target_path[i] && bin_path[i]; i++)
+ {
+ if (IS_DIR_SEP(target_path[i]) && IS_DIR_SEP(bin_path[i]))
+ prefix_len = i + 1;
+ else if (target_path[i] != bin_path[i])
+ break;
+ }
+ if (prefix_len == 0)
+ goto no_match; /* no common prefix? */
+ tail_len = strlen(bin_path) - prefix_len;
+
+ /*
+ * Set up my_exec_path without the actual executable name, and
+ * canonicalize to simplify comparison to bin_path.
+ */
+ strlcpy(ret_path, my_exec_path, MAXPGPATH);
+ trim_directory(ret_path); /* remove my executable name */
+ canonicalize_path(ret_path);
+
+ /*
+ * Tail match?
+ */
+ tail_start = (int) strlen(ret_path) - tail_len;
+ if (tail_start > 0 &&
+ IS_DIR_SEP(ret_path[tail_start - 1]) &&
+ dir_strcmp(ret_path + tail_start, bin_path + prefix_len) == 0)
+ {
+ ret_path[tail_start] = '\0';
+ trim_trailing_separator(ret_path);
+ join_path_components(ret_path, ret_path, target_path + prefix_len);
+ canonicalize_path(ret_path);
+ return;
+ }
+
+no_match:
+ strlcpy(ret_path, target_path, MAXPGPATH);
+ canonicalize_path(ret_path);
+}
+
+
+/*
+ * make_absolute_path
+ *
+ * If the given pathname isn't already absolute, make it so, interpreting
+ * it relative to the current working directory.
+ *
+ * Also canonicalizes the path. The result is always a malloc'd copy.
+ *
+ * In backend, failure cases result in ereport(ERROR); in frontend,
+ * we write a complaint on stderr and return NULL.
+ *
+ * Note: interpretation of relative-path arguments during postmaster startup
+ * should happen before doing ChangeToDataDir(), else the user will probably
+ * not like the results.
+ */
+char *
+make_absolute_path(const char *path)
+{
+ char *new;
+
+ /* Returning null for null input is convenient for some callers */
+ if (path == NULL)
+ return NULL;
+
+ if (!is_absolute_path(path))
+ {
+ char *buf;
+ size_t buflen;
+
+ buflen = MAXPGPATH;
+ for (;;)
+ {
+ buf = malloc(buflen);
+ if (!buf)
+ {
+#ifndef FRONTEND
+ ereport(ERROR,
+ (errcode(ERRCODE_OUT_OF_MEMORY),
+ errmsg("out of memory")));
+#else
+ fprintf(stderr, _("out of memory\n"));
+ return NULL;
+#endif
+ }
+
+ if (getcwd(buf, buflen))
+ break;
+ else if (errno == ERANGE)
+ {
+ free(buf);
+ buflen *= 2;
+ continue;
+ }
+ else
+ {
+ int save_errno = errno;
+
+ free(buf);
+ errno = save_errno;
+#ifndef FRONTEND
+ elog(ERROR, "could not get current working directory: %m");
+#else
+ fprintf(stderr, _("could not get current working directory: %s\n"),
+ strerror(errno));
+ return NULL;
+#endif
+ }
+ }
+
+ new = malloc(strlen(buf) + strlen(path) + 2);
+ if (!new)
+ {
+ free(buf);
+#ifndef FRONTEND
+ ereport(ERROR,
+ (errcode(ERRCODE_OUT_OF_MEMORY),
+ errmsg("out of memory")));
+#else
+ fprintf(stderr, _("out of memory\n"));
+ return NULL;
+#endif
+ }
+ sprintf(new, "%s/%s", buf, path);
+ free(buf);
+ }
+ else
+ {
+ new = strdup(path);
+ if (!new)
+ {
+#ifndef FRONTEND
+ ereport(ERROR,
+ (errcode(ERRCODE_OUT_OF_MEMORY),
+ errmsg("out of memory")));
+#else
+ fprintf(stderr, _("out of memory\n"));
+ return NULL;
+#endif
+ }
+ }
+
+ /* Make sure punctuation is canonical, too */
+ canonicalize_path(new);
+
+ return new;
+}
+
+
+/*
+ * get_share_path
+ */
+void
+get_share_path(const char *my_exec_path, char *ret_path)
+{
+ make_relative_path(ret_path, PGSHAREDIR, PGBINDIR, my_exec_path);
+}
+
+/*
+ * get_etc_path
+ */
+void
+get_etc_path(const char *my_exec_path, char *ret_path)
+{
+ make_relative_path(ret_path, SYSCONFDIR, PGBINDIR, my_exec_path);
+}
+
+/*
+ * get_include_path
+ */
+void
+get_include_path(const char *my_exec_path, char *ret_path)
+{
+ make_relative_path(ret_path, INCLUDEDIR, PGBINDIR, my_exec_path);
+}
+
+/*
+ * get_pkginclude_path
+ */
+void
+get_pkginclude_path(const char *my_exec_path, char *ret_path)
+{
+ make_relative_path(ret_path, PKGINCLUDEDIR, PGBINDIR, my_exec_path);
+}
+
+/*
+ * get_includeserver_path
+ */
+void
+get_includeserver_path(const char *my_exec_path, char *ret_path)
+{
+ make_relative_path(ret_path, INCLUDEDIRSERVER, PGBINDIR, my_exec_path);
+}
+
+/*
+ * get_lib_path
+ */
+void
+get_lib_path(const char *my_exec_path, char *ret_path)
+{
+ make_relative_path(ret_path, LIBDIR, PGBINDIR, my_exec_path);
+}
+
+/*
+ * get_pkglib_path
+ */
+void
+get_pkglib_path(const char *my_exec_path, char *ret_path)
+{
+ make_relative_path(ret_path, PKGLIBDIR, PGBINDIR, my_exec_path);
+}
+
+/*
+ * get_locale_path
+ */
+void
+get_locale_path(const char *my_exec_path, char *ret_path)
+{
+ make_relative_path(ret_path, LOCALEDIR, PGBINDIR, my_exec_path);
+}
+
+/*
+ * get_doc_path
+ */
+void
+get_doc_path(const char *my_exec_path, char *ret_path)
+{
+ make_relative_path(ret_path, DOCDIR, PGBINDIR, my_exec_path);
+}
+
+/*
+ * get_html_path
+ */
+void
+get_html_path(const char *my_exec_path, char *ret_path)
+{
+ make_relative_path(ret_path, HTMLDIR, PGBINDIR, my_exec_path);
+}
+
+/*
+ * get_man_path
+ */
+void
+get_man_path(const char *my_exec_path, char *ret_path)
+{
+ make_relative_path(ret_path, MANDIR, PGBINDIR, my_exec_path);
+}
+
+
+/*
+ * get_home_path
+ *
+ * On Unix, this actually returns the user's home directory. On Windows
+ * it returns the PostgreSQL-specific application data folder.
+ */
+bool
+get_home_path(char *ret_path)
+{
+#ifndef WIN32
+ /*
+ * We first consult $HOME. If that's unset, try to get the info from
+ * <pwd.h>.
+ */
+ const char *home;
+
+ home = getenv("HOME");
+ if (home == NULL || home[0] == '\0')
+ return pg_get_user_home_dir(geteuid(), ret_path, MAXPGPATH);
+ strlcpy(ret_path, home, MAXPGPATH);
+ return true;
+#else
+ char *tmppath;
+
+ /*
+ * Note: We use getenv() here because the more modern SHGetFolderPath()
+ * would force the backend to link with shell32.lib, which eats valuable
+ * desktop heap. XXX This function is used only in psql, which already
+ * brings in shell32 via libpq. Moving this function to its own file
+ * would keep it out of the backend, freeing it from this concern.
+ */
+ tmppath = getenv("APPDATA");
+ if (!tmppath)
+ return false;
+ snprintf(ret_path, MAXPGPATH, "%s/postgresql", tmppath);
+ return true;
+#endif
+}
+
+
+/*
+ * get_parent_directory
+ *
+ * Modify the given string in-place to name the parent directory of the
+ * named file.
+ *
+ * If the input is just a file name with no directory part, the result is
+ * an empty string, not ".". This is appropriate when the next step is
+ * join_path_components(), but might need special handling otherwise.
+ *
+ * Caution: this will not produce desirable results if the string ends
+ * with "..". For most callers this is not a problem since the string
+ * is already known to name a regular file. If in doubt, apply
+ * canonicalize_path() first.
+ */
+void
+get_parent_directory(char *path)
+{
+ trim_directory(path);
+}
+
+
+/*
+ * trim_directory
+ *
+ * Trim trailing directory from path, that is, remove any trailing slashes,
+ * the last pathname component, and the slash just ahead of it --- but never
+ * remove a leading slash.
+ *
+ * For the convenience of canonicalize_path, the path's new end location
+ * is returned.
+ */
+static char *
+trim_directory(char *path)
+{
+ char *p;
+
+ path = skip_drive(path);
+
+ if (path[0] == '\0')
+ return path;
+
+ /* back up over trailing slash(es) */
+ for (p = path + strlen(path) - 1; IS_DIR_SEP(*p) && p > path; p--)
+ ;
+ /* back up over directory name */
+ for (; !IS_DIR_SEP(*p) && p > path; p--)
+ ;
+ /* if multiple slashes before directory name, remove 'em all */
+ for (; p > path && IS_DIR_SEP(*(p - 1)); p--)
+ ;
+ /* don't erase a leading slash */
+ if (p == path && IS_DIR_SEP(*p))
+ p++;
+ *p = '\0';
+ return p;
+}
+
+
+/*
+ * trim_trailing_separator
+ *
+ * trim off trailing slashes, but not a leading slash
+ */
+static void
+trim_trailing_separator(char *path)
+{
+ char *p;
+
+ path = skip_drive(path);
+ p = path + strlen(path);
+ if (p > path)
+ for (p--; p > path && IS_DIR_SEP(*p); p--)
+ *p = '\0';
+}
+
+/*
+ * append_subdir_to_path
+ *
+ * Append the currently-considered subdirectory name to the output
+ * path in canonicalize_path. Return the new end location of the
+ * output path.
+ *
+ * Since canonicalize_path updates the path in-place, we must use
+ * memmove not memcpy, and we don't yet terminate the path with '\0'.
+ */
+static char *
+append_subdir_to_path(char *path, char *subdir)
+{
+ size_t len = strlen(subdir);
+
+ /* No need to copy data if path and subdir are the same. */
+ if (path != subdir)
+ memmove(path, subdir, len);
+
+ return path + len;
+}
diff --git a/contrib/libs/libpq/src/port/pg_bitutils.c b/contrib/libs/libpq/src/port/pg_bitutils.c
new file mode 100644
index 0000000000..1f3dea2d4b
--- /dev/null
+++ b/contrib/libs/libpq/src/port/pg_bitutils.c
@@ -0,0 +1,335 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_bitutils.c
+ * Miscellaneous functions for bit-wise operations.
+ *
+ * Copyright (c) 2019-2023, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/port/pg_bitutils.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "c.h"
+
+#ifdef HAVE__GET_CPUID
+#include <cpuid.h>
+#endif
+#ifdef HAVE__CPUID
+#include <intrin.h>
+#endif
+
+#include "port/pg_bitutils.h"
+
+
+/*
+ * Array giving the position of the left-most set bit for each possible
+ * byte value. We count the right-most position as the 0th bit, and the
+ * left-most the 7th bit. The 0th entry of the array should not be used.
+ *
+ * Note: this is not used by the functions in pg_bitutils.h when
+ * HAVE__BUILTIN_CLZ is defined, but we provide it anyway, so that
+ * extensions possibly compiled with a different compiler can use it.
+ */
+const uint8 pg_leftmost_one_pos[256] = {
+ 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+};
+
+/*
+ * Array giving the position of the right-most set bit for each possible
+ * byte value. We count the right-most position as the 0th bit, and the
+ * left-most the 7th bit. The 0th entry of the array should not be used.
+ *
+ * Note: this is not used by the functions in pg_bitutils.h when
+ * HAVE__BUILTIN_CTZ is defined, but we provide it anyway, so that
+ * extensions possibly compiled with a different compiler can use it.
+ */
+const uint8 pg_rightmost_one_pos[256] = {
+ 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
+};
+
+/*
+ * Array giving the number of 1-bits in each possible byte value.
+ *
+ * Note: we export this for use by functions in which explicit use
+ * of the popcount functions seems unlikely to be a win.
+ */
+const uint8 pg_number_of_ones[256] = {
+ 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
+};
+
+static int pg_popcount32_slow(uint32 word);
+static int pg_popcount64_slow(uint64 word);
+
+#ifdef TRY_POPCNT_FAST
+static bool pg_popcount_available(void);
+static int pg_popcount32_choose(uint32 word);
+static int pg_popcount64_choose(uint64 word);
+static int pg_popcount32_fast(uint32 word);
+static int pg_popcount64_fast(uint64 word);
+
+int (*pg_popcount32) (uint32 word) = pg_popcount32_choose;
+int (*pg_popcount64) (uint64 word) = pg_popcount64_choose;
+#endif /* TRY_POPCNT_FAST */
+
+#ifdef TRY_POPCNT_FAST
+
+/*
+ * Return true if CPUID indicates that the POPCNT instruction is available.
+ */
+static bool
+pg_popcount_available(void)
+{
+ unsigned int exx[4] = {0, 0, 0, 0};
+
+#if defined(HAVE__GET_CPUID)
+ __get_cpuid(1, &exx[0], &exx[1], &exx[2], &exx[3]);
+#elif defined(HAVE__CPUID)
+ __cpuid(exx, 1);
+#else
+#error cpuid instruction not available
+#endif
+
+ return (exx[2] & (1 << 23)) != 0; /* POPCNT */
+}
+
+/*
+ * These functions get called on the first call to pg_popcount32 etc.
+ * They detect whether we can use the asm implementations, and replace
+ * the function pointers so that subsequent calls are routed directly to
+ * the chosen implementation.
+ */
+static int
+pg_popcount32_choose(uint32 word)
+{
+ if (pg_popcount_available())
+ {
+ pg_popcount32 = pg_popcount32_fast;
+ pg_popcount64 = pg_popcount64_fast;
+ }
+ else
+ {
+ pg_popcount32 = pg_popcount32_slow;
+ pg_popcount64 = pg_popcount64_slow;
+ }
+
+ return pg_popcount32(word);
+}
+
+static int
+pg_popcount64_choose(uint64 word)
+{
+ if (pg_popcount_available())
+ {
+ pg_popcount32 = pg_popcount32_fast;
+ pg_popcount64 = pg_popcount64_fast;
+ }
+ else
+ {
+ pg_popcount32 = pg_popcount32_slow;
+ pg_popcount64 = pg_popcount64_slow;
+ }
+
+ return pg_popcount64(word);
+}
+
+/*
+ * pg_popcount32_fast
+ * Return the number of 1 bits set in word
+ */
+static int
+pg_popcount32_fast(uint32 word)
+{
+#ifdef _MSC_VER
+ return __popcnt(word);
+#else
+ uint32 res;
+
+__asm__ __volatile__(" popcntl %1,%0\n":"=q"(res):"rm"(word):"cc");
+ return (int) res;
+#endif
+}
+
+/*
+ * pg_popcount64_fast
+ * Return the number of 1 bits set in word
+ */
+static int
+pg_popcount64_fast(uint64 word)
+{
+#ifdef _MSC_VER
+ return __popcnt64(word);
+#else
+ uint64 res;
+
+__asm__ __volatile__(" popcntq %1,%0\n":"=q"(res):"rm"(word):"cc");
+ return (int) res;
+#endif
+}
+
+#endif /* TRY_POPCNT_FAST */
+
+
+/*
+ * pg_popcount32_slow
+ * Return the number of 1 bits set in word
+ */
+static int
+pg_popcount32_slow(uint32 word)
+{
+#ifdef HAVE__BUILTIN_POPCOUNT
+ return __builtin_popcount(word);
+#else /* !HAVE__BUILTIN_POPCOUNT */
+ int result = 0;
+
+ while (word != 0)
+ {
+ result += pg_number_of_ones[word & 255];
+ word >>= 8;
+ }
+
+ return result;
+#endif /* HAVE__BUILTIN_POPCOUNT */
+}
+
+/*
+ * pg_popcount64_slow
+ * Return the number of 1 bits set in word
+ */
+static int
+pg_popcount64_slow(uint64 word)
+{
+#ifdef HAVE__BUILTIN_POPCOUNT
+#if defined(HAVE_LONG_INT_64)
+ 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
+#endif
+#else /* !HAVE__BUILTIN_POPCOUNT */
+ int result = 0;
+
+ while (word != 0)
+ {
+ result += pg_number_of_ones[word & 255];
+ word >>= 8;
+ }
+
+ return result;
+#endif /* HAVE__BUILTIN_POPCOUNT */
+}
+
+#ifndef TRY_POPCNT_FAST
+
+/*
+ * When the POPCNT instruction is not available, there's no point in using
+ * function pointers to vary the implementation between the fast and slow
+ * method. We instead just make these actual external functions when
+ * TRY_POPCNT_FAST is not defined. The compiler should be able to inline
+ * the slow versions here.
+ */
+int
+pg_popcount32(uint32 word)
+{
+ return pg_popcount32_slow(word);
+}
+
+int
+pg_popcount64(uint64 word)
+{
+ return pg_popcount64_slow(word);
+}
+
+#endif /* !TRY_POPCNT_FAST */
+
+/*
+ * pg_popcount
+ * Returns the number of 1-bits in buf
+ */
+uint64
+pg_popcount(const char *buf, int bytes)
+{
+ uint64 popcnt = 0;
+
+#if SIZEOF_VOID_P >= 8
+ /* Process in 64-bit chunks if the buffer is aligned. */
+ if (buf == (const char *) TYPEALIGN(8, buf))
+ {
+ const uint64 *words = (const uint64 *) buf;
+
+ while (bytes >= 8)
+ {
+ popcnt += pg_popcount64(*words++);
+ bytes -= 8;
+ }
+
+ buf = (const char *) words;
+ }
+#else
+ /* Process in 32-bit chunks if the buffer is aligned. */
+ if (buf == (const char *) TYPEALIGN(4, buf))
+ {
+ const uint32 *words = (const uint32 *) buf;
+
+ while (bytes >= 4)
+ {
+ popcnt += pg_popcount32(*words++);
+ bytes -= 4;
+ }
+
+ buf = (const char *) words;
+ }
+#endif
+
+ /* Process any remaining bytes */
+ while (bytes--)
+ popcnt += pg_number_of_ones[(unsigned char) *buf++];
+
+ return popcnt;
+}
diff --git a/contrib/libs/libpq/src/port/pg_config_paths.h b/contrib/libs/libpq/src/port/pg_config_paths.h
new file mode 100644
index 0000000000..2e2db6a40c
--- /dev/null
+++ b/contrib/libs/libpq/src/port/pg_config_paths.h
@@ -0,0 +1,12 @@
+#define PGBINDIR "/var/empty/postgresql-16.1/bin"
+#define PGSHAREDIR "/var/empty/postgresql-16.1/share"
+#define SYSCONFDIR "/etc/postgresql"
+#define INCLUDEDIR "/var/empty/postgresql-16.1/include"
+#define PKGINCLUDEDIR "/var/empty/postgresql-16.1/include"
+#define INCLUDEDIRSERVER "/var/empty/postgresql-16.1/include/server"
+#define LIBDIR "/var/empty/tmp/out/lib"
+#define PKGLIBDIR "/var/empty/tmp/out/lib/postgresql"
+#define LOCALEDIR "/var/empty/postgresql-16.1/share/locale"
+#define DOCDIR "/var/empty/postgresql-16.1/share/doc/"
+#define HTMLDIR "/var/empty/postgresql-16.1/share/doc/"
+#define MANDIR "/var/empty/postgresql-16.1/share/man"
diff --git a/contrib/libs/libpq/src/port/pg_crc32c_sb8.c b/contrib/libs/libpq/src/port/pg_crc32c_sb8.c
new file mode 100644
index 0000000000..cdd3e05123
--- /dev/null
+++ b/contrib/libs/libpq/src/port/pg_crc32c_sb8.c
@@ -0,0 +1,1169 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_crc32c_sb8.c
+ * Compute CRC-32C checksum using slicing-by-8 algorithm.
+ *
+ * Michael E. Kounavis, Frank L. Berry,
+ * "Novel Table Lookup-Based Algorithms for High-Performance CRC
+ * Generation", IEEE Transactions on Computers, vol.57, no. 11,
+ * pp. 1550-1560, November 2008, doi:10.1109/TC.2008.85
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/port/pg_crc32c_sb8.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "c.h"
+
+#include "port/pg_crc32c.h"
+
+static const uint32 pg_crc32c_table[8][256];
+
+/* Accumulate one input byte */
+#ifdef WORDS_BIGENDIAN
+#define CRC8(x) pg_crc32c_table[0][((crc >> 24) ^ (x)) & 0xFF] ^ (crc << 8)
+#else
+#define CRC8(x) pg_crc32c_table[0][(crc ^ (x)) & 0xFF] ^ (crc >> 8)
+#endif
+
+pg_crc32c
+pg_comp_crc32c_sb8(pg_crc32c crc, const void *data, size_t len)
+{
+ const unsigned char *p = data;
+ const uint32 *p4;
+
+ /*
+ * Handle 0-3 initial bytes one at a time, so that the loop below starts
+ * with a pointer aligned to four bytes.
+ */
+ while (len > 0 && ((uintptr_t) p & 3))
+ {
+ crc = CRC8(*p++);
+ len--;
+ }
+
+ /*
+ * Process eight bytes of data at a time.
+ */
+ p4 = (const uint32 *) p;
+ while (len >= 8)
+ {
+ uint32 a = *p4++ ^ crc;
+ uint32 b = *p4++;
+
+#ifdef WORDS_BIGENDIAN
+ const uint8 c0 = b;
+ const uint8 c1 = b >> 8;
+ const uint8 c2 = b >> 16;
+ const uint8 c3 = b >> 24;
+ const uint8 c4 = a;
+ const uint8 c5 = a >> 8;
+ const uint8 c6 = a >> 16;
+ const uint8 c7 = a >> 24;
+#else
+ const uint8 c0 = b >> 24;
+ const uint8 c1 = b >> 16;
+ const uint8 c2 = b >> 8;
+ const uint8 c3 = b;
+ const uint8 c4 = a >> 24;
+ const uint8 c5 = a >> 16;
+ const uint8 c6 = a >> 8;
+ const uint8 c7 = a;
+#endif
+
+ crc =
+ pg_crc32c_table[0][c0] ^ pg_crc32c_table[1][c1] ^
+ pg_crc32c_table[2][c2] ^ pg_crc32c_table[3][c3] ^
+ pg_crc32c_table[4][c4] ^ pg_crc32c_table[5][c5] ^
+ pg_crc32c_table[6][c6] ^ pg_crc32c_table[7][c7];
+
+ len -= 8;
+ }
+
+ /*
+ * Handle any remaining bytes one at a time.
+ */
+ p = (const unsigned char *) p4;
+ while (len > 0)
+ {
+ crc = CRC8(*p++);
+ len--;
+ }
+
+ return crc;
+}
+
+/*
+ * Lookup tables for the slicing-by-8 algorithm, for the so-called Castagnoli
+ * polynomial (the same that is used e.g. in iSCSI), 0x1EDC6F41. Using
+ * Williams' terms, this is the "normal", not "reflected" version. However, on
+ * big-endian systems the values in the tables are stored in byte-reversed
+ * order (IOW, the tables are stored in little-endian order even on big-endian
+ * systems).
+ */
+static const uint32 pg_crc32c_table[8][256] = {
+#ifndef WORDS_BIGENDIAN
+ {
+ 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,
+ 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
+ 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
+ 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
+ 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B,
+ 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
+ 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54,
+ 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
+ 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,
+ 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
+ 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5,
+ 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
+ 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45,
+ 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
+ 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,
+ 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
+ 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48,
+ 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
+ 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687,
+ 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
+ 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,
+ 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
+ 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8,
+ 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
+ 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096,
+ 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
+ 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,
+ 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
+ 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9,
+ 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
+ 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36,
+ 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
+ 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,
+ 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
+ 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043,
+ 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
+ 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3,
+ 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
+ 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,
+ 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
+ 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652,
+ 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
+ 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D,
+ 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
+ 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,
+ 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
+ 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2,
+ 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
+ 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530,
+ 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
+ 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,
+ 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
+ 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F,
+ 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
+ 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90,
+ 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
+ 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,
+ 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
+ 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,
+ 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
+ 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,
+ 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
+ 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
+ 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351
+ },
+ {
+ 0x00000000, 0x13A29877, 0x274530EE, 0x34E7A899,
+ 0x4E8A61DC, 0x5D28F9AB, 0x69CF5132, 0x7A6DC945,
+ 0x9D14C3B8, 0x8EB65BCF, 0xBA51F356, 0xA9F36B21,
+ 0xD39EA264, 0xC03C3A13, 0xF4DB928A, 0xE7790AFD,
+ 0x3FC5F181, 0x2C6769F6, 0x1880C16F, 0x0B225918,
+ 0x714F905D, 0x62ED082A, 0x560AA0B3, 0x45A838C4,
+ 0xA2D13239, 0xB173AA4E, 0x859402D7, 0x96369AA0,
+ 0xEC5B53E5, 0xFFF9CB92, 0xCB1E630B, 0xD8BCFB7C,
+ 0x7F8BE302, 0x6C297B75, 0x58CED3EC, 0x4B6C4B9B,
+ 0x310182DE, 0x22A31AA9, 0x1644B230, 0x05E62A47,
+ 0xE29F20BA, 0xF13DB8CD, 0xC5DA1054, 0xD6788823,
+ 0xAC154166, 0xBFB7D911, 0x8B507188, 0x98F2E9FF,
+ 0x404E1283, 0x53EC8AF4, 0x670B226D, 0x74A9BA1A,
+ 0x0EC4735F, 0x1D66EB28, 0x298143B1, 0x3A23DBC6,
+ 0xDD5AD13B, 0xCEF8494C, 0xFA1FE1D5, 0xE9BD79A2,
+ 0x93D0B0E7, 0x80722890, 0xB4958009, 0xA737187E,
+ 0xFF17C604, 0xECB55E73, 0xD852F6EA, 0xCBF06E9D,
+ 0xB19DA7D8, 0xA23F3FAF, 0x96D89736, 0x857A0F41,
+ 0x620305BC, 0x71A19DCB, 0x45463552, 0x56E4AD25,
+ 0x2C896460, 0x3F2BFC17, 0x0BCC548E, 0x186ECCF9,
+ 0xC0D23785, 0xD370AFF2, 0xE797076B, 0xF4359F1C,
+ 0x8E585659, 0x9DFACE2E, 0xA91D66B7, 0xBABFFEC0,
+ 0x5DC6F43D, 0x4E646C4A, 0x7A83C4D3, 0x69215CA4,
+ 0x134C95E1, 0x00EE0D96, 0x3409A50F, 0x27AB3D78,
+ 0x809C2506, 0x933EBD71, 0xA7D915E8, 0xB47B8D9F,
+ 0xCE1644DA, 0xDDB4DCAD, 0xE9537434, 0xFAF1EC43,
+ 0x1D88E6BE, 0x0E2A7EC9, 0x3ACDD650, 0x296F4E27,
+ 0x53028762, 0x40A01F15, 0x7447B78C, 0x67E52FFB,
+ 0xBF59D487, 0xACFB4CF0, 0x981CE469, 0x8BBE7C1E,
+ 0xF1D3B55B, 0xE2712D2C, 0xD69685B5, 0xC5341DC2,
+ 0x224D173F, 0x31EF8F48, 0x050827D1, 0x16AABFA6,
+ 0x6CC776E3, 0x7F65EE94, 0x4B82460D, 0x5820DE7A,
+ 0xFBC3FAF9, 0xE861628E, 0xDC86CA17, 0xCF245260,
+ 0xB5499B25, 0xA6EB0352, 0x920CABCB, 0x81AE33BC,
+ 0x66D73941, 0x7575A136, 0x419209AF, 0x523091D8,
+ 0x285D589D, 0x3BFFC0EA, 0x0F186873, 0x1CBAF004,
+ 0xC4060B78, 0xD7A4930F, 0xE3433B96, 0xF0E1A3E1,
+ 0x8A8C6AA4, 0x992EF2D3, 0xADC95A4A, 0xBE6BC23D,
+ 0x5912C8C0, 0x4AB050B7, 0x7E57F82E, 0x6DF56059,
+ 0x1798A91C, 0x043A316B, 0x30DD99F2, 0x237F0185,
+ 0x844819FB, 0x97EA818C, 0xA30D2915, 0xB0AFB162,
+ 0xCAC27827, 0xD960E050, 0xED8748C9, 0xFE25D0BE,
+ 0x195CDA43, 0x0AFE4234, 0x3E19EAAD, 0x2DBB72DA,
+ 0x57D6BB9F, 0x447423E8, 0x70938B71, 0x63311306,
+ 0xBB8DE87A, 0xA82F700D, 0x9CC8D894, 0x8F6A40E3,
+ 0xF50789A6, 0xE6A511D1, 0xD242B948, 0xC1E0213F,
+ 0x26992BC2, 0x353BB3B5, 0x01DC1B2C, 0x127E835B,
+ 0x68134A1E, 0x7BB1D269, 0x4F567AF0, 0x5CF4E287,
+ 0x04D43CFD, 0x1776A48A, 0x23910C13, 0x30339464,
+ 0x4A5E5D21, 0x59FCC556, 0x6D1B6DCF, 0x7EB9F5B8,
+ 0x99C0FF45, 0x8A626732, 0xBE85CFAB, 0xAD2757DC,
+ 0xD74A9E99, 0xC4E806EE, 0xF00FAE77, 0xE3AD3600,
+ 0x3B11CD7C, 0x28B3550B, 0x1C54FD92, 0x0FF665E5,
+ 0x759BACA0, 0x663934D7, 0x52DE9C4E, 0x417C0439,
+ 0xA6050EC4, 0xB5A796B3, 0x81403E2A, 0x92E2A65D,
+ 0xE88F6F18, 0xFB2DF76F, 0xCFCA5FF6, 0xDC68C781,
+ 0x7B5FDFFF, 0x68FD4788, 0x5C1AEF11, 0x4FB87766,
+ 0x35D5BE23, 0x26772654, 0x12908ECD, 0x013216BA,
+ 0xE64B1C47, 0xF5E98430, 0xC10E2CA9, 0xD2ACB4DE,
+ 0xA8C17D9B, 0xBB63E5EC, 0x8F844D75, 0x9C26D502,
+ 0x449A2E7E, 0x5738B609, 0x63DF1E90, 0x707D86E7,
+ 0x0A104FA2, 0x19B2D7D5, 0x2D557F4C, 0x3EF7E73B,
+ 0xD98EEDC6, 0xCA2C75B1, 0xFECBDD28, 0xED69455F,
+ 0x97048C1A, 0x84A6146D, 0xB041BCF4, 0xA3E32483
+ },
+ {
+ 0x00000000, 0xA541927E, 0x4F6F520D, 0xEA2EC073,
+ 0x9EDEA41A, 0x3B9F3664, 0xD1B1F617, 0x74F06469,
+ 0x38513EC5, 0x9D10ACBB, 0x773E6CC8, 0xD27FFEB6,
+ 0xA68F9ADF, 0x03CE08A1, 0xE9E0C8D2, 0x4CA15AAC,
+ 0x70A27D8A, 0xD5E3EFF4, 0x3FCD2F87, 0x9A8CBDF9,
+ 0xEE7CD990, 0x4B3D4BEE, 0xA1138B9D, 0x045219E3,
+ 0x48F3434F, 0xEDB2D131, 0x079C1142, 0xA2DD833C,
+ 0xD62DE755, 0x736C752B, 0x9942B558, 0x3C032726,
+ 0xE144FB14, 0x4405696A, 0xAE2BA919, 0x0B6A3B67,
+ 0x7F9A5F0E, 0xDADBCD70, 0x30F50D03, 0x95B49F7D,
+ 0xD915C5D1, 0x7C5457AF, 0x967A97DC, 0x333B05A2,
+ 0x47CB61CB, 0xE28AF3B5, 0x08A433C6, 0xADE5A1B8,
+ 0x91E6869E, 0x34A714E0, 0xDE89D493, 0x7BC846ED,
+ 0x0F382284, 0xAA79B0FA, 0x40577089, 0xE516E2F7,
+ 0xA9B7B85B, 0x0CF62A25, 0xE6D8EA56, 0x43997828,
+ 0x37691C41, 0x92288E3F, 0x78064E4C, 0xDD47DC32,
+ 0xC76580D9, 0x622412A7, 0x880AD2D4, 0x2D4B40AA,
+ 0x59BB24C3, 0xFCFAB6BD, 0x16D476CE, 0xB395E4B0,
+ 0xFF34BE1C, 0x5A752C62, 0xB05BEC11, 0x151A7E6F,
+ 0x61EA1A06, 0xC4AB8878, 0x2E85480B, 0x8BC4DA75,
+ 0xB7C7FD53, 0x12866F2D, 0xF8A8AF5E, 0x5DE93D20,
+ 0x29195949, 0x8C58CB37, 0x66760B44, 0xC337993A,
+ 0x8F96C396, 0x2AD751E8, 0xC0F9919B, 0x65B803E5,
+ 0x1148678C, 0xB409F5F2, 0x5E273581, 0xFB66A7FF,
+ 0x26217BCD, 0x8360E9B3, 0x694E29C0, 0xCC0FBBBE,
+ 0xB8FFDFD7, 0x1DBE4DA9, 0xF7908DDA, 0x52D11FA4,
+ 0x1E704508, 0xBB31D776, 0x511F1705, 0xF45E857B,
+ 0x80AEE112, 0x25EF736C, 0xCFC1B31F, 0x6A802161,
+ 0x56830647, 0xF3C29439, 0x19EC544A, 0xBCADC634,
+ 0xC85DA25D, 0x6D1C3023, 0x8732F050, 0x2273622E,
+ 0x6ED23882, 0xCB93AAFC, 0x21BD6A8F, 0x84FCF8F1,
+ 0xF00C9C98, 0x554D0EE6, 0xBF63CE95, 0x1A225CEB,
+ 0x8B277743, 0x2E66E53D, 0xC448254E, 0x6109B730,
+ 0x15F9D359, 0xB0B84127, 0x5A968154, 0xFFD7132A,
+ 0xB3764986, 0x1637DBF8, 0xFC191B8B, 0x595889F5,
+ 0x2DA8ED9C, 0x88E97FE2, 0x62C7BF91, 0xC7862DEF,
+ 0xFB850AC9, 0x5EC498B7, 0xB4EA58C4, 0x11ABCABA,
+ 0x655BAED3, 0xC01A3CAD, 0x2A34FCDE, 0x8F756EA0,
+ 0xC3D4340C, 0x6695A672, 0x8CBB6601, 0x29FAF47F,
+ 0x5D0A9016, 0xF84B0268, 0x1265C21B, 0xB7245065,
+ 0x6A638C57, 0xCF221E29, 0x250CDE5A, 0x804D4C24,
+ 0xF4BD284D, 0x51FCBA33, 0xBBD27A40, 0x1E93E83E,
+ 0x5232B292, 0xF77320EC, 0x1D5DE09F, 0xB81C72E1,
+ 0xCCEC1688, 0x69AD84F6, 0x83834485, 0x26C2D6FB,
+ 0x1AC1F1DD, 0xBF8063A3, 0x55AEA3D0, 0xF0EF31AE,
+ 0x841F55C7, 0x215EC7B9, 0xCB7007CA, 0x6E3195B4,
+ 0x2290CF18, 0x87D15D66, 0x6DFF9D15, 0xC8BE0F6B,
+ 0xBC4E6B02, 0x190FF97C, 0xF321390F, 0x5660AB71,
+ 0x4C42F79A, 0xE90365E4, 0x032DA597, 0xA66C37E9,
+ 0xD29C5380, 0x77DDC1FE, 0x9DF3018D, 0x38B293F3,
+ 0x7413C95F, 0xD1525B21, 0x3B7C9B52, 0x9E3D092C,
+ 0xEACD6D45, 0x4F8CFF3B, 0xA5A23F48, 0x00E3AD36,
+ 0x3CE08A10, 0x99A1186E, 0x738FD81D, 0xD6CE4A63,
+ 0xA23E2E0A, 0x077FBC74, 0xED517C07, 0x4810EE79,
+ 0x04B1B4D5, 0xA1F026AB, 0x4BDEE6D8, 0xEE9F74A6,
+ 0x9A6F10CF, 0x3F2E82B1, 0xD50042C2, 0x7041D0BC,
+ 0xAD060C8E, 0x08479EF0, 0xE2695E83, 0x4728CCFD,
+ 0x33D8A894, 0x96993AEA, 0x7CB7FA99, 0xD9F668E7,
+ 0x9557324B, 0x3016A035, 0xDA386046, 0x7F79F238,
+ 0x0B899651, 0xAEC8042F, 0x44E6C45C, 0xE1A75622,
+ 0xDDA47104, 0x78E5E37A, 0x92CB2309, 0x378AB177,
+ 0x437AD51E, 0xE63B4760, 0x0C158713, 0xA954156D,
+ 0xE5F54FC1, 0x40B4DDBF, 0xAA9A1DCC, 0x0FDB8FB2,
+ 0x7B2BEBDB, 0xDE6A79A5, 0x3444B9D6, 0x91052BA8
+ },
+ {
+ 0x00000000, 0xDD45AAB8, 0xBF672381, 0x62228939,
+ 0x7B2231F3, 0xA6679B4B, 0xC4451272, 0x1900B8CA,
+ 0xF64463E6, 0x2B01C95E, 0x49234067, 0x9466EADF,
+ 0x8D665215, 0x5023F8AD, 0x32017194, 0xEF44DB2C,
+ 0xE964B13D, 0x34211B85, 0x560392BC, 0x8B463804,
+ 0x924680CE, 0x4F032A76, 0x2D21A34F, 0xF06409F7,
+ 0x1F20D2DB, 0xC2657863, 0xA047F15A, 0x7D025BE2,
+ 0x6402E328, 0xB9474990, 0xDB65C0A9, 0x06206A11,
+ 0xD725148B, 0x0A60BE33, 0x6842370A, 0xB5079DB2,
+ 0xAC072578, 0x71428FC0, 0x136006F9, 0xCE25AC41,
+ 0x2161776D, 0xFC24DDD5, 0x9E0654EC, 0x4343FE54,
+ 0x5A43469E, 0x8706EC26, 0xE524651F, 0x3861CFA7,
+ 0x3E41A5B6, 0xE3040F0E, 0x81268637, 0x5C632C8F,
+ 0x45639445, 0x98263EFD, 0xFA04B7C4, 0x27411D7C,
+ 0xC805C650, 0x15406CE8, 0x7762E5D1, 0xAA274F69,
+ 0xB327F7A3, 0x6E625D1B, 0x0C40D422, 0xD1057E9A,
+ 0xABA65FE7, 0x76E3F55F, 0x14C17C66, 0xC984D6DE,
+ 0xD0846E14, 0x0DC1C4AC, 0x6FE34D95, 0xB2A6E72D,
+ 0x5DE23C01, 0x80A796B9, 0xE2851F80, 0x3FC0B538,
+ 0x26C00DF2, 0xFB85A74A, 0x99A72E73, 0x44E284CB,
+ 0x42C2EEDA, 0x9F874462, 0xFDA5CD5B, 0x20E067E3,
+ 0x39E0DF29, 0xE4A57591, 0x8687FCA8, 0x5BC25610,
+ 0xB4868D3C, 0x69C32784, 0x0BE1AEBD, 0xD6A40405,
+ 0xCFA4BCCF, 0x12E11677, 0x70C39F4E, 0xAD8635F6,
+ 0x7C834B6C, 0xA1C6E1D4, 0xC3E468ED, 0x1EA1C255,
+ 0x07A17A9F, 0xDAE4D027, 0xB8C6591E, 0x6583F3A6,
+ 0x8AC7288A, 0x57828232, 0x35A00B0B, 0xE8E5A1B3,
+ 0xF1E51979, 0x2CA0B3C1, 0x4E823AF8, 0x93C79040,
+ 0x95E7FA51, 0x48A250E9, 0x2A80D9D0, 0xF7C57368,
+ 0xEEC5CBA2, 0x3380611A, 0x51A2E823, 0x8CE7429B,
+ 0x63A399B7, 0xBEE6330F, 0xDCC4BA36, 0x0181108E,
+ 0x1881A844, 0xC5C402FC, 0xA7E68BC5, 0x7AA3217D,
+ 0x52A0C93F, 0x8FE56387, 0xEDC7EABE, 0x30824006,
+ 0x2982F8CC, 0xF4C75274, 0x96E5DB4D, 0x4BA071F5,
+ 0xA4E4AAD9, 0x79A10061, 0x1B838958, 0xC6C623E0,
+ 0xDFC69B2A, 0x02833192, 0x60A1B8AB, 0xBDE41213,
+ 0xBBC47802, 0x6681D2BA, 0x04A35B83, 0xD9E6F13B,
+ 0xC0E649F1, 0x1DA3E349, 0x7F816A70, 0xA2C4C0C8,
+ 0x4D801BE4, 0x90C5B15C, 0xF2E73865, 0x2FA292DD,
+ 0x36A22A17, 0xEBE780AF, 0x89C50996, 0x5480A32E,
+ 0x8585DDB4, 0x58C0770C, 0x3AE2FE35, 0xE7A7548D,
+ 0xFEA7EC47, 0x23E246FF, 0x41C0CFC6, 0x9C85657E,
+ 0x73C1BE52, 0xAE8414EA, 0xCCA69DD3, 0x11E3376B,
+ 0x08E38FA1, 0xD5A62519, 0xB784AC20, 0x6AC10698,
+ 0x6CE16C89, 0xB1A4C631, 0xD3864F08, 0x0EC3E5B0,
+ 0x17C35D7A, 0xCA86F7C2, 0xA8A47EFB, 0x75E1D443,
+ 0x9AA50F6F, 0x47E0A5D7, 0x25C22CEE, 0xF8878656,
+ 0xE1873E9C, 0x3CC29424, 0x5EE01D1D, 0x83A5B7A5,
+ 0xF90696D8, 0x24433C60, 0x4661B559, 0x9B241FE1,
+ 0x8224A72B, 0x5F610D93, 0x3D4384AA, 0xE0062E12,
+ 0x0F42F53E, 0xD2075F86, 0xB025D6BF, 0x6D607C07,
+ 0x7460C4CD, 0xA9256E75, 0xCB07E74C, 0x16424DF4,
+ 0x106227E5, 0xCD278D5D, 0xAF050464, 0x7240AEDC,
+ 0x6B401616, 0xB605BCAE, 0xD4273597, 0x09629F2F,
+ 0xE6264403, 0x3B63EEBB, 0x59416782, 0x8404CD3A,
+ 0x9D0475F0, 0x4041DF48, 0x22635671, 0xFF26FCC9,
+ 0x2E238253, 0xF36628EB, 0x9144A1D2, 0x4C010B6A,
+ 0x5501B3A0, 0x88441918, 0xEA669021, 0x37233A99,
+ 0xD867E1B5, 0x05224B0D, 0x6700C234, 0xBA45688C,
+ 0xA345D046, 0x7E007AFE, 0x1C22F3C7, 0xC167597F,
+ 0xC747336E, 0x1A0299D6, 0x782010EF, 0xA565BA57,
+ 0xBC65029D, 0x6120A825, 0x0302211C, 0xDE478BA4,
+ 0x31035088, 0xEC46FA30, 0x8E647309, 0x5321D9B1,
+ 0x4A21617B, 0x9764CBC3, 0xF54642FA, 0x2803E842
+ },
+ {
+ 0x00000000, 0x38116FAC, 0x7022DF58, 0x4833B0F4,
+ 0xE045BEB0, 0xD854D11C, 0x906761E8, 0xA8760E44,
+ 0xC5670B91, 0xFD76643D, 0xB545D4C9, 0x8D54BB65,
+ 0x2522B521, 0x1D33DA8D, 0x55006A79, 0x6D1105D5,
+ 0x8F2261D3, 0xB7330E7F, 0xFF00BE8B, 0xC711D127,
+ 0x6F67DF63, 0x5776B0CF, 0x1F45003B, 0x27546F97,
+ 0x4A456A42, 0x725405EE, 0x3A67B51A, 0x0276DAB6,
+ 0xAA00D4F2, 0x9211BB5E, 0xDA220BAA, 0xE2336406,
+ 0x1BA8B557, 0x23B9DAFB, 0x6B8A6A0F, 0x539B05A3,
+ 0xFBED0BE7, 0xC3FC644B, 0x8BCFD4BF, 0xB3DEBB13,
+ 0xDECFBEC6, 0xE6DED16A, 0xAEED619E, 0x96FC0E32,
+ 0x3E8A0076, 0x069B6FDA, 0x4EA8DF2E, 0x76B9B082,
+ 0x948AD484, 0xAC9BBB28, 0xE4A80BDC, 0xDCB96470,
+ 0x74CF6A34, 0x4CDE0598, 0x04EDB56C, 0x3CFCDAC0,
+ 0x51EDDF15, 0x69FCB0B9, 0x21CF004D, 0x19DE6FE1,
+ 0xB1A861A5, 0x89B90E09, 0xC18ABEFD, 0xF99BD151,
+ 0x37516AAE, 0x0F400502, 0x4773B5F6, 0x7F62DA5A,
+ 0xD714D41E, 0xEF05BBB2, 0xA7360B46, 0x9F2764EA,
+ 0xF236613F, 0xCA270E93, 0x8214BE67, 0xBA05D1CB,
+ 0x1273DF8F, 0x2A62B023, 0x625100D7, 0x5A406F7B,
+ 0xB8730B7D, 0x806264D1, 0xC851D425, 0xF040BB89,
+ 0x5836B5CD, 0x6027DA61, 0x28146A95, 0x10050539,
+ 0x7D1400EC, 0x45056F40, 0x0D36DFB4, 0x3527B018,
+ 0x9D51BE5C, 0xA540D1F0, 0xED736104, 0xD5620EA8,
+ 0x2CF9DFF9, 0x14E8B055, 0x5CDB00A1, 0x64CA6F0D,
+ 0xCCBC6149, 0xF4AD0EE5, 0xBC9EBE11, 0x848FD1BD,
+ 0xE99ED468, 0xD18FBBC4, 0x99BC0B30, 0xA1AD649C,
+ 0x09DB6AD8, 0x31CA0574, 0x79F9B580, 0x41E8DA2C,
+ 0xA3DBBE2A, 0x9BCAD186, 0xD3F96172, 0xEBE80EDE,
+ 0x439E009A, 0x7B8F6F36, 0x33BCDFC2, 0x0BADB06E,
+ 0x66BCB5BB, 0x5EADDA17, 0x169E6AE3, 0x2E8F054F,
+ 0x86F90B0B, 0xBEE864A7, 0xF6DBD453, 0xCECABBFF,
+ 0x6EA2D55C, 0x56B3BAF0, 0x1E800A04, 0x269165A8,
+ 0x8EE76BEC, 0xB6F60440, 0xFEC5B4B4, 0xC6D4DB18,
+ 0xABC5DECD, 0x93D4B161, 0xDBE70195, 0xE3F66E39,
+ 0x4B80607D, 0x73910FD1, 0x3BA2BF25, 0x03B3D089,
+ 0xE180B48F, 0xD991DB23, 0x91A26BD7, 0xA9B3047B,
+ 0x01C50A3F, 0x39D46593, 0x71E7D567, 0x49F6BACB,
+ 0x24E7BF1E, 0x1CF6D0B2, 0x54C56046, 0x6CD40FEA,
+ 0xC4A201AE, 0xFCB36E02, 0xB480DEF6, 0x8C91B15A,
+ 0x750A600B, 0x4D1B0FA7, 0x0528BF53, 0x3D39D0FF,
+ 0x954FDEBB, 0xAD5EB117, 0xE56D01E3, 0xDD7C6E4F,
+ 0xB06D6B9A, 0x887C0436, 0xC04FB4C2, 0xF85EDB6E,
+ 0x5028D52A, 0x6839BA86, 0x200A0A72, 0x181B65DE,
+ 0xFA2801D8, 0xC2396E74, 0x8A0ADE80, 0xB21BB12C,
+ 0x1A6DBF68, 0x227CD0C4, 0x6A4F6030, 0x525E0F9C,
+ 0x3F4F0A49, 0x075E65E5, 0x4F6DD511, 0x777CBABD,
+ 0xDF0AB4F9, 0xE71BDB55, 0xAF286BA1, 0x9739040D,
+ 0x59F3BFF2, 0x61E2D05E, 0x29D160AA, 0x11C00F06,
+ 0xB9B60142, 0x81A76EEE, 0xC994DE1A, 0xF185B1B6,
+ 0x9C94B463, 0xA485DBCF, 0xECB66B3B, 0xD4A70497,
+ 0x7CD10AD3, 0x44C0657F, 0x0CF3D58B, 0x34E2BA27,
+ 0xD6D1DE21, 0xEEC0B18D, 0xA6F30179, 0x9EE26ED5,
+ 0x36946091, 0x0E850F3D, 0x46B6BFC9, 0x7EA7D065,
+ 0x13B6D5B0, 0x2BA7BA1C, 0x63940AE8, 0x5B856544,
+ 0xF3F36B00, 0xCBE204AC, 0x83D1B458, 0xBBC0DBF4,
+ 0x425B0AA5, 0x7A4A6509, 0x3279D5FD, 0x0A68BA51,
+ 0xA21EB415, 0x9A0FDBB9, 0xD23C6B4D, 0xEA2D04E1,
+ 0x873C0134, 0xBF2D6E98, 0xF71EDE6C, 0xCF0FB1C0,
+ 0x6779BF84, 0x5F68D028, 0x175B60DC, 0x2F4A0F70,
+ 0xCD796B76, 0xF56804DA, 0xBD5BB42E, 0x854ADB82,
+ 0x2D3CD5C6, 0x152DBA6A, 0x5D1E0A9E, 0x650F6532,
+ 0x081E60E7, 0x300F0F4B, 0x783CBFBF, 0x402DD013,
+ 0xE85BDE57, 0xD04AB1FB, 0x9879010F, 0xA0686EA3
+ },
+ {
+ 0x00000000, 0xEF306B19, 0xDB8CA0C3, 0x34BCCBDA,
+ 0xB2F53777, 0x5DC55C6E, 0x697997B4, 0x8649FCAD,
+ 0x6006181F, 0x8F367306, 0xBB8AB8DC, 0x54BAD3C5,
+ 0xD2F32F68, 0x3DC34471, 0x097F8FAB, 0xE64FE4B2,
+ 0xC00C303E, 0x2F3C5B27, 0x1B8090FD, 0xF4B0FBE4,
+ 0x72F90749, 0x9DC96C50, 0xA975A78A, 0x4645CC93,
+ 0xA00A2821, 0x4F3A4338, 0x7B8688E2, 0x94B6E3FB,
+ 0x12FF1F56, 0xFDCF744F, 0xC973BF95, 0x2643D48C,
+ 0x85F4168D, 0x6AC47D94, 0x5E78B64E, 0xB148DD57,
+ 0x370121FA, 0xD8314AE3, 0xEC8D8139, 0x03BDEA20,
+ 0xE5F20E92, 0x0AC2658B, 0x3E7EAE51, 0xD14EC548,
+ 0x570739E5, 0xB83752FC, 0x8C8B9926, 0x63BBF23F,
+ 0x45F826B3, 0xAAC84DAA, 0x9E748670, 0x7144ED69,
+ 0xF70D11C4, 0x183D7ADD, 0x2C81B107, 0xC3B1DA1E,
+ 0x25FE3EAC, 0xCACE55B5, 0xFE729E6F, 0x1142F576,
+ 0x970B09DB, 0x783B62C2, 0x4C87A918, 0xA3B7C201,
+ 0x0E045BEB, 0xE13430F2, 0xD588FB28, 0x3AB89031,
+ 0xBCF16C9C, 0x53C10785, 0x677DCC5F, 0x884DA746,
+ 0x6E0243F4, 0x813228ED, 0xB58EE337, 0x5ABE882E,
+ 0xDCF77483, 0x33C71F9A, 0x077BD440, 0xE84BBF59,
+ 0xCE086BD5, 0x213800CC, 0x1584CB16, 0xFAB4A00F,
+ 0x7CFD5CA2, 0x93CD37BB, 0xA771FC61, 0x48419778,
+ 0xAE0E73CA, 0x413E18D3, 0x7582D309, 0x9AB2B810,
+ 0x1CFB44BD, 0xF3CB2FA4, 0xC777E47E, 0x28478F67,
+ 0x8BF04D66, 0x64C0267F, 0x507CEDA5, 0xBF4C86BC,
+ 0x39057A11, 0xD6351108, 0xE289DAD2, 0x0DB9B1CB,
+ 0xEBF65579, 0x04C63E60, 0x307AF5BA, 0xDF4A9EA3,
+ 0x5903620E, 0xB6330917, 0x828FC2CD, 0x6DBFA9D4,
+ 0x4BFC7D58, 0xA4CC1641, 0x9070DD9B, 0x7F40B682,
+ 0xF9094A2F, 0x16392136, 0x2285EAEC, 0xCDB581F5,
+ 0x2BFA6547, 0xC4CA0E5E, 0xF076C584, 0x1F46AE9D,
+ 0x990F5230, 0x763F3929, 0x4283F2F3, 0xADB399EA,
+ 0x1C08B7D6, 0xF338DCCF, 0xC7841715, 0x28B47C0C,
+ 0xAEFD80A1, 0x41CDEBB8, 0x75712062, 0x9A414B7B,
+ 0x7C0EAFC9, 0x933EC4D0, 0xA7820F0A, 0x48B26413,
+ 0xCEFB98BE, 0x21CBF3A7, 0x1577387D, 0xFA475364,
+ 0xDC0487E8, 0x3334ECF1, 0x0788272B, 0xE8B84C32,
+ 0x6EF1B09F, 0x81C1DB86, 0xB57D105C, 0x5A4D7B45,
+ 0xBC029FF7, 0x5332F4EE, 0x678E3F34, 0x88BE542D,
+ 0x0EF7A880, 0xE1C7C399, 0xD57B0843, 0x3A4B635A,
+ 0x99FCA15B, 0x76CCCA42, 0x42700198, 0xAD406A81,
+ 0x2B09962C, 0xC439FD35, 0xF08536EF, 0x1FB55DF6,
+ 0xF9FAB944, 0x16CAD25D, 0x22761987, 0xCD46729E,
+ 0x4B0F8E33, 0xA43FE52A, 0x90832EF0, 0x7FB345E9,
+ 0x59F09165, 0xB6C0FA7C, 0x827C31A6, 0x6D4C5ABF,
+ 0xEB05A612, 0x0435CD0B, 0x308906D1, 0xDFB96DC8,
+ 0x39F6897A, 0xD6C6E263, 0xE27A29B9, 0x0D4A42A0,
+ 0x8B03BE0D, 0x6433D514, 0x508F1ECE, 0xBFBF75D7,
+ 0x120CEC3D, 0xFD3C8724, 0xC9804CFE, 0x26B027E7,
+ 0xA0F9DB4A, 0x4FC9B053, 0x7B757B89, 0x94451090,
+ 0x720AF422, 0x9D3A9F3B, 0xA98654E1, 0x46B63FF8,
+ 0xC0FFC355, 0x2FCFA84C, 0x1B736396, 0xF443088F,
+ 0xD200DC03, 0x3D30B71A, 0x098C7CC0, 0xE6BC17D9,
+ 0x60F5EB74, 0x8FC5806D, 0xBB794BB7, 0x544920AE,
+ 0xB206C41C, 0x5D36AF05, 0x698A64DF, 0x86BA0FC6,
+ 0x00F3F36B, 0xEFC39872, 0xDB7F53A8, 0x344F38B1,
+ 0x97F8FAB0, 0x78C891A9, 0x4C745A73, 0xA344316A,
+ 0x250DCDC7, 0xCA3DA6DE, 0xFE816D04, 0x11B1061D,
+ 0xF7FEE2AF, 0x18CE89B6, 0x2C72426C, 0xC3422975,
+ 0x450BD5D8, 0xAA3BBEC1, 0x9E87751B, 0x71B71E02,
+ 0x57F4CA8E, 0xB8C4A197, 0x8C786A4D, 0x63480154,
+ 0xE501FDF9, 0x0A3196E0, 0x3E8D5D3A, 0xD1BD3623,
+ 0x37F2D291, 0xD8C2B988, 0xEC7E7252, 0x034E194B,
+ 0x8507E5E6, 0x6A378EFF, 0x5E8B4525, 0xB1BB2E3C
+ },
+ {
+ 0x00000000, 0x68032CC8, 0xD0065990, 0xB8057558,
+ 0xA5E0C5D1, 0xCDE3E919, 0x75E69C41, 0x1DE5B089,
+ 0x4E2DFD53, 0x262ED19B, 0x9E2BA4C3, 0xF628880B,
+ 0xEBCD3882, 0x83CE144A, 0x3BCB6112, 0x53C84DDA,
+ 0x9C5BFAA6, 0xF458D66E, 0x4C5DA336, 0x245E8FFE,
+ 0x39BB3F77, 0x51B813BF, 0xE9BD66E7, 0x81BE4A2F,
+ 0xD27607F5, 0xBA752B3D, 0x02705E65, 0x6A7372AD,
+ 0x7796C224, 0x1F95EEEC, 0xA7909BB4, 0xCF93B77C,
+ 0x3D5B83BD, 0x5558AF75, 0xED5DDA2D, 0x855EF6E5,
+ 0x98BB466C, 0xF0B86AA4, 0x48BD1FFC, 0x20BE3334,
+ 0x73767EEE, 0x1B755226, 0xA370277E, 0xCB730BB6,
+ 0xD696BB3F, 0xBE9597F7, 0x0690E2AF, 0x6E93CE67,
+ 0xA100791B, 0xC90355D3, 0x7106208B, 0x19050C43,
+ 0x04E0BCCA, 0x6CE39002, 0xD4E6E55A, 0xBCE5C992,
+ 0xEF2D8448, 0x872EA880, 0x3F2BDDD8, 0x5728F110,
+ 0x4ACD4199, 0x22CE6D51, 0x9ACB1809, 0xF2C834C1,
+ 0x7AB7077A, 0x12B42BB2, 0xAAB15EEA, 0xC2B27222,
+ 0xDF57C2AB, 0xB754EE63, 0x0F519B3B, 0x6752B7F3,
+ 0x349AFA29, 0x5C99D6E1, 0xE49CA3B9, 0x8C9F8F71,
+ 0x917A3FF8, 0xF9791330, 0x417C6668, 0x297F4AA0,
+ 0xE6ECFDDC, 0x8EEFD114, 0x36EAA44C, 0x5EE98884,
+ 0x430C380D, 0x2B0F14C5, 0x930A619D, 0xFB094D55,
+ 0xA8C1008F, 0xC0C22C47, 0x78C7591F, 0x10C475D7,
+ 0x0D21C55E, 0x6522E996, 0xDD279CCE, 0xB524B006,
+ 0x47EC84C7, 0x2FEFA80F, 0x97EADD57, 0xFFE9F19F,
+ 0xE20C4116, 0x8A0F6DDE, 0x320A1886, 0x5A09344E,
+ 0x09C17994, 0x61C2555C, 0xD9C72004, 0xB1C40CCC,
+ 0xAC21BC45, 0xC422908D, 0x7C27E5D5, 0x1424C91D,
+ 0xDBB77E61, 0xB3B452A9, 0x0BB127F1, 0x63B20B39,
+ 0x7E57BBB0, 0x16549778, 0xAE51E220, 0xC652CEE8,
+ 0x959A8332, 0xFD99AFFA, 0x459CDAA2, 0x2D9FF66A,
+ 0x307A46E3, 0x58796A2B, 0xE07C1F73, 0x887F33BB,
+ 0xF56E0EF4, 0x9D6D223C, 0x25685764, 0x4D6B7BAC,
+ 0x508ECB25, 0x388DE7ED, 0x808892B5, 0xE88BBE7D,
+ 0xBB43F3A7, 0xD340DF6F, 0x6B45AA37, 0x034686FF,
+ 0x1EA33676, 0x76A01ABE, 0xCEA56FE6, 0xA6A6432E,
+ 0x6935F452, 0x0136D89A, 0xB933ADC2, 0xD130810A,
+ 0xCCD53183, 0xA4D61D4B, 0x1CD36813, 0x74D044DB,
+ 0x27180901, 0x4F1B25C9, 0xF71E5091, 0x9F1D7C59,
+ 0x82F8CCD0, 0xEAFBE018, 0x52FE9540, 0x3AFDB988,
+ 0xC8358D49, 0xA036A181, 0x1833D4D9, 0x7030F811,
+ 0x6DD54898, 0x05D66450, 0xBDD31108, 0xD5D03DC0,
+ 0x8618701A, 0xEE1B5CD2, 0x561E298A, 0x3E1D0542,
+ 0x23F8B5CB, 0x4BFB9903, 0xF3FEEC5B, 0x9BFDC093,
+ 0x546E77EF, 0x3C6D5B27, 0x84682E7F, 0xEC6B02B7,
+ 0xF18EB23E, 0x998D9EF6, 0x2188EBAE, 0x498BC766,
+ 0x1A438ABC, 0x7240A674, 0xCA45D32C, 0xA246FFE4,
+ 0xBFA34F6D, 0xD7A063A5, 0x6FA516FD, 0x07A63A35,
+ 0x8FD9098E, 0xE7DA2546, 0x5FDF501E, 0x37DC7CD6,
+ 0x2A39CC5F, 0x423AE097, 0xFA3F95CF, 0x923CB907,
+ 0xC1F4F4DD, 0xA9F7D815, 0x11F2AD4D, 0x79F18185,
+ 0x6414310C, 0x0C171DC4, 0xB412689C, 0xDC114454,
+ 0x1382F328, 0x7B81DFE0, 0xC384AAB8, 0xAB878670,
+ 0xB66236F9, 0xDE611A31, 0x66646F69, 0x0E6743A1,
+ 0x5DAF0E7B, 0x35AC22B3, 0x8DA957EB, 0xE5AA7B23,
+ 0xF84FCBAA, 0x904CE762, 0x2849923A, 0x404ABEF2,
+ 0xB2828A33, 0xDA81A6FB, 0x6284D3A3, 0x0A87FF6B,
+ 0x17624FE2, 0x7F61632A, 0xC7641672, 0xAF673ABA,
+ 0xFCAF7760, 0x94AC5BA8, 0x2CA92EF0, 0x44AA0238,
+ 0x594FB2B1, 0x314C9E79, 0x8949EB21, 0xE14AC7E9,
+ 0x2ED97095, 0x46DA5C5D, 0xFEDF2905, 0x96DC05CD,
+ 0x8B39B544, 0xE33A998C, 0x5B3FECD4, 0x333CC01C,
+ 0x60F48DC6, 0x08F7A10E, 0xB0F2D456, 0xD8F1F89E,
+ 0xC5144817, 0xAD1764DF, 0x15121187, 0x7D113D4F
+ },
+ {
+ 0x00000000, 0x493C7D27, 0x9278FA4E, 0xDB448769,
+ 0x211D826D, 0x6821FF4A, 0xB3657823, 0xFA590504,
+ 0x423B04DA, 0x0B0779FD, 0xD043FE94, 0x997F83B3,
+ 0x632686B7, 0x2A1AFB90, 0xF15E7CF9, 0xB86201DE,
+ 0x847609B4, 0xCD4A7493, 0x160EF3FA, 0x5F328EDD,
+ 0xA56B8BD9, 0xEC57F6FE, 0x37137197, 0x7E2F0CB0,
+ 0xC64D0D6E, 0x8F717049, 0x5435F720, 0x1D098A07,
+ 0xE7508F03, 0xAE6CF224, 0x7528754D, 0x3C14086A,
+ 0x0D006599, 0x443C18BE, 0x9F789FD7, 0xD644E2F0,
+ 0x2C1DE7F4, 0x65219AD3, 0xBE651DBA, 0xF759609D,
+ 0x4F3B6143, 0x06071C64, 0xDD439B0D, 0x947FE62A,
+ 0x6E26E32E, 0x271A9E09, 0xFC5E1960, 0xB5626447,
+ 0x89766C2D, 0xC04A110A, 0x1B0E9663, 0x5232EB44,
+ 0xA86BEE40, 0xE1579367, 0x3A13140E, 0x732F6929,
+ 0xCB4D68F7, 0x827115D0, 0x593592B9, 0x1009EF9E,
+ 0xEA50EA9A, 0xA36C97BD, 0x782810D4, 0x31146DF3,
+ 0x1A00CB32, 0x533CB615, 0x8878317C, 0xC1444C5B,
+ 0x3B1D495F, 0x72213478, 0xA965B311, 0xE059CE36,
+ 0x583BCFE8, 0x1107B2CF, 0xCA4335A6, 0x837F4881,
+ 0x79264D85, 0x301A30A2, 0xEB5EB7CB, 0xA262CAEC,
+ 0x9E76C286, 0xD74ABFA1, 0x0C0E38C8, 0x453245EF,
+ 0xBF6B40EB, 0xF6573DCC, 0x2D13BAA5, 0x642FC782,
+ 0xDC4DC65C, 0x9571BB7B, 0x4E353C12, 0x07094135,
+ 0xFD504431, 0xB46C3916, 0x6F28BE7F, 0x2614C358,
+ 0x1700AEAB, 0x5E3CD38C, 0x857854E5, 0xCC4429C2,
+ 0x361D2CC6, 0x7F2151E1, 0xA465D688, 0xED59ABAF,
+ 0x553BAA71, 0x1C07D756, 0xC743503F, 0x8E7F2D18,
+ 0x7426281C, 0x3D1A553B, 0xE65ED252, 0xAF62AF75,
+ 0x9376A71F, 0xDA4ADA38, 0x010E5D51, 0x48322076,
+ 0xB26B2572, 0xFB575855, 0x2013DF3C, 0x692FA21B,
+ 0xD14DA3C5, 0x9871DEE2, 0x4335598B, 0x0A0924AC,
+ 0xF05021A8, 0xB96C5C8F, 0x6228DBE6, 0x2B14A6C1,
+ 0x34019664, 0x7D3DEB43, 0xA6796C2A, 0xEF45110D,
+ 0x151C1409, 0x5C20692E, 0x8764EE47, 0xCE589360,
+ 0x763A92BE, 0x3F06EF99, 0xE44268F0, 0xAD7E15D7,
+ 0x572710D3, 0x1E1B6DF4, 0xC55FEA9D, 0x8C6397BA,
+ 0xB0779FD0, 0xF94BE2F7, 0x220F659E, 0x6B3318B9,
+ 0x916A1DBD, 0xD856609A, 0x0312E7F3, 0x4A2E9AD4,
+ 0xF24C9B0A, 0xBB70E62D, 0x60346144, 0x29081C63,
+ 0xD3511967, 0x9A6D6440, 0x4129E329, 0x08159E0E,
+ 0x3901F3FD, 0x703D8EDA, 0xAB7909B3, 0xE2457494,
+ 0x181C7190, 0x51200CB7, 0x8A648BDE, 0xC358F6F9,
+ 0x7B3AF727, 0x32068A00, 0xE9420D69, 0xA07E704E,
+ 0x5A27754A, 0x131B086D, 0xC85F8F04, 0x8163F223,
+ 0xBD77FA49, 0xF44B876E, 0x2F0F0007, 0x66337D20,
+ 0x9C6A7824, 0xD5560503, 0x0E12826A, 0x472EFF4D,
+ 0xFF4CFE93, 0xB67083B4, 0x6D3404DD, 0x240879FA,
+ 0xDE517CFE, 0x976D01D9, 0x4C2986B0, 0x0515FB97,
+ 0x2E015D56, 0x673D2071, 0xBC79A718, 0xF545DA3F,
+ 0x0F1CDF3B, 0x4620A21C, 0x9D642575, 0xD4585852,
+ 0x6C3A598C, 0x250624AB, 0xFE42A3C2, 0xB77EDEE5,
+ 0x4D27DBE1, 0x041BA6C6, 0xDF5F21AF, 0x96635C88,
+ 0xAA7754E2, 0xE34B29C5, 0x380FAEAC, 0x7133D38B,
+ 0x8B6AD68F, 0xC256ABA8, 0x19122CC1, 0x502E51E6,
+ 0xE84C5038, 0xA1702D1F, 0x7A34AA76, 0x3308D751,
+ 0xC951D255, 0x806DAF72, 0x5B29281B, 0x1215553C,
+ 0x230138CF, 0x6A3D45E8, 0xB179C281, 0xF845BFA6,
+ 0x021CBAA2, 0x4B20C785, 0x906440EC, 0xD9583DCB,
+ 0x613A3C15, 0x28064132, 0xF342C65B, 0xBA7EBB7C,
+ 0x4027BE78, 0x091BC35F, 0xD25F4436, 0x9B633911,
+ 0xA777317B, 0xEE4B4C5C, 0x350FCB35, 0x7C33B612,
+ 0x866AB316, 0xCF56CE31, 0x14124958, 0x5D2E347F,
+ 0xE54C35A1, 0xAC704886, 0x7734CFEF, 0x3E08B2C8,
+ 0xC451B7CC, 0x8D6DCAEB, 0x56294D82, 0x1F1530A5
+ }
+#else /* !WORDS_BIGENDIAN */
+ {
+ 0x00000000, 0x03836BF2, 0xF7703BE1, 0xF4F35013,
+ 0x1F979AC7, 0x1C14F135, 0xE8E7A126, 0xEB64CAD4,
+ 0xCF58D98A, 0xCCDBB278, 0x3828E26B, 0x3BAB8999,
+ 0xD0CF434D, 0xD34C28BF, 0x27BF78AC, 0x243C135E,
+ 0x6FC75E10, 0x6C4435E2, 0x98B765F1, 0x9B340E03,
+ 0x7050C4D7, 0x73D3AF25, 0x8720FF36, 0x84A394C4,
+ 0xA09F879A, 0xA31CEC68, 0x57EFBC7B, 0x546CD789,
+ 0xBF081D5D, 0xBC8B76AF, 0x487826BC, 0x4BFB4D4E,
+ 0xDE8EBD20, 0xDD0DD6D2, 0x29FE86C1, 0x2A7DED33,
+ 0xC11927E7, 0xC29A4C15, 0x36691C06, 0x35EA77F4,
+ 0x11D664AA, 0x12550F58, 0xE6A65F4B, 0xE52534B9,
+ 0x0E41FE6D, 0x0DC2959F, 0xF931C58C, 0xFAB2AE7E,
+ 0xB149E330, 0xB2CA88C2, 0x4639D8D1, 0x45BAB323,
+ 0xAEDE79F7, 0xAD5D1205, 0x59AE4216, 0x5A2D29E4,
+ 0x7E113ABA, 0x7D925148, 0x8961015B, 0x8AE26AA9,
+ 0x6186A07D, 0x6205CB8F, 0x96F69B9C, 0x9575F06E,
+ 0xBC1D7B41, 0xBF9E10B3, 0x4B6D40A0, 0x48EE2B52,
+ 0xA38AE186, 0xA0098A74, 0x54FADA67, 0x5779B195,
+ 0x7345A2CB, 0x70C6C939, 0x8435992A, 0x87B6F2D8,
+ 0x6CD2380C, 0x6F5153FE, 0x9BA203ED, 0x9821681F,
+ 0xD3DA2551, 0xD0594EA3, 0x24AA1EB0, 0x27297542,
+ 0xCC4DBF96, 0xCFCED464, 0x3B3D8477, 0x38BEEF85,
+ 0x1C82FCDB, 0x1F019729, 0xEBF2C73A, 0xE871ACC8,
+ 0x0315661C, 0x00960DEE, 0xF4655DFD, 0xF7E6360F,
+ 0x6293C661, 0x6110AD93, 0x95E3FD80, 0x96609672,
+ 0x7D045CA6, 0x7E873754, 0x8A746747, 0x89F70CB5,
+ 0xADCB1FEB, 0xAE487419, 0x5ABB240A, 0x59384FF8,
+ 0xB25C852C, 0xB1DFEEDE, 0x452CBECD, 0x46AFD53F,
+ 0x0D549871, 0x0ED7F383, 0xFA24A390, 0xF9A7C862,
+ 0x12C302B6, 0x11406944, 0xE5B33957, 0xE63052A5,
+ 0xC20C41FB, 0xC18F2A09, 0x357C7A1A, 0x36FF11E8,
+ 0xDD9BDB3C, 0xDE18B0CE, 0x2AEBE0DD, 0x29688B2F,
+ 0x783BF682, 0x7BB89D70, 0x8F4BCD63, 0x8CC8A691,
+ 0x67AC6C45, 0x642F07B7, 0x90DC57A4, 0x935F3C56,
+ 0xB7632F08, 0xB4E044FA, 0x401314E9, 0x43907F1B,
+ 0xA8F4B5CF, 0xAB77DE3D, 0x5F848E2E, 0x5C07E5DC,
+ 0x17FCA892, 0x147FC360, 0xE08C9373, 0xE30FF881,
+ 0x086B3255, 0x0BE859A7, 0xFF1B09B4, 0xFC986246,
+ 0xD8A47118, 0xDB271AEA, 0x2FD44AF9, 0x2C57210B,
+ 0xC733EBDF, 0xC4B0802D, 0x3043D03E, 0x33C0BBCC,
+ 0xA6B54BA2, 0xA5362050, 0x51C57043, 0x52461BB1,
+ 0xB922D165, 0xBAA1BA97, 0x4E52EA84, 0x4DD18176,
+ 0x69ED9228, 0x6A6EF9DA, 0x9E9DA9C9, 0x9D1EC23B,
+ 0x767A08EF, 0x75F9631D, 0x810A330E, 0x828958FC,
+ 0xC97215B2, 0xCAF17E40, 0x3E022E53, 0x3D8145A1,
+ 0xD6E58F75, 0xD566E487, 0x2195B494, 0x2216DF66,
+ 0x062ACC38, 0x05A9A7CA, 0xF15AF7D9, 0xF2D99C2B,
+ 0x19BD56FF, 0x1A3E3D0D, 0xEECD6D1E, 0xED4E06EC,
+ 0xC4268DC3, 0xC7A5E631, 0x3356B622, 0x30D5DDD0,
+ 0xDBB11704, 0xD8327CF6, 0x2CC12CE5, 0x2F424717,
+ 0x0B7E5449, 0x08FD3FBB, 0xFC0E6FA8, 0xFF8D045A,
+ 0x14E9CE8E, 0x176AA57C, 0xE399F56F, 0xE01A9E9D,
+ 0xABE1D3D3, 0xA862B821, 0x5C91E832, 0x5F1283C0,
+ 0xB4764914, 0xB7F522E6, 0x430672F5, 0x40851907,
+ 0x64B90A59, 0x673A61AB, 0x93C931B8, 0x904A5A4A,
+ 0x7B2E909E, 0x78ADFB6C, 0x8C5EAB7F, 0x8FDDC08D,
+ 0x1AA830E3, 0x192B5B11, 0xEDD80B02, 0xEE5B60F0,
+ 0x053FAA24, 0x06BCC1D6, 0xF24F91C5, 0xF1CCFA37,
+ 0xD5F0E969, 0xD673829B, 0x2280D288, 0x2103B97A,
+ 0xCA6773AE, 0xC9E4185C, 0x3D17484F, 0x3E9423BD,
+ 0x756F6EF3, 0x76EC0501, 0x821F5512, 0x819C3EE0,
+ 0x6AF8F434, 0x697B9FC6, 0x9D88CFD5, 0x9E0BA427,
+ 0xBA37B779, 0xB9B4DC8B, 0x4D478C98, 0x4EC4E76A,
+ 0xA5A02DBE, 0xA623464C, 0x52D0165F, 0x51537DAD,
+ },
+ {
+ 0x00000000, 0x7798A213, 0xEE304527, 0x99A8E734,
+ 0xDC618A4E, 0xABF9285D, 0x3251CF69, 0x45C96D7A,
+ 0xB8C3149D, 0xCF5BB68E, 0x56F351BA, 0x216BF3A9,
+ 0x64A29ED3, 0x133A3CC0, 0x8A92DBF4, 0xFD0A79E7,
+ 0x81F1C53F, 0xF669672C, 0x6FC18018, 0x1859220B,
+ 0x5D904F71, 0x2A08ED62, 0xB3A00A56, 0xC438A845,
+ 0x3932D1A2, 0x4EAA73B1, 0xD7029485, 0xA09A3696,
+ 0xE5535BEC, 0x92CBF9FF, 0x0B631ECB, 0x7CFBBCD8,
+ 0x02E38B7F, 0x757B296C, 0xECD3CE58, 0x9B4B6C4B,
+ 0xDE820131, 0xA91AA322, 0x30B24416, 0x472AE605,
+ 0xBA209FE2, 0xCDB83DF1, 0x5410DAC5, 0x238878D6,
+ 0x664115AC, 0x11D9B7BF, 0x8871508B, 0xFFE9F298,
+ 0x83124E40, 0xF48AEC53, 0x6D220B67, 0x1ABAA974,
+ 0x5F73C40E, 0x28EB661D, 0xB1438129, 0xC6DB233A,
+ 0x3BD15ADD, 0x4C49F8CE, 0xD5E11FFA, 0xA279BDE9,
+ 0xE7B0D093, 0x90287280, 0x098095B4, 0x7E1837A7,
+ 0x04C617FF, 0x735EB5EC, 0xEAF652D8, 0x9D6EF0CB,
+ 0xD8A79DB1, 0xAF3F3FA2, 0x3697D896, 0x410F7A85,
+ 0xBC050362, 0xCB9DA171, 0x52354645, 0x25ADE456,
+ 0x6064892C, 0x17FC2B3F, 0x8E54CC0B, 0xF9CC6E18,
+ 0x8537D2C0, 0xF2AF70D3, 0x6B0797E7, 0x1C9F35F4,
+ 0x5956588E, 0x2ECEFA9D, 0xB7661DA9, 0xC0FEBFBA,
+ 0x3DF4C65D, 0x4A6C644E, 0xD3C4837A, 0xA45C2169,
+ 0xE1954C13, 0x960DEE00, 0x0FA50934, 0x783DAB27,
+ 0x06259C80, 0x71BD3E93, 0xE815D9A7, 0x9F8D7BB4,
+ 0xDA4416CE, 0xADDCB4DD, 0x347453E9, 0x43ECF1FA,
+ 0xBEE6881D, 0xC97E2A0E, 0x50D6CD3A, 0x274E6F29,
+ 0x62870253, 0x151FA040, 0x8CB74774, 0xFB2FE567,
+ 0x87D459BF, 0xF04CFBAC, 0x69E41C98, 0x1E7CBE8B,
+ 0x5BB5D3F1, 0x2C2D71E2, 0xB58596D6, 0xC21D34C5,
+ 0x3F174D22, 0x488FEF31, 0xD1270805, 0xA6BFAA16,
+ 0xE376C76C, 0x94EE657F, 0x0D46824B, 0x7ADE2058,
+ 0xF9FAC3FB, 0x8E6261E8, 0x17CA86DC, 0x605224CF,
+ 0x259B49B5, 0x5203EBA6, 0xCBAB0C92, 0xBC33AE81,
+ 0x4139D766, 0x36A17575, 0xAF099241, 0xD8913052,
+ 0x9D585D28, 0xEAC0FF3B, 0x7368180F, 0x04F0BA1C,
+ 0x780B06C4, 0x0F93A4D7, 0x963B43E3, 0xE1A3E1F0,
+ 0xA46A8C8A, 0xD3F22E99, 0x4A5AC9AD, 0x3DC26BBE,
+ 0xC0C81259, 0xB750B04A, 0x2EF8577E, 0x5960F56D,
+ 0x1CA99817, 0x6B313A04, 0xF299DD30, 0x85017F23,
+ 0xFB194884, 0x8C81EA97, 0x15290DA3, 0x62B1AFB0,
+ 0x2778C2CA, 0x50E060D9, 0xC94887ED, 0xBED025FE,
+ 0x43DA5C19, 0x3442FE0A, 0xADEA193E, 0xDA72BB2D,
+ 0x9FBBD657, 0xE8237444, 0x718B9370, 0x06133163,
+ 0x7AE88DBB, 0x0D702FA8, 0x94D8C89C, 0xE3406A8F,
+ 0xA68907F5, 0xD111A5E6, 0x48B942D2, 0x3F21E0C1,
+ 0xC22B9926, 0xB5B33B35, 0x2C1BDC01, 0x5B837E12,
+ 0x1E4A1368, 0x69D2B17B, 0xF07A564F, 0x87E2F45C,
+ 0xFD3CD404, 0x8AA47617, 0x130C9123, 0x64943330,
+ 0x215D5E4A, 0x56C5FC59, 0xCF6D1B6D, 0xB8F5B97E,
+ 0x45FFC099, 0x3267628A, 0xABCF85BE, 0xDC5727AD,
+ 0x999E4AD7, 0xEE06E8C4, 0x77AE0FF0, 0x0036ADE3,
+ 0x7CCD113B, 0x0B55B328, 0x92FD541C, 0xE565F60F,
+ 0xA0AC9B75, 0xD7343966, 0x4E9CDE52, 0x39047C41,
+ 0xC40E05A6, 0xB396A7B5, 0x2A3E4081, 0x5DA6E292,
+ 0x186F8FE8, 0x6FF72DFB, 0xF65FCACF, 0x81C768DC,
+ 0xFFDF5F7B, 0x8847FD68, 0x11EF1A5C, 0x6677B84F,
+ 0x23BED535, 0x54267726, 0xCD8E9012, 0xBA163201,
+ 0x471C4BE6, 0x3084E9F5, 0xA92C0EC1, 0xDEB4ACD2,
+ 0x9B7DC1A8, 0xECE563BB, 0x754D848F, 0x02D5269C,
+ 0x7E2E9A44, 0x09B63857, 0x901EDF63, 0xE7867D70,
+ 0xA24F100A, 0xD5D7B219, 0x4C7F552D, 0x3BE7F73E,
+ 0xC6ED8ED9, 0xB1752CCA, 0x28DDCBFE, 0x5F4569ED,
+ 0x1A8C0497, 0x6D14A684, 0xF4BC41B0, 0x8324E3A3,
+ },
+ {
+ 0x00000000, 0x7E9241A5, 0x0D526F4F, 0x73C02EEA,
+ 0x1AA4DE9E, 0x64369F3B, 0x17F6B1D1, 0x6964F074,
+ 0xC53E5138, 0xBBAC109D, 0xC86C3E77, 0xB6FE7FD2,
+ 0xDF9A8FA6, 0xA108CE03, 0xD2C8E0E9, 0xAC5AA14C,
+ 0x8A7DA270, 0xF4EFE3D5, 0x872FCD3F, 0xF9BD8C9A,
+ 0x90D97CEE, 0xEE4B3D4B, 0x9D8B13A1, 0xE3195204,
+ 0x4F43F348, 0x31D1B2ED, 0x42119C07, 0x3C83DDA2,
+ 0x55E72DD6, 0x2B756C73, 0x58B54299, 0x2627033C,
+ 0x14FB44E1, 0x6A690544, 0x19A92BAE, 0x673B6A0B,
+ 0x0E5F9A7F, 0x70CDDBDA, 0x030DF530, 0x7D9FB495,
+ 0xD1C515D9, 0xAF57547C, 0xDC977A96, 0xA2053B33,
+ 0xCB61CB47, 0xB5F38AE2, 0xC633A408, 0xB8A1E5AD,
+ 0x9E86E691, 0xE014A734, 0x93D489DE, 0xED46C87B,
+ 0x8422380F, 0xFAB079AA, 0x89705740, 0xF7E216E5,
+ 0x5BB8B7A9, 0x252AF60C, 0x56EAD8E6, 0x28789943,
+ 0x411C6937, 0x3F8E2892, 0x4C4E0678, 0x32DC47DD,
+ 0xD98065C7, 0xA7122462, 0xD4D20A88, 0xAA404B2D,
+ 0xC324BB59, 0xBDB6FAFC, 0xCE76D416, 0xB0E495B3,
+ 0x1CBE34FF, 0x622C755A, 0x11EC5BB0, 0x6F7E1A15,
+ 0x061AEA61, 0x7888ABC4, 0x0B48852E, 0x75DAC48B,
+ 0x53FDC7B7, 0x2D6F8612, 0x5EAFA8F8, 0x203DE95D,
+ 0x49591929, 0x37CB588C, 0x440B7666, 0x3A9937C3,
+ 0x96C3968F, 0xE851D72A, 0x9B91F9C0, 0xE503B865,
+ 0x8C674811, 0xF2F509B4, 0x8135275E, 0xFFA766FB,
+ 0xCD7B2126, 0xB3E96083, 0xC0294E69, 0xBEBB0FCC,
+ 0xD7DFFFB8, 0xA94DBE1D, 0xDA8D90F7, 0xA41FD152,
+ 0x0845701E, 0x76D731BB, 0x05171F51, 0x7B855EF4,
+ 0x12E1AE80, 0x6C73EF25, 0x1FB3C1CF, 0x6121806A,
+ 0x47068356, 0x3994C2F3, 0x4A54EC19, 0x34C6ADBC,
+ 0x5DA25DC8, 0x23301C6D, 0x50F03287, 0x2E627322,
+ 0x8238D26E, 0xFCAA93CB, 0x8F6ABD21, 0xF1F8FC84,
+ 0x989C0CF0, 0xE60E4D55, 0x95CE63BF, 0xEB5C221A,
+ 0x4377278B, 0x3DE5662E, 0x4E2548C4, 0x30B70961,
+ 0x59D3F915, 0x2741B8B0, 0x5481965A, 0x2A13D7FF,
+ 0x864976B3, 0xF8DB3716, 0x8B1B19FC, 0xF5895859,
+ 0x9CEDA82D, 0xE27FE988, 0x91BFC762, 0xEF2D86C7,
+ 0xC90A85FB, 0xB798C45E, 0xC458EAB4, 0xBACAAB11,
+ 0xD3AE5B65, 0xAD3C1AC0, 0xDEFC342A, 0xA06E758F,
+ 0x0C34D4C3, 0x72A69566, 0x0166BB8C, 0x7FF4FA29,
+ 0x16900A5D, 0x68024BF8, 0x1BC26512, 0x655024B7,
+ 0x578C636A, 0x291E22CF, 0x5ADE0C25, 0x244C4D80,
+ 0x4D28BDF4, 0x33BAFC51, 0x407AD2BB, 0x3EE8931E,
+ 0x92B23252, 0xEC2073F7, 0x9FE05D1D, 0xE1721CB8,
+ 0x8816ECCC, 0xF684AD69, 0x85448383, 0xFBD6C226,
+ 0xDDF1C11A, 0xA36380BF, 0xD0A3AE55, 0xAE31EFF0,
+ 0xC7551F84, 0xB9C75E21, 0xCA0770CB, 0xB495316E,
+ 0x18CF9022, 0x665DD187, 0x159DFF6D, 0x6B0FBEC8,
+ 0x026B4EBC, 0x7CF90F19, 0x0F3921F3, 0x71AB6056,
+ 0x9AF7424C, 0xE46503E9, 0x97A52D03, 0xE9376CA6,
+ 0x80539CD2, 0xFEC1DD77, 0x8D01F39D, 0xF393B238,
+ 0x5FC91374, 0x215B52D1, 0x529B7C3B, 0x2C093D9E,
+ 0x456DCDEA, 0x3BFF8C4F, 0x483FA2A5, 0x36ADE300,
+ 0x108AE03C, 0x6E18A199, 0x1DD88F73, 0x634ACED6,
+ 0x0A2E3EA2, 0x74BC7F07, 0x077C51ED, 0x79EE1048,
+ 0xD5B4B104, 0xAB26F0A1, 0xD8E6DE4B, 0xA6749FEE,
+ 0xCF106F9A, 0xB1822E3F, 0xC24200D5, 0xBCD04170,
+ 0x8E0C06AD, 0xF09E4708, 0x835E69E2, 0xFDCC2847,
+ 0x94A8D833, 0xEA3A9996, 0x99FAB77C, 0xE768F6D9,
+ 0x4B325795, 0x35A01630, 0x466038DA, 0x38F2797F,
+ 0x5196890B, 0x2F04C8AE, 0x5CC4E644, 0x2256A7E1,
+ 0x0471A4DD, 0x7AE3E578, 0x0923CB92, 0x77B18A37,
+ 0x1ED57A43, 0x60473BE6, 0x1387150C, 0x6D1554A9,
+ 0xC14FF5E5, 0xBFDDB440, 0xCC1D9AAA, 0xB28FDB0F,
+ 0xDBEB2B7B, 0xA5796ADE, 0xD6B94434, 0xA82B0591,
+ },
+ {
+ 0x00000000, 0xB8AA45DD, 0x812367BF, 0x39892262,
+ 0xF331227B, 0x4B9B67A6, 0x721245C4, 0xCAB80019,
+ 0xE66344F6, 0x5EC9012B, 0x67402349, 0xDFEA6694,
+ 0x1552668D, 0xADF82350, 0x94710132, 0x2CDB44EF,
+ 0x3DB164E9, 0x851B2134, 0xBC920356, 0x0438468B,
+ 0xCE804692, 0x762A034F, 0x4FA3212D, 0xF70964F0,
+ 0xDBD2201F, 0x637865C2, 0x5AF147A0, 0xE25B027D,
+ 0x28E30264, 0x904947B9, 0xA9C065DB, 0x116A2006,
+ 0x8B1425D7, 0x33BE600A, 0x0A374268, 0xB29D07B5,
+ 0x782507AC, 0xC08F4271, 0xF9066013, 0x41AC25CE,
+ 0x6D776121, 0xD5DD24FC, 0xEC54069E, 0x54FE4343,
+ 0x9E46435A, 0x26EC0687, 0x1F6524E5, 0xA7CF6138,
+ 0xB6A5413E, 0x0E0F04E3, 0x37862681, 0x8F2C635C,
+ 0x45946345, 0xFD3E2698, 0xC4B704FA, 0x7C1D4127,
+ 0x50C605C8, 0xE86C4015, 0xD1E56277, 0x694F27AA,
+ 0xA3F727B3, 0x1B5D626E, 0x22D4400C, 0x9A7E05D1,
+ 0xE75FA6AB, 0x5FF5E376, 0x667CC114, 0xDED684C9,
+ 0x146E84D0, 0xACC4C10D, 0x954DE36F, 0x2DE7A6B2,
+ 0x013CE25D, 0xB996A780, 0x801F85E2, 0x38B5C03F,
+ 0xF20DC026, 0x4AA785FB, 0x732EA799, 0xCB84E244,
+ 0xDAEEC242, 0x6244879F, 0x5BCDA5FD, 0xE367E020,
+ 0x29DFE039, 0x9175A5E4, 0xA8FC8786, 0x1056C25B,
+ 0x3C8D86B4, 0x8427C369, 0xBDAEE10B, 0x0504A4D6,
+ 0xCFBCA4CF, 0x7716E112, 0x4E9FC370, 0xF63586AD,
+ 0x6C4B837C, 0xD4E1C6A1, 0xED68E4C3, 0x55C2A11E,
+ 0x9F7AA107, 0x27D0E4DA, 0x1E59C6B8, 0xA6F38365,
+ 0x8A28C78A, 0x32828257, 0x0B0BA035, 0xB3A1E5E8,
+ 0x7919E5F1, 0xC1B3A02C, 0xF83A824E, 0x4090C793,
+ 0x51FAE795, 0xE950A248, 0xD0D9802A, 0x6873C5F7,
+ 0xA2CBC5EE, 0x1A618033, 0x23E8A251, 0x9B42E78C,
+ 0xB799A363, 0x0F33E6BE, 0x36BAC4DC, 0x8E108101,
+ 0x44A88118, 0xFC02C4C5, 0xC58BE6A7, 0x7D21A37A,
+ 0x3FC9A052, 0x8763E58F, 0xBEEAC7ED, 0x06408230,
+ 0xCCF88229, 0x7452C7F4, 0x4DDBE596, 0xF571A04B,
+ 0xD9AAE4A4, 0x6100A179, 0x5889831B, 0xE023C6C6,
+ 0x2A9BC6DF, 0x92318302, 0xABB8A160, 0x1312E4BD,
+ 0x0278C4BB, 0xBAD28166, 0x835BA304, 0x3BF1E6D9,
+ 0xF149E6C0, 0x49E3A31D, 0x706A817F, 0xC8C0C4A2,
+ 0xE41B804D, 0x5CB1C590, 0x6538E7F2, 0xDD92A22F,
+ 0x172AA236, 0xAF80E7EB, 0x9609C589, 0x2EA38054,
+ 0xB4DD8585, 0x0C77C058, 0x35FEE23A, 0x8D54A7E7,
+ 0x47ECA7FE, 0xFF46E223, 0xC6CFC041, 0x7E65859C,
+ 0x52BEC173, 0xEA1484AE, 0xD39DA6CC, 0x6B37E311,
+ 0xA18FE308, 0x1925A6D5, 0x20AC84B7, 0x9806C16A,
+ 0x896CE16C, 0x31C6A4B1, 0x084F86D3, 0xB0E5C30E,
+ 0x7A5DC317, 0xC2F786CA, 0xFB7EA4A8, 0x43D4E175,
+ 0x6F0FA59A, 0xD7A5E047, 0xEE2CC225, 0x568687F8,
+ 0x9C3E87E1, 0x2494C23C, 0x1D1DE05E, 0xA5B7A583,
+ 0xD89606F9, 0x603C4324, 0x59B56146, 0xE11F249B,
+ 0x2BA72482, 0x930D615F, 0xAA84433D, 0x122E06E0,
+ 0x3EF5420F, 0x865F07D2, 0xBFD625B0, 0x077C606D,
+ 0xCDC46074, 0x756E25A9, 0x4CE707CB, 0xF44D4216,
+ 0xE5276210, 0x5D8D27CD, 0x640405AF, 0xDCAE4072,
+ 0x1616406B, 0xAEBC05B6, 0x973527D4, 0x2F9F6209,
+ 0x034426E6, 0xBBEE633B, 0x82674159, 0x3ACD0484,
+ 0xF075049D, 0x48DF4140, 0x71566322, 0xC9FC26FF,
+ 0x5382232E, 0xEB2866F3, 0xD2A14491, 0x6A0B014C,
+ 0xA0B30155, 0x18194488, 0x219066EA, 0x993A2337,
+ 0xB5E167D8, 0x0D4B2205, 0x34C20067, 0x8C6845BA,
+ 0x46D045A3, 0xFE7A007E, 0xC7F3221C, 0x7F5967C1,
+ 0x6E3347C7, 0xD699021A, 0xEF102078, 0x57BA65A5,
+ 0x9D0265BC, 0x25A82061, 0x1C210203, 0xA48B47DE,
+ 0x88500331, 0x30FA46EC, 0x0973648E, 0xB1D92153,
+ 0x7B61214A, 0xC3CB6497, 0xFA4246F5, 0x42E80328,
+ },
+ {
+ 0x00000000, 0xAC6F1138, 0x58DF2270, 0xF4B03348,
+ 0xB0BE45E0, 0x1CD154D8, 0xE8616790, 0x440E76A8,
+ 0x910B67C5, 0x3D6476FD, 0xC9D445B5, 0x65BB548D,
+ 0x21B52225, 0x8DDA331D, 0x796A0055, 0xD505116D,
+ 0xD361228F, 0x7F0E33B7, 0x8BBE00FF, 0x27D111C7,
+ 0x63DF676F, 0xCFB07657, 0x3B00451F, 0x976F5427,
+ 0x426A454A, 0xEE055472, 0x1AB5673A, 0xB6DA7602,
+ 0xF2D400AA, 0x5EBB1192, 0xAA0B22DA, 0x066433E2,
+ 0x57B5A81B, 0xFBDAB923, 0x0F6A8A6B, 0xA3059B53,
+ 0xE70BEDFB, 0x4B64FCC3, 0xBFD4CF8B, 0x13BBDEB3,
+ 0xC6BECFDE, 0x6AD1DEE6, 0x9E61EDAE, 0x320EFC96,
+ 0x76008A3E, 0xDA6F9B06, 0x2EDFA84E, 0x82B0B976,
+ 0x84D48A94, 0x28BB9BAC, 0xDC0BA8E4, 0x7064B9DC,
+ 0x346ACF74, 0x9805DE4C, 0x6CB5ED04, 0xC0DAFC3C,
+ 0x15DFED51, 0xB9B0FC69, 0x4D00CF21, 0xE16FDE19,
+ 0xA561A8B1, 0x090EB989, 0xFDBE8AC1, 0x51D19BF9,
+ 0xAE6A5137, 0x0205400F, 0xF6B57347, 0x5ADA627F,
+ 0x1ED414D7, 0xB2BB05EF, 0x460B36A7, 0xEA64279F,
+ 0x3F6136F2, 0x930E27CA, 0x67BE1482, 0xCBD105BA,
+ 0x8FDF7312, 0x23B0622A, 0xD7005162, 0x7B6F405A,
+ 0x7D0B73B8, 0xD1646280, 0x25D451C8, 0x89BB40F0,
+ 0xCDB53658, 0x61DA2760, 0x956A1428, 0x39050510,
+ 0xEC00147D, 0x406F0545, 0xB4DF360D, 0x18B02735,
+ 0x5CBE519D, 0xF0D140A5, 0x046173ED, 0xA80E62D5,
+ 0xF9DFF92C, 0x55B0E814, 0xA100DB5C, 0x0D6FCA64,
+ 0x4961BCCC, 0xE50EADF4, 0x11BE9EBC, 0xBDD18F84,
+ 0x68D49EE9, 0xC4BB8FD1, 0x300BBC99, 0x9C64ADA1,
+ 0xD86ADB09, 0x7405CA31, 0x80B5F979, 0x2CDAE841,
+ 0x2ABEDBA3, 0x86D1CA9B, 0x7261F9D3, 0xDE0EE8EB,
+ 0x9A009E43, 0x366F8F7B, 0xC2DFBC33, 0x6EB0AD0B,
+ 0xBBB5BC66, 0x17DAAD5E, 0xE36A9E16, 0x4F058F2E,
+ 0x0B0BF986, 0xA764E8BE, 0x53D4DBF6, 0xFFBBCACE,
+ 0x5CD5A26E, 0xF0BAB356, 0x040A801E, 0xA8659126,
+ 0xEC6BE78E, 0x4004F6B6, 0xB4B4C5FE, 0x18DBD4C6,
+ 0xCDDEC5AB, 0x61B1D493, 0x9501E7DB, 0x396EF6E3,
+ 0x7D60804B, 0xD10F9173, 0x25BFA23B, 0x89D0B303,
+ 0x8FB480E1, 0x23DB91D9, 0xD76BA291, 0x7B04B3A9,
+ 0x3F0AC501, 0x9365D439, 0x67D5E771, 0xCBBAF649,
+ 0x1EBFE724, 0xB2D0F61C, 0x4660C554, 0xEA0FD46C,
+ 0xAE01A2C4, 0x026EB3FC, 0xF6DE80B4, 0x5AB1918C,
+ 0x0B600A75, 0xA70F1B4D, 0x53BF2805, 0xFFD0393D,
+ 0xBBDE4F95, 0x17B15EAD, 0xE3016DE5, 0x4F6E7CDD,
+ 0x9A6B6DB0, 0x36047C88, 0xC2B44FC0, 0x6EDB5EF8,
+ 0x2AD52850, 0x86BA3968, 0x720A0A20, 0xDE651B18,
+ 0xD80128FA, 0x746E39C2, 0x80DE0A8A, 0x2CB11BB2,
+ 0x68BF6D1A, 0xC4D07C22, 0x30604F6A, 0x9C0F5E52,
+ 0x490A4F3F, 0xE5655E07, 0x11D56D4F, 0xBDBA7C77,
+ 0xF9B40ADF, 0x55DB1BE7, 0xA16B28AF, 0x0D043997,
+ 0xF2BFF359, 0x5ED0E261, 0xAA60D129, 0x060FC011,
+ 0x4201B6B9, 0xEE6EA781, 0x1ADE94C9, 0xB6B185F1,
+ 0x63B4949C, 0xCFDB85A4, 0x3B6BB6EC, 0x9704A7D4,
+ 0xD30AD17C, 0x7F65C044, 0x8BD5F30C, 0x27BAE234,
+ 0x21DED1D6, 0x8DB1C0EE, 0x7901F3A6, 0xD56EE29E,
+ 0x91609436, 0x3D0F850E, 0xC9BFB646, 0x65D0A77E,
+ 0xB0D5B613, 0x1CBAA72B, 0xE80A9463, 0x4465855B,
+ 0x006BF3F3, 0xAC04E2CB, 0x58B4D183, 0xF4DBC0BB,
+ 0xA50A5B42, 0x09654A7A, 0xFDD57932, 0x51BA680A,
+ 0x15B41EA2, 0xB9DB0F9A, 0x4D6B3CD2, 0xE1042DEA,
+ 0x34013C87, 0x986E2DBF, 0x6CDE1EF7, 0xC0B10FCF,
+ 0x84BF7967, 0x28D0685F, 0xDC605B17, 0x700F4A2F,
+ 0x766B79CD, 0xDA0468F5, 0x2EB45BBD, 0x82DB4A85,
+ 0xC6D53C2D, 0x6ABA2D15, 0x9E0A1E5D, 0x32650F65,
+ 0xE7601E08, 0x4B0F0F30, 0xBFBF3C78, 0x13D02D40,
+ 0x57DE5BE8, 0xFBB14AD0, 0x0F017998, 0xA36E68A0,
+ },
+ {
+ 0x00000000, 0x196B30EF, 0xC3A08CDB, 0xDACBBC34,
+ 0x7737F5B2, 0x6E5CC55D, 0xB4977969, 0xADFC4986,
+ 0x1F180660, 0x0673368F, 0xDCB88ABB, 0xC5D3BA54,
+ 0x682FF3D2, 0x7144C33D, 0xAB8F7F09, 0xB2E44FE6,
+ 0x3E300CC0, 0x275B3C2F, 0xFD90801B, 0xE4FBB0F4,
+ 0x4907F972, 0x506CC99D, 0x8AA775A9, 0x93CC4546,
+ 0x21280AA0, 0x38433A4F, 0xE288867B, 0xFBE3B694,
+ 0x561FFF12, 0x4F74CFFD, 0x95BF73C9, 0x8CD44326,
+ 0x8D16F485, 0x947DC46A, 0x4EB6785E, 0x57DD48B1,
+ 0xFA210137, 0xE34A31D8, 0x39818DEC, 0x20EABD03,
+ 0x920EF2E5, 0x8B65C20A, 0x51AE7E3E, 0x48C54ED1,
+ 0xE5390757, 0xFC5237B8, 0x26998B8C, 0x3FF2BB63,
+ 0xB326F845, 0xAA4DC8AA, 0x7086749E, 0x69ED4471,
+ 0xC4110DF7, 0xDD7A3D18, 0x07B1812C, 0x1EDAB1C3,
+ 0xAC3EFE25, 0xB555CECA, 0x6F9E72FE, 0x76F54211,
+ 0xDB090B97, 0xC2623B78, 0x18A9874C, 0x01C2B7A3,
+ 0xEB5B040E, 0xF23034E1, 0x28FB88D5, 0x3190B83A,
+ 0x9C6CF1BC, 0x8507C153, 0x5FCC7D67, 0x46A74D88,
+ 0xF443026E, 0xED283281, 0x37E38EB5, 0x2E88BE5A,
+ 0x8374F7DC, 0x9A1FC733, 0x40D47B07, 0x59BF4BE8,
+ 0xD56B08CE, 0xCC003821, 0x16CB8415, 0x0FA0B4FA,
+ 0xA25CFD7C, 0xBB37CD93, 0x61FC71A7, 0x78974148,
+ 0xCA730EAE, 0xD3183E41, 0x09D38275, 0x10B8B29A,
+ 0xBD44FB1C, 0xA42FCBF3, 0x7EE477C7, 0x678F4728,
+ 0x664DF08B, 0x7F26C064, 0xA5ED7C50, 0xBC864CBF,
+ 0x117A0539, 0x081135D6, 0xD2DA89E2, 0xCBB1B90D,
+ 0x7955F6EB, 0x603EC604, 0xBAF57A30, 0xA39E4ADF,
+ 0x0E620359, 0x170933B6, 0xCDC28F82, 0xD4A9BF6D,
+ 0x587DFC4B, 0x4116CCA4, 0x9BDD7090, 0x82B6407F,
+ 0x2F4A09F9, 0x36213916, 0xECEA8522, 0xF581B5CD,
+ 0x4765FA2B, 0x5E0ECAC4, 0x84C576F0, 0x9DAE461F,
+ 0x30520F99, 0x29393F76, 0xF3F28342, 0xEA99B3AD,
+ 0xD6B7081C, 0xCFDC38F3, 0x151784C7, 0x0C7CB428,
+ 0xA180FDAE, 0xB8EBCD41, 0x62207175, 0x7B4B419A,
+ 0xC9AF0E7C, 0xD0C43E93, 0x0A0F82A7, 0x1364B248,
+ 0xBE98FBCE, 0xA7F3CB21, 0x7D387715, 0x645347FA,
+ 0xE88704DC, 0xF1EC3433, 0x2B278807, 0x324CB8E8,
+ 0x9FB0F16E, 0x86DBC181, 0x5C107DB5, 0x457B4D5A,
+ 0xF79F02BC, 0xEEF43253, 0x343F8E67, 0x2D54BE88,
+ 0x80A8F70E, 0x99C3C7E1, 0x43087BD5, 0x5A634B3A,
+ 0x5BA1FC99, 0x42CACC76, 0x98017042, 0x816A40AD,
+ 0x2C96092B, 0x35FD39C4, 0xEF3685F0, 0xF65DB51F,
+ 0x44B9FAF9, 0x5DD2CA16, 0x87197622, 0x9E7246CD,
+ 0x338E0F4B, 0x2AE53FA4, 0xF02E8390, 0xE945B37F,
+ 0x6591F059, 0x7CFAC0B6, 0xA6317C82, 0xBF5A4C6D,
+ 0x12A605EB, 0x0BCD3504, 0xD1068930, 0xC86DB9DF,
+ 0x7A89F639, 0x63E2C6D6, 0xB9297AE2, 0xA0424A0D,
+ 0x0DBE038B, 0x14D53364, 0xCE1E8F50, 0xD775BFBF,
+ 0x3DEC0C12, 0x24873CFD, 0xFE4C80C9, 0xE727B026,
+ 0x4ADBF9A0, 0x53B0C94F, 0x897B757B, 0x90104594,
+ 0x22F40A72, 0x3B9F3A9D, 0xE15486A9, 0xF83FB646,
+ 0x55C3FFC0, 0x4CA8CF2F, 0x9663731B, 0x8F0843F4,
+ 0x03DC00D2, 0x1AB7303D, 0xC07C8C09, 0xD917BCE6,
+ 0x74EBF560, 0x6D80C58F, 0xB74B79BB, 0xAE204954,
+ 0x1CC406B2, 0x05AF365D, 0xDF648A69, 0xC60FBA86,
+ 0x6BF3F300, 0x7298C3EF, 0xA8537FDB, 0xB1384F34,
+ 0xB0FAF897, 0xA991C878, 0x735A744C, 0x6A3144A3,
+ 0xC7CD0D25, 0xDEA63DCA, 0x046D81FE, 0x1D06B111,
+ 0xAFE2FEF7, 0xB689CE18, 0x6C42722C, 0x752942C3,
+ 0xD8D50B45, 0xC1BE3BAA, 0x1B75879E, 0x021EB771,
+ 0x8ECAF457, 0x97A1C4B8, 0x4D6A788C, 0x54014863,
+ 0xF9FD01E5, 0xE096310A, 0x3A5D8D3E, 0x2336BDD1,
+ 0x91D2F237, 0x88B9C2D8, 0x52727EEC, 0x4B194E03,
+ 0xE6E50785, 0xFF8E376A, 0x25458B5E, 0x3C2EBBB1,
+ },
+ {
+ 0x00000000, 0xC82C0368, 0x905906D0, 0x587505B8,
+ 0xD1C5E0A5, 0x19E9E3CD, 0x419CE675, 0x89B0E51D,
+ 0x53FD2D4E, 0x9BD12E26, 0xC3A42B9E, 0x0B8828F6,
+ 0x8238CDEB, 0x4A14CE83, 0x1261CB3B, 0xDA4DC853,
+ 0xA6FA5B9C, 0x6ED658F4, 0x36A35D4C, 0xFE8F5E24,
+ 0x773FBB39, 0xBF13B851, 0xE766BDE9, 0x2F4ABE81,
+ 0xF50776D2, 0x3D2B75BA, 0x655E7002, 0xAD72736A,
+ 0x24C29677, 0xECEE951F, 0xB49B90A7, 0x7CB793CF,
+ 0xBD835B3D, 0x75AF5855, 0x2DDA5DED, 0xE5F65E85,
+ 0x6C46BB98, 0xA46AB8F0, 0xFC1FBD48, 0x3433BE20,
+ 0xEE7E7673, 0x2652751B, 0x7E2770A3, 0xB60B73CB,
+ 0x3FBB96D6, 0xF79795BE, 0xAFE29006, 0x67CE936E,
+ 0x1B7900A1, 0xD35503C9, 0x8B200671, 0x430C0519,
+ 0xCABCE004, 0x0290E36C, 0x5AE5E6D4, 0x92C9E5BC,
+ 0x48842DEF, 0x80A82E87, 0xD8DD2B3F, 0x10F12857,
+ 0x9941CD4A, 0x516DCE22, 0x0918CB9A, 0xC134C8F2,
+ 0x7A07B77A, 0xB22BB412, 0xEA5EB1AA, 0x2272B2C2,
+ 0xABC257DF, 0x63EE54B7, 0x3B9B510F, 0xF3B75267,
+ 0x29FA9A34, 0xE1D6995C, 0xB9A39CE4, 0x718F9F8C,
+ 0xF83F7A91, 0x301379F9, 0x68667C41, 0xA04A7F29,
+ 0xDCFDECE6, 0x14D1EF8E, 0x4CA4EA36, 0x8488E95E,
+ 0x0D380C43, 0xC5140F2B, 0x9D610A93, 0x554D09FB,
+ 0x8F00C1A8, 0x472CC2C0, 0x1F59C778, 0xD775C410,
+ 0x5EC5210D, 0x96E92265, 0xCE9C27DD, 0x06B024B5,
+ 0xC784EC47, 0x0FA8EF2F, 0x57DDEA97, 0x9FF1E9FF,
+ 0x16410CE2, 0xDE6D0F8A, 0x86180A32, 0x4E34095A,
+ 0x9479C109, 0x5C55C261, 0x0420C7D9, 0xCC0CC4B1,
+ 0x45BC21AC, 0x8D9022C4, 0xD5E5277C, 0x1DC92414,
+ 0x617EB7DB, 0xA952B4B3, 0xF127B10B, 0x390BB263,
+ 0xB0BB577E, 0x78975416, 0x20E251AE, 0xE8CE52C6,
+ 0x32839A95, 0xFAAF99FD, 0xA2DA9C45, 0x6AF69F2D,
+ 0xE3467A30, 0x2B6A7958, 0x731F7CE0, 0xBB337F88,
+ 0xF40E6EF5, 0x3C226D9D, 0x64576825, 0xAC7B6B4D,
+ 0x25CB8E50, 0xEDE78D38, 0xB5928880, 0x7DBE8BE8,
+ 0xA7F343BB, 0x6FDF40D3, 0x37AA456B, 0xFF864603,
+ 0x7636A31E, 0xBE1AA076, 0xE66FA5CE, 0x2E43A6A6,
+ 0x52F43569, 0x9AD83601, 0xC2AD33B9, 0x0A8130D1,
+ 0x8331D5CC, 0x4B1DD6A4, 0x1368D31C, 0xDB44D074,
+ 0x01091827, 0xC9251B4F, 0x91501EF7, 0x597C1D9F,
+ 0xD0CCF882, 0x18E0FBEA, 0x4095FE52, 0x88B9FD3A,
+ 0x498D35C8, 0x81A136A0, 0xD9D43318, 0x11F83070,
+ 0x9848D56D, 0x5064D605, 0x0811D3BD, 0xC03DD0D5,
+ 0x1A701886, 0xD25C1BEE, 0x8A291E56, 0x42051D3E,
+ 0xCBB5F823, 0x0399FB4B, 0x5BECFEF3, 0x93C0FD9B,
+ 0xEF776E54, 0x275B6D3C, 0x7F2E6884, 0xB7026BEC,
+ 0x3EB28EF1, 0xF69E8D99, 0xAEEB8821, 0x66C78B49,
+ 0xBC8A431A, 0x74A64072, 0x2CD345CA, 0xE4FF46A2,
+ 0x6D4FA3BF, 0xA563A0D7, 0xFD16A56F, 0x353AA607,
+ 0x8E09D98F, 0x4625DAE7, 0x1E50DF5F, 0xD67CDC37,
+ 0x5FCC392A, 0x97E03A42, 0xCF953FFA, 0x07B93C92,
+ 0xDDF4F4C1, 0x15D8F7A9, 0x4DADF211, 0x8581F179,
+ 0x0C311464, 0xC41D170C, 0x9C6812B4, 0x544411DC,
+ 0x28F38213, 0xE0DF817B, 0xB8AA84C3, 0x708687AB,
+ 0xF93662B6, 0x311A61DE, 0x696F6466, 0xA143670E,
+ 0x7B0EAF5D, 0xB322AC35, 0xEB57A98D, 0x237BAAE5,
+ 0xAACB4FF8, 0x62E74C90, 0x3A924928, 0xF2BE4A40,
+ 0x338A82B2, 0xFBA681DA, 0xA3D38462, 0x6BFF870A,
+ 0xE24F6217, 0x2A63617F, 0x721664C7, 0xBA3A67AF,
+ 0x6077AFFC, 0xA85BAC94, 0xF02EA92C, 0x3802AA44,
+ 0xB1B24F59, 0x799E4C31, 0x21EB4989, 0xE9C74AE1,
+ 0x9570D92E, 0x5D5CDA46, 0x0529DFFE, 0xCD05DC96,
+ 0x44B5398B, 0x8C993AE3, 0xD4EC3F5B, 0x1CC03C33,
+ 0xC68DF460, 0x0EA1F708, 0x56D4F2B0, 0x9EF8F1D8,
+ 0x174814C5, 0xDF6417AD, 0x87111215, 0x4F3D117D,
+ },
+ {
+ 0x00000000, 0x277D3C49, 0x4EFA7892, 0x698744DB,
+ 0x6D821D21, 0x4AFF2168, 0x237865B3, 0x040559FA,
+ 0xDA043B42, 0xFD79070B, 0x94FE43D0, 0xB3837F99,
+ 0xB7862663, 0x90FB1A2A, 0xF97C5EF1, 0xDE0162B8,
+ 0xB4097684, 0x93744ACD, 0xFAF30E16, 0xDD8E325F,
+ 0xD98B6BA5, 0xFEF657EC, 0x97711337, 0xB00C2F7E,
+ 0x6E0D4DC6, 0x4970718F, 0x20F73554, 0x078A091D,
+ 0x038F50E7, 0x24F26CAE, 0x4D752875, 0x6A08143C,
+ 0x9965000D, 0xBE183C44, 0xD79F789F, 0xF0E244D6,
+ 0xF4E71D2C, 0xD39A2165, 0xBA1D65BE, 0x9D6059F7,
+ 0x43613B4F, 0x641C0706, 0x0D9B43DD, 0x2AE67F94,
+ 0x2EE3266E, 0x099E1A27, 0x60195EFC, 0x476462B5,
+ 0x2D6C7689, 0x0A114AC0, 0x63960E1B, 0x44EB3252,
+ 0x40EE6BA8, 0x679357E1, 0x0E14133A, 0x29692F73,
+ 0xF7684DCB, 0xD0157182, 0xB9923559, 0x9EEF0910,
+ 0x9AEA50EA, 0xBD976CA3, 0xD4102878, 0xF36D1431,
+ 0x32CB001A, 0x15B63C53, 0x7C317888, 0x5B4C44C1,
+ 0x5F491D3B, 0x78342172, 0x11B365A9, 0x36CE59E0,
+ 0xE8CF3B58, 0xCFB20711, 0xA63543CA, 0x81487F83,
+ 0x854D2679, 0xA2301A30, 0xCBB75EEB, 0xECCA62A2,
+ 0x86C2769E, 0xA1BF4AD7, 0xC8380E0C, 0xEF453245,
+ 0xEB406BBF, 0xCC3D57F6, 0xA5BA132D, 0x82C72F64,
+ 0x5CC64DDC, 0x7BBB7195, 0x123C354E, 0x35410907,
+ 0x314450FD, 0x16396CB4, 0x7FBE286F, 0x58C31426,
+ 0xABAE0017, 0x8CD33C5E, 0xE5547885, 0xC22944CC,
+ 0xC62C1D36, 0xE151217F, 0x88D665A4, 0xAFAB59ED,
+ 0x71AA3B55, 0x56D7071C, 0x3F5043C7, 0x182D7F8E,
+ 0x1C282674, 0x3B551A3D, 0x52D25EE6, 0x75AF62AF,
+ 0x1FA77693, 0x38DA4ADA, 0x515D0E01, 0x76203248,
+ 0x72256BB2, 0x555857FB, 0x3CDF1320, 0x1BA22F69,
+ 0xC5A34DD1, 0xE2DE7198, 0x8B593543, 0xAC24090A,
+ 0xA82150F0, 0x8F5C6CB9, 0xE6DB2862, 0xC1A6142B,
+ 0x64960134, 0x43EB3D7D, 0x2A6C79A6, 0x0D1145EF,
+ 0x09141C15, 0x2E69205C, 0x47EE6487, 0x609358CE,
+ 0xBE923A76, 0x99EF063F, 0xF06842E4, 0xD7157EAD,
+ 0xD3102757, 0xF46D1B1E, 0x9DEA5FC5, 0xBA97638C,
+ 0xD09F77B0, 0xF7E24BF9, 0x9E650F22, 0xB918336B,
+ 0xBD1D6A91, 0x9A6056D8, 0xF3E71203, 0xD49A2E4A,
+ 0x0A9B4CF2, 0x2DE670BB, 0x44613460, 0x631C0829,
+ 0x671951D3, 0x40646D9A, 0x29E32941, 0x0E9E1508,
+ 0xFDF30139, 0xDA8E3D70, 0xB30979AB, 0x947445E2,
+ 0x90711C18, 0xB70C2051, 0xDE8B648A, 0xF9F658C3,
+ 0x27F73A7B, 0x008A0632, 0x690D42E9, 0x4E707EA0,
+ 0x4A75275A, 0x6D081B13, 0x048F5FC8, 0x23F26381,
+ 0x49FA77BD, 0x6E874BF4, 0x07000F2F, 0x207D3366,
+ 0x24786A9C, 0x030556D5, 0x6A82120E, 0x4DFF2E47,
+ 0x93FE4CFF, 0xB48370B6, 0xDD04346D, 0xFA790824,
+ 0xFE7C51DE, 0xD9016D97, 0xB086294C, 0x97FB1505,
+ 0x565D012E, 0x71203D67, 0x18A779BC, 0x3FDA45F5,
+ 0x3BDF1C0F, 0x1CA22046, 0x7525649D, 0x525858D4,
+ 0x8C593A6C, 0xAB240625, 0xC2A342FE, 0xE5DE7EB7,
+ 0xE1DB274D, 0xC6A61B04, 0xAF215FDF, 0x885C6396,
+ 0xE25477AA, 0xC5294BE3, 0xACAE0F38, 0x8BD33371,
+ 0x8FD66A8B, 0xA8AB56C2, 0xC12C1219, 0xE6512E50,
+ 0x38504CE8, 0x1F2D70A1, 0x76AA347A, 0x51D70833,
+ 0x55D251C9, 0x72AF6D80, 0x1B28295B, 0x3C551512,
+ 0xCF380123, 0xE8453D6A, 0x81C279B1, 0xA6BF45F8,
+ 0xA2BA1C02, 0x85C7204B, 0xEC406490, 0xCB3D58D9,
+ 0x153C3A61, 0x32410628, 0x5BC642F3, 0x7CBB7EBA,
+ 0x78BE2740, 0x5FC31B09, 0x36445FD2, 0x1139639B,
+ 0x7B3177A7, 0x5C4C4BEE, 0x35CB0F35, 0x12B6337C,
+ 0x16B36A86, 0x31CE56CF, 0x58491214, 0x7F342E5D,
+ 0xA1354CE5, 0x864870AC, 0xEFCF3477, 0xC8B2083E,
+ 0xCCB751C4, 0xEBCA6D8D, 0x824D2956, 0xA530151F
+ }
+#endif /* WORDS_BIGENDIAN */
+};
diff --git a/contrib/libs/libpq/src/port/pg_crc32c_sse42.c b/contrib/libs/libpq/src/port/pg_crc32c_sse42.c
new file mode 100644
index 0000000000..0bac452717
--- /dev/null
+++ b/contrib/libs/libpq/src/port/pg_crc32c_sse42.c
@@ -0,0 +1,69 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_crc32c_sse42.c
+ * Compute CRC-32C checksum using Intel SSE 4.2 instructions.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/port/pg_crc32c_sse42.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "c.h"
+
+#include <nmmintrin.h>
+
+#include "port/pg_crc32c.h"
+
+pg_attribute_no_sanitize_alignment()
+pg_crc32c
+pg_comp_crc32c_sse42(pg_crc32c crc, const void *data, size_t len)
+{
+ const unsigned char *p = data;
+ const unsigned char *pend = p + len;
+
+ /*
+ * Process eight bytes of data at a time.
+ *
+ * NB: We do unaligned accesses here. The Intel architecture allows that,
+ * and performance testing didn't show any performance gain from aligning
+ * the begin address.
+ */
+#ifdef __x86_64__
+ while (p + 8 <= pend)
+ {
+ crc = (uint32) _mm_crc32_u64(crc, *((const uint64 *) p));
+ p += 8;
+ }
+
+ /* Process remaining full four bytes if any */
+ if (p + 4 <= pend)
+ {
+ crc = _mm_crc32_u32(crc, *((const unsigned int *) p));
+ p += 4;
+ }
+#else
+
+ /*
+ * Process four bytes at a time. (The eight byte instruction is not
+ * available on the 32-bit x86 architecture).
+ */
+ while (p + 4 <= pend)
+ {
+ crc = _mm_crc32_u32(crc, *((const unsigned int *) p));
+ p += 4;
+ }
+#endif /* __x86_64__ */
+
+ /* Process any remaining bytes one at a time. */
+ while (p < pend)
+ {
+ crc = _mm_crc32_u8(crc, *p);
+ p++;
+ }
+
+ return crc;
+}
diff --git a/contrib/libs/libpq/src/port/pg_crc32c_sse42_choose.c b/contrib/libs/libpq/src/port/pg_crc32c_sse42_choose.c
new file mode 100644
index 0000000000..41ff4a35ad
--- /dev/null
+++ b/contrib/libs/libpq/src/port/pg_crc32c_sse42_choose.c
@@ -0,0 +1,64 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_crc32c_sse42_choose.c
+ * Choose between Intel SSE 4.2 and software CRC-32C implementation.
+ *
+ * On first call, checks if the CPU we're running on supports Intel SSE
+ * 4.2. If it does, use the special SSE instructions for CRC-32C
+ * computation. Otherwise, fall back to the pure software implementation
+ * (slicing-by-8).
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/port/pg_crc32c_sse42_choose.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "c.h"
+
+#ifdef HAVE__GET_CPUID
+#include <cpuid.h>
+#endif
+
+#ifdef HAVE__CPUID
+#include <intrin.h>
+#endif
+
+#include "port/pg_crc32c.h"
+
+static bool
+pg_crc32c_sse42_available(void)
+{
+ unsigned int exx[4] = {0, 0, 0, 0};
+
+#if defined(HAVE__GET_CPUID)
+ __get_cpuid(1, &exx[0], &exx[1], &exx[2], &exx[3]);
+#elif defined(HAVE__CPUID)
+ __cpuid(exx, 1);
+#else
+#error cpuid instruction not available
+#endif
+
+ return (exx[2] & (1 << 20)) != 0; /* SSE 4.2 */
+}
+
+/*
+ * This gets called on the first call. It replaces the function pointer
+ * so that subsequent calls are routed directly to the chosen implementation.
+ */
+static pg_crc32c
+pg_comp_crc32c_choose(pg_crc32c crc, const void *data, size_t len)
+{
+ if (pg_crc32c_sse42_available())
+ pg_comp_crc32c = pg_comp_crc32c_sse42;
+ else
+ pg_comp_crc32c = pg_comp_crc32c_sb8;
+
+ return pg_comp_crc32c(crc, data, len);
+}
+
+pg_crc32c (*pg_comp_crc32c) (pg_crc32c crc, const void *data, size_t len) = pg_comp_crc32c_choose;
diff --git a/contrib/libs/libpq/src/port/pg_strong_random.c b/contrib/libs/libpq/src/port/pg_strong_random.c
new file mode 100644
index 0000000000..862c84aa6f
--- /dev/null
+++ b/contrib/libs/libpq/src/port/pg_strong_random.c
@@ -0,0 +1,182 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_strong_random.c
+ * generate a cryptographically secure random number
+ *
+ * Our definition of "strong" is that it's suitable for generating random
+ * salts and query cancellation keys, during authentication.
+ *
+ * Note: this code is run quite early in postmaster and backend startup;
+ * therefore, even when built for backend, it cannot rely on backend
+ * infrastructure such as elog() or palloc().
+ *
+ * Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/port/pg_strong_random.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "c.h"
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+/*
+ * pg_strong_random & pg_strong_random_init
+ *
+ * Generate requested number of random bytes. The returned bytes are
+ * cryptographically secure, suitable for use e.g. in authentication.
+ *
+ * Before pg_strong_random is called in any process, the generator must first
+ * be initialized by calling pg_strong_random_init().
+ *
+ * We rely on system facilities for actually generating the numbers.
+ * We support a number of sources:
+ *
+ * 1. OpenSSL's RAND_bytes()
+ * 2. Windows' CryptGenRandom() function
+ * 3. /dev/urandom
+ *
+ * Returns true on success, and false if none of the sources
+ * were available. NB: It is important to check the return value!
+ * Proceeding with key generation when no random data was available
+ * would lead to predictable keys and security issues.
+ */
+
+
+
+#ifdef USE_OPENSSL
+
+#include <openssl/rand.h>
+
+void
+pg_strong_random_init(void)
+{
+ /*
+ * Make sure processes do not share OpenSSL randomness state. This is no
+ * longer required in OpenSSL 1.1.1 and later versions, but until we drop
+ * support for version < 1.1.1 we need to do this.
+ */
+ RAND_poll();
+}
+
+bool
+pg_strong_random(void *buf, size_t len)
+{
+ int i;
+
+ /*
+ * Check that OpenSSL's CSPRNG has been sufficiently seeded, and if not
+ * add more seed data using RAND_poll(). With some older versions of
+ * OpenSSL, it may be necessary to call RAND_poll() a number of times. If
+ * RAND_poll() fails to generate seed data within the given amount of
+ * retries, subsequent RAND_bytes() calls will fail, but we allow that to
+ * happen to let pg_strong_random() callers handle that with appropriate
+ * error handling.
+ */
+#define NUM_RAND_POLL_RETRIES 8
+
+ for (i = 0; i < NUM_RAND_POLL_RETRIES; i++)
+ {
+ if (RAND_status() == 1)
+ {
+ /* The CSPRNG is sufficiently seeded */
+ break;
+ }
+
+ RAND_poll();
+ }
+
+ if (RAND_bytes(buf, len) == 1)
+ return true;
+ return false;
+}
+
+#elif WIN32
+
+#include <wincrypt.h>
+/*
+ * Cache a global crypto provider that only gets freed when the process
+ * exits, in case we need random numbers more than once.
+ */
+static HCRYPTPROV hProvider = 0;
+
+void
+pg_strong_random_init(void)
+{
+ /* No initialization needed on WIN32 */
+}
+
+bool
+pg_strong_random(void *buf, size_t len)
+{
+ if (hProvider == 0)
+ {
+ if (!CryptAcquireContext(&hProvider,
+ NULL,
+ MS_DEF_PROV,
+ PROV_RSA_FULL,
+ CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
+ {
+ /*
+ * On failure, set back to 0 in case the value was for some reason
+ * modified.
+ */
+ hProvider = 0;
+ }
+ }
+ /* Re-check in case we just retrieved the provider */
+ if (hProvider != 0)
+ {
+ if (CryptGenRandom(hProvider, len, buf))
+ return true;
+ }
+ return false;
+}
+
+#else /* not USE_OPENSSL or WIN32 */
+
+/*
+ * Without OpenSSL or Win32 support, just read /dev/urandom ourselves.
+ */
+
+void
+pg_strong_random_init(void)
+{
+ /* No initialization needed */
+}
+
+bool
+pg_strong_random(void *buf, size_t len)
+{
+ int f;
+ char *p = buf;
+ ssize_t res;
+
+ f = open("/dev/urandom", O_RDONLY, 0);
+ if (f == -1)
+ return false;
+
+ while (len)
+ {
+ res = read(f, p, len);
+ if (res <= 0)
+ {
+ if (errno == EINTR)
+ continue; /* interrupted by signal, just retry */
+
+ close(f);
+ return false;
+ }
+
+ p += res;
+ len -= res;
+ }
+
+ close(f);
+ return true;
+}
+#endif
diff --git a/contrib/libs/libpq/src/port/pgcheckdir.c b/contrib/libs/libpq/src/port/pgcheckdir.c
new file mode 100644
index 0000000000..94aa40ca8f
--- /dev/null
+++ b/contrib/libs/libpq/src/port/pgcheckdir.c
@@ -0,0 +1,92 @@
+/*-------------------------------------------------------------------------
+ *
+ * pgcheckdir.c
+ *
+ * A simple subroutine to check whether a directory exists and is empty or not.
+ * Useful in both initdb and the backend.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/port/pgcheckdir.c
+ *-------------------------------------------------------------------------
+ */
+
+#include "c.h"
+
+#include <dirent.h>
+
+
+/*
+ * Test to see if a directory exists and is empty or not.
+ *
+ * Returns:
+ * 0 if nonexistent
+ * 1 if exists and empty
+ * 2 if exists and contains _only_ dot files
+ * 3 if exists and contains a mount point
+ * 4 if exists and not empty
+ * -1 if trouble accessing directory (errno reflects the error)
+ */
+int
+pg_check_dir(const char *dir)
+{
+ int result = 1;
+ DIR *chkdir;
+ struct dirent *file;
+ bool dot_found = false;
+ bool mount_found = false;
+ int readdir_errno;
+
+ chkdir = opendir(dir);
+ if (chkdir == NULL)
+ return (errno == ENOENT) ? 0 : -1;
+
+ while (errno = 0, (file = readdir(chkdir)) != NULL)
+ {
+ if (strcmp(".", file->d_name) == 0 ||
+ strcmp("..", file->d_name) == 0)
+ {
+ /* skip this and parent directory */
+ continue;
+ }
+#ifndef WIN32
+ /* file starts with "." */
+ else if (file->d_name[0] == '.')
+ {
+ dot_found = true;
+ }
+ /* lost+found directory */
+ else if (strcmp("lost+found", file->d_name) == 0)
+ {
+ mount_found = true;
+ }
+#endif
+ else
+ {
+ result = 4; /* not empty */
+ break;
+ }
+ }
+
+ if (errno)
+ result = -1; /* some kind of I/O error? */
+
+ /* Close chkdir and avoid overwriting the readdir errno on success */
+ readdir_errno = errno;
+ if (closedir(chkdir))
+ result = -1; /* error executing closedir */
+ else
+ errno = readdir_errno;
+
+ /* We report on mount point if we find a lost+found directory */
+ if (result == 1 && mount_found)
+ result = 3;
+
+ /* We report on dot-files if we _only_ find dot files */
+ if (result == 1 && dot_found)
+ result = 2;
+
+ return result;
+}
diff --git a/contrib/libs/libpq/src/port/pgmkdirp.c b/contrib/libs/libpq/src/port/pgmkdirp.c
new file mode 100644
index 0000000000..d943559760
--- /dev/null
+++ b/contrib/libs/libpq/src/port/pgmkdirp.c
@@ -0,0 +1,148 @@
+/*
+ * This is adapted from FreeBSD's src/bin/mkdir/mkdir.c, which bears
+ * the following copyright notice:
+ *
+ * Copyright (c) 1983, 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "c.h"
+
+#include <sys/stat.h>
+
+
+/*
+ * pg_mkdir_p --- create a directory and, if necessary, parent directories
+ *
+ * This is equivalent to "mkdir -p" except we don't complain if the target
+ * directory already exists.
+ *
+ * We assume the path is in canonical form, i.e., uses / as the separator.
+ *
+ * omode is the file permissions bits for the target directory. Note that any
+ * parent directories that have to be created get permissions according to the
+ * prevailing umask, but with u+wx forced on to ensure we can create there.
+ * (We declare omode as int, not mode_t, to minimize dependencies for port.h.)
+ *
+ * Returns 0 on success, -1 (with errno set) on failure.
+ *
+ * Note that on failure, the path arg has been modified to show the particular
+ * directory level we had problems with.
+ */
+int
+pg_mkdir_p(char *path, int omode)
+{
+ struct stat sb;
+ mode_t numask,
+ oumask;
+ int last,
+ retval;
+ char *p;
+
+ retval = 0;
+ p = path;
+
+#ifdef WIN32
+ /* skip network and drive specifiers for win32 */
+ if (strlen(p) >= 2)
+ {
+ if (p[0] == '/' && p[1] == '/')
+ {
+ /* network drive */
+ p = strstr(p + 2, "/");
+ if (p == NULL)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ }
+ else if (p[1] == ':' &&
+ ((p[0] >= 'a' && p[0] <= 'z') ||
+ (p[0] >= 'A' && p[0] <= 'Z')))
+ {
+ /* local drive */
+ p += 2;
+ }
+ }
+#endif
+
+ /*
+ * POSIX 1003.2: For each dir operand that does not name an existing
+ * directory, effects equivalent to those caused by the following command
+ * shall occur:
+ *
+ * mkdir -p -m $(umask -S),u+wx $(dirname dir) && mkdir [-m mode] dir
+ *
+ * We change the user's umask and then restore it, instead of doing
+ * chmod's. Note we assume umask() can't change errno.
+ */
+ oumask = umask(0);
+ numask = oumask & ~(S_IWUSR | S_IXUSR);
+ (void) umask(numask);
+
+ if (p[0] == '/') /* Skip leading '/'. */
+ ++p;
+ for (last = 0; !last; ++p)
+ {
+ if (p[0] == '\0')
+ last = 1;
+ else if (p[0] != '/')
+ continue;
+ *p = '\0';
+ if (!last && p[1] == '\0')
+ last = 1;
+
+ if (last)
+ (void) umask(oumask);
+
+ /* check for pre-existing directory */
+ if (stat(path, &sb) == 0)
+ {
+ if (!S_ISDIR(sb.st_mode))
+ {
+ if (last)
+ errno = EEXIST;
+ else
+ errno = ENOTDIR;
+ retval = -1;
+ break;
+ }
+ }
+ else if (mkdir(path, last ? omode : S_IRWXU | S_IRWXG | S_IRWXO) < 0)
+ {
+ retval = -1;
+ break;
+ }
+ if (!last)
+ *p = '/';
+ }
+
+ /* ensure we restored umask */
+ (void) umask(oumask);
+
+ return retval;
+}
diff --git a/contrib/libs/libpq/src/port/pgsleep.c b/contrib/libs/libpq/src/port/pgsleep.c
new file mode 100644
index 0000000000..a1bcd78e4b
--- /dev/null
+++ b/contrib/libs/libpq/src/port/pgsleep.c
@@ -0,0 +1,57 @@
+/*-------------------------------------------------------------------------
+ *
+ * pgsleep.c
+ * Portable delay handling.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ *
+ * src/port/pgsleep.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "c.h"
+
+#include <time.h>
+
+/*
+ * In a Windows backend, we don't use this implementation, but rather
+ * the signal-aware version in src/backend/port/win32/signal.c.
+ */
+#if defined(FRONTEND) || !defined(WIN32)
+
+/*
+ * pg_usleep --- delay the specified number of microseconds.
+ *
+ * NOTE: Although the delay is specified in microseconds, older Unixen and
+ * Windows use periodic kernel ticks to wake up, which might increase the delay
+ * time significantly. We've observed delay increases as large as 20
+ * milliseconds on supported platforms.
+ *
+ * On machines where "long" is 32 bits, the maximum delay is ~2000 seconds.
+ *
+ * CAUTION: It's not a good idea to use long sleeps in the backend. They will
+ * silently return early if a signal is caught, but that doesn't include
+ * latches being set on most OSes, and even signal handlers that set MyLatch
+ * might happen to run before the sleep begins, allowing the full delay.
+ * Better practice is to use WaitLatch() with a timeout, so that backends
+ * respond to latches and signals promptly.
+ */
+void
+pg_usleep(long microsec)
+{
+ if (microsec > 0)
+ {
+#ifndef WIN32
+ struct timespec delay;
+
+ delay.tv_sec = microsec / 1000000L;
+ delay.tv_nsec = (microsec % 1000000L) * 1000;
+ (void) nanosleep(&delay, NULL);
+#else
+ SleepEx((microsec < 500 ? 1 : (microsec + 500) / 1000), FALSE);
+#endif
+ }
+}
+
+#endif /* defined(FRONTEND) || !defined(WIN32) */
diff --git a/contrib/libs/libpq/src/port/pgstrcasecmp.c b/contrib/libs/libpq/src/port/pgstrcasecmp.c
new file mode 100644
index 0000000000..27c1546f6f
--- /dev/null
+++ b/contrib/libs/libpq/src/port/pgstrcasecmp.c
@@ -0,0 +1,151 @@
+/*-------------------------------------------------------------------------
+ *
+ * pgstrcasecmp.c
+ * Portable SQL-like case-independent comparisons and conversions.
+ *
+ * SQL99 specifies Unicode-aware case normalization, which we don't yet
+ * have the infrastructure for. Instead we use tolower() to provide a
+ * locale-aware translation. However, there are some locales where this
+ * is not right either (eg, Turkish may do strange things with 'i' and
+ * 'I'). Our current compromise is to use tolower() for characters with
+ * the high bit set, and use an ASCII-only downcasing for 7-bit
+ * characters.
+ *
+ * NB: this code should match downcase_truncate_identifier() in scansup.c.
+ *
+ * We also provide strict ASCII-only case conversion functions, which can
+ * be used to implement C/POSIX case folding semantics no matter what the
+ * C library thinks the locale is.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ *
+ * src/port/pgstrcasecmp.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "c.h"
+
+#include <ctype.h>
+
+
+/*
+ * Case-independent comparison of two null-terminated strings.
+ */
+int
+pg_strcasecmp(const char *s1, const char *s2)
+{
+ for (;;)
+ {
+ unsigned char ch1 = (unsigned char) *s1++;
+ unsigned char ch2 = (unsigned char) *s2++;
+
+ if (ch1 != ch2)
+ {
+ if (ch1 >= 'A' && ch1 <= 'Z')
+ ch1 += 'a' - 'A';
+ else if (IS_HIGHBIT_SET(ch1) && isupper(ch1))
+ ch1 = tolower(ch1);
+
+ if (ch2 >= 'A' && ch2 <= 'Z')
+ ch2 += 'a' - 'A';
+ else if (IS_HIGHBIT_SET(ch2) && isupper(ch2))
+ ch2 = tolower(ch2);
+
+ if (ch1 != ch2)
+ return (int) ch1 - (int) ch2;
+ }
+ if (ch1 == 0)
+ break;
+ }
+ return 0;
+}
+
+/*
+ * Case-independent comparison of two not-necessarily-null-terminated strings.
+ * At most n bytes will be examined from each string.
+ */
+int
+pg_strncasecmp(const char *s1, const char *s2, size_t n)
+{
+ while (n-- > 0)
+ {
+ unsigned char ch1 = (unsigned char) *s1++;
+ unsigned char ch2 = (unsigned char) *s2++;
+
+ if (ch1 != ch2)
+ {
+ if (ch1 >= 'A' && ch1 <= 'Z')
+ ch1 += 'a' - 'A';
+ else if (IS_HIGHBIT_SET(ch1) && isupper(ch1))
+ ch1 = tolower(ch1);
+
+ if (ch2 >= 'A' && ch2 <= 'Z')
+ ch2 += 'a' - 'A';
+ else if (IS_HIGHBIT_SET(ch2) && isupper(ch2))
+ ch2 = tolower(ch2);
+
+ if (ch1 != ch2)
+ return (int) ch1 - (int) ch2;
+ }
+ if (ch1 == 0)
+ break;
+ }
+ return 0;
+}
+
+/*
+ * Fold a character to upper case.
+ *
+ * Unlike some versions of toupper(), this is safe to apply to characters
+ * that aren't lower case letters. Note however that the whole thing is
+ * a bit bogus for multibyte character sets.
+ */
+unsigned char
+pg_toupper(unsigned char ch)
+{
+ if (ch >= 'a' && ch <= 'z')
+ ch += 'A' - 'a';
+ else if (IS_HIGHBIT_SET(ch) && islower(ch))
+ ch = toupper(ch);
+ return ch;
+}
+
+/*
+ * Fold a character to lower case.
+ *
+ * Unlike some versions of tolower(), this is safe to apply to characters
+ * that aren't upper case letters. Note however that the whole thing is
+ * a bit bogus for multibyte character sets.
+ */
+unsigned char
+pg_tolower(unsigned char ch)
+{
+ if (ch >= 'A' && ch <= 'Z')
+ ch += 'a' - 'A';
+ else if (IS_HIGHBIT_SET(ch) && isupper(ch))
+ ch = tolower(ch);
+ return ch;
+}
+
+/*
+ * Fold a character to upper case, following C/POSIX locale rules.
+ */
+unsigned char
+pg_ascii_toupper(unsigned char ch)
+{
+ if (ch >= 'a' && ch <= 'z')
+ ch += 'A' - 'a';
+ return ch;
+}
+
+/*
+ * Fold a character to lower case, following C/POSIX locale rules.
+ */
+unsigned char
+pg_ascii_tolower(unsigned char ch)
+{
+ if (ch >= 'A' && ch <= 'Z')
+ ch += 'a' - 'A';
+ return ch;
+}
diff --git a/contrib/libs/libpq/src/port/pgstrsignal.c b/contrib/libs/libpq/src/port/pgstrsignal.c
new file mode 100644
index 0000000000..7d76d1cca9
--- /dev/null
+++ b/contrib/libs/libpq/src/port/pgstrsignal.c
@@ -0,0 +1,64 @@
+/*-------------------------------------------------------------------------
+ *
+ * pgstrsignal.c
+ * Identify a Unix signal number
+ *
+ * On platforms compliant with modern POSIX, this just wraps strsignal(3).
+ * Elsewhere, we do the best we can.
+ *
+ * This file is not currently built in MSVC builds, since it's useless
+ * on non-Unix platforms.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/port/pgstrsignal.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "c.h"
+
+
+/*
+ * pg_strsignal
+ *
+ * Return a string identifying the given Unix signal number.
+ *
+ * The result is declared "const char *" because callers should not
+ * modify the string. Note, however, that POSIX does not promise that
+ * the string will remain valid across later calls to strsignal().
+ *
+ * This version guarantees to return a non-NULL pointer, although
+ * some platforms' versions of strsignal() reputedly do not.
+ *
+ * Note that the fallback cases just return constant strings such as
+ * "unrecognized signal". Project style is for callers to print the
+ * numeric signal value along with the result of this function, so
+ * there's no need to work harder than that.
+ */
+const char *
+pg_strsignal(int signum)
+{
+ const char *result;
+
+ /*
+ * If we have strsignal(3), use that --- but check its result for NULL.
+ */
+#ifdef HAVE_STRSIGNAL
+ result = strsignal(signum);
+ if (result == NULL)
+ result = "unrecognized signal";
+#else
+
+ /*
+ * We used to have code here to try to use sys_siglist[] if available.
+ * However, it seems that all platforms with sys_siglist[] have also had
+ * strsignal() for many years now, so that was just a waste of code.
+ */
+ result = "(signal names not available on this platform)";
+#endif
+
+ return result;
+}
diff --git a/contrib/libs/libpq/src/port/pqsignal.c b/contrib/libs/libpq/src/port/pqsignal.c
new file mode 100644
index 0000000000..de9ed2c566
--- /dev/null
+++ b/contrib/libs/libpq/src/port/pqsignal.c
@@ -0,0 +1,62 @@
+/*-------------------------------------------------------------------------
+ *
+ * pqsignal.c
+ * reliable BSD-style signal(2) routine stolen from RWW who stole it
+ * from Stevens...
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/port/pqsignal.c
+ *
+ * We now assume that all Unix-oid systems have POSIX sigaction(2)
+ * with support for restartable signals (SA_RESTART). We used to also
+ * support BSD-style signal(2), but there really shouldn't be anything
+ * out there anymore that doesn't have the POSIX API.
+ *
+ * Windows, of course, is resolutely in a class by itself. In the backend,
+ * we don't use this file at all; src/backend/port/win32/signal.c provides
+ * pqsignal() for the backend environment. Frontend programs can use
+ * this version of pqsignal() if they wish, but beware that this does
+ * not provide restartable signals on Windows.
+ *
+ * ------------------------------------------------------------------------
+ */
+
+#include "c.h"
+
+#include <signal.h>
+
+#ifndef FRONTEND
+#error #include "libpq/pqsignal.h"
+#endif
+
+/*
+ * Set up a signal handler, with SA_RESTART, for signal "signo"
+ *
+ * Returns the previous handler.
+ */
+pqsigfunc
+pqsignal(int signo, pqsigfunc func)
+{
+#if !(defined(WIN32) && defined(FRONTEND))
+ struct sigaction act,
+ oact;
+
+ act.sa_handler = func;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_RESTART;
+#ifdef SA_NOCLDSTOP
+ if (signo == SIGCHLD)
+ act.sa_flags |= SA_NOCLDSTOP;
+#endif
+ if (sigaction(signo, &act, &oact) < 0)
+ return SIG_ERR;
+ return oact.sa_handler;
+#else
+ /* Forward to Windows native signal system. */
+ return signal(signo, func);
+#endif
+}
diff --git a/contrib/libs/libpq/src/port/pthread-win32.h b/contrib/libs/libpq/src/port/pthread-win32.h
new file mode 100644
index 0000000000..97ccc17a12
--- /dev/null
+++ b/contrib/libs/libpq/src/port/pthread-win32.h
@@ -0,0 +1,22 @@
+/*
+ * src/port/pthread-win32.h
+ */
+#ifndef __PTHREAD_H
+#define __PTHREAD_H
+
+typedef ULONG pthread_key_t;
+typedef CRITICAL_SECTION *pthread_mutex_t;
+typedef int pthread_once_t;
+
+DWORD pthread_self(void);
+
+void pthread_setspecific(pthread_key_t, void *);
+void *pthread_getspecific(pthread_key_t);
+
+int pthread_mutex_init(pthread_mutex_t *, void *attr);
+int pthread_mutex_lock(pthread_mutex_t *);
+
+/* blocking */
+int pthread_mutex_unlock(pthread_mutex_t *);
+
+#endif
diff --git a/contrib/libs/libpq/src/port/qsort.c b/contrib/libs/libpq/src/port/qsort.c
new file mode 100644
index 0000000000..7879e6cd56
--- /dev/null
+++ b/contrib/libs/libpq/src/port/qsort.c
@@ -0,0 +1,22 @@
+/*
+ * qsort.c: standard quicksort algorithm
+ */
+
+#include "c.h"
+
+#define ST_SORT pg_qsort
+#define ST_ELEMENT_TYPE_VOID
+#define ST_COMPARE_RUNTIME_POINTER
+#define ST_SCOPE
+#define ST_DECLARE
+#define ST_DEFINE
+#include "lib/sort_template.h"
+
+/*
+ * qsort comparator wrapper for strcmp.
+ */
+int
+pg_qsort_strcmp(const void *a, const void *b)
+{
+ return strcmp(*(const char *const *) a, *(const char *const *) b);
+}
diff --git a/contrib/libs/libpq/src/port/qsort_arg.c b/contrib/libs/libpq/src/port/qsort_arg.c
new file mode 100644
index 0000000000..fa7e11a3b8
--- /dev/null
+++ b/contrib/libs/libpq/src/port/qsort_arg.c
@@ -0,0 +1,14 @@
+/*
+ * qsort_arg.c: qsort with a passthrough "void *" argument
+ */
+
+#include "c.h"
+
+#define ST_SORT qsort_arg
+#define ST_ELEMENT_TYPE_VOID
+#define ST_COMPARATOR_TYPE_NAME qsort_arg_comparator
+#define ST_COMPARE_RUNTIME_POINTER
+#define ST_COMPARE_ARG_TYPE void
+#define ST_SCOPE
+#define ST_DEFINE
+#include "lib/sort_template.h"
diff --git a/contrib/libs/libpq/src/port/quotes.c b/contrib/libs/libpq/src/port/quotes.c
new file mode 100644
index 0000000000..a80e88d69b
--- /dev/null
+++ b/contrib/libs/libpq/src/port/quotes.c
@@ -0,0 +1,51 @@
+/*-------------------------------------------------------------------------
+ *
+ * quotes.c
+ * string quoting and escaping functions
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/port/quotes.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "c.h"
+
+/*
+ * Escape (by doubling) any single quotes or backslashes in given string
+ *
+ * Note: this is used to process postgresql.conf entries and to quote
+ * string literals in pg_basebackup for writing the recovery configuration.
+ * Since postgresql.conf strings are defined to treat backslashes as escapes,
+ * we have to double backslashes here.
+ *
+ * Since this function is only used for parsing or creating configuration
+ * files, we do not care about encoding considerations.
+ *
+ * Returns a malloced() string that it's the responsibility of the caller
+ * to free.
+ */
+char *
+escape_single_quotes_ascii(const char *src)
+{
+ int len = strlen(src),
+ i,
+ j;
+ char *result = malloc(len * 2 + 1);
+
+ if (!result)
+ return NULL;
+
+ for (i = 0, j = 0; i < len; i++)
+ {
+ if (SQL_STR_DOUBLE(src[i], true))
+ result[j++] = src[i];
+ result[j++] = src[i];
+ }
+ result[j] = '\0';
+ return result;
+}
diff --git a/contrib/libs/libpq/src/port/snprintf.c b/contrib/libs/libpq/src/port/snprintf.c
new file mode 100644
index 0000000000..e3e316e049
--- /dev/null
+++ b/contrib/libs/libpq/src/port/snprintf.c
@@ -0,0 +1,1535 @@
+/*
+ * Copyright (c) 1983, 1995, 1996 Eric P. Allman
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * src/port/snprintf.c
+ */
+
+#include "c.h"
+
+#include <math.h>
+
+/*
+ * We used to use the platform's NL_ARGMAX here, but that's a bad idea,
+ * first because the point of this module is to remove platform dependencies
+ * not perpetuate them, and second because some platforms use ridiculously
+ * large values, leading to excessive stack consumption in dopr().
+ */
+#define PG_NL_ARGMAX 31
+
+
+/*
+ * SNPRINTF, VSNPRINTF and friends
+ *
+ * These versions have been grabbed off the net. They have been
+ * cleaned up to compile properly and support for most of the C99
+ * specification has been added. Remaining unimplemented features are:
+ *
+ * 1. No locale support: the radix character is always '.' and the '
+ * (single quote) format flag is ignored.
+ *
+ * 2. No support for the "%n" format specification.
+ *
+ * 3. No support for wide characters ("lc" and "ls" formats).
+ *
+ * 4. No support for "long double" ("Lf" and related formats).
+ *
+ * 5. Space and '#' flags are not implemented.
+ *
+ * In addition, we support some extensions over C99:
+ *
+ * 1. Argument order control through "%n$" and "*n$", as required by POSIX.
+ *
+ * 2. "%m" expands to the value of strerror(errno), where errno is the
+ * value that variable had at the start of the call. This is a glibc
+ * extension, but a very useful one.
+ *
+ *
+ * Historically the result values of sprintf/snprintf varied across platforms.
+ * This implementation now follows the C99 standard:
+ *
+ * 1. -1 is returned if an error is detected in the format string, or if
+ * a write to the target stream fails (as reported by fwrite). Note that
+ * overrunning snprintf's target buffer is *not* an error.
+ *
+ * 2. For successful writes to streams, the actual number of bytes written
+ * to the stream is returned.
+ *
+ * 3. For successful sprintf/snprintf, the number of bytes that would have
+ * been written to an infinite-size buffer (excluding the trailing '\0')
+ * is returned. snprintf will truncate its output to fit in the buffer
+ * (ensuring a trailing '\0' unless count == 0), but this is not reflected
+ * in the function result.
+ *
+ * snprintf buffer overrun can be detected by checking for function result
+ * greater than or equal to the supplied count.
+ */
+
+/**************************************************************
+ * Original:
+ * Patrick Powell Tue Apr 11 09:48:21 PDT 1995
+ * A bombproof version of doprnt (dopr) included.
+ * Sigh. This sort of thing is always nasty do deal with. Note that
+ * the version here does not include floating point. (now it does ... tgl)
+ **************************************************************/
+
+/* Prevent recursion */
+#undef vsnprintf
+#undef snprintf
+#undef vsprintf
+#undef sprintf
+#undef vfprintf
+#undef fprintf
+#undef vprintf
+#undef printf
+
+/*
+ * Info about where the formatted output is going.
+ *
+ * dopr and subroutines will not write at/past bufend, but snprintf
+ * reserves one byte, ensuring it may place the trailing '\0' there.
+ *
+ * In snprintf, we use nchars to count the number of bytes dropped on the
+ * floor due to buffer overrun. The correct result of snprintf is thus
+ * (bufptr - bufstart) + nchars. (This isn't as inconsistent as it might
+ * seem: nchars is the number of emitted bytes that are not in the buffer now,
+ * either because we sent them to the stream or because we couldn't fit them
+ * into the buffer to begin with.)
+ */
+typedef struct
+{
+ char *bufptr; /* next buffer output position */
+ char *bufstart; /* first buffer element */
+ char *bufend; /* last+1 buffer element, or NULL */
+ /* bufend == NULL is for sprintf, where we assume buf is big enough */
+ FILE *stream; /* eventual output destination, or NULL */
+ int nchars; /* # chars sent to stream, or dropped */
+ bool failed; /* call is a failure; errno is set */
+} PrintfTarget;
+
+/*
+ * Info about the type and value of a formatting parameter. Note that we
+ * don't currently support "long double", "wint_t", or "wchar_t *" data,
+ * nor the '%n' formatting code; else we'd need more types. Also, at this
+ * level we need not worry about signed vs unsigned values.
+ */
+typedef enum
+{
+ ATYPE_NONE = 0,
+ ATYPE_INT,
+ ATYPE_LONG,
+ ATYPE_LONGLONG,
+ ATYPE_DOUBLE,
+ ATYPE_CHARPTR
+} PrintfArgType;
+
+typedef union
+{
+ int i;
+ long l;
+ long long ll;
+ double d;
+ char *cptr;
+} PrintfArgValue;
+
+
+static void flushbuffer(PrintfTarget *target);
+static void dopr(PrintfTarget *target, const char *format, va_list args);
+
+
+/*
+ * Externally visible entry points.
+ *
+ * All of these are just wrappers around dopr(). Note it's essential that
+ * they not change the value of "errno" before reaching dopr().
+ */
+
+int
+pg_vsnprintf(char *str, size_t count, const char *fmt, va_list args)
+{
+ PrintfTarget target;
+ char onebyte[1];
+
+ /*
+ * C99 allows the case str == NULL when count == 0. Rather than
+ * special-casing this situation further down, we substitute a one-byte
+ * local buffer. Callers cannot tell, since the function result doesn't
+ * depend on count.
+ */
+ if (count == 0)
+ {
+ str = onebyte;
+ count = 1;
+ }
+ target.bufstart = target.bufptr = str;
+ target.bufend = str + count - 1;
+ target.stream = NULL;
+ target.nchars = 0;
+ target.failed = false;
+ dopr(&target, fmt, args);
+ *(target.bufptr) = '\0';
+ return target.failed ? -1 : (target.bufptr - target.bufstart
+ + target.nchars);
+}
+
+int
+pg_snprintf(char *str, size_t count, const char *fmt,...)
+{
+ int len;
+ va_list args;
+
+ va_start(args, fmt);
+ len = pg_vsnprintf(str, count, fmt, args);
+ va_end(args);
+ return len;
+}
+
+int
+pg_vsprintf(char *str, const char *fmt, va_list args)
+{
+ PrintfTarget target;
+
+ target.bufstart = target.bufptr = str;
+ target.bufend = NULL;
+ target.stream = NULL;
+ target.nchars = 0; /* not really used in this case */
+ target.failed = false;
+ dopr(&target, fmt, args);
+ *(target.bufptr) = '\0';
+ return target.failed ? -1 : (target.bufptr - target.bufstart
+ + target.nchars);
+}
+
+int
+pg_sprintf(char *str, const char *fmt,...)
+{
+ int len;
+ va_list args;
+
+ va_start(args, fmt);
+ len = pg_vsprintf(str, fmt, args);
+ va_end(args);
+ return len;
+}
+
+int
+pg_vfprintf(FILE *stream, const char *fmt, va_list args)
+{
+ PrintfTarget target;
+ char buffer[1024]; /* size is arbitrary */
+
+ if (stream == NULL)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ target.bufstart = target.bufptr = buffer;
+ target.bufend = buffer + sizeof(buffer); /* use the whole buffer */
+ target.stream = stream;
+ target.nchars = 0;
+ target.failed = false;
+ dopr(&target, fmt, args);
+ /* dump any remaining buffer contents */
+ flushbuffer(&target);
+ return target.failed ? -1 : target.nchars;
+}
+
+int
+pg_fprintf(FILE *stream, const char *fmt,...)
+{
+ int len;
+ va_list args;
+
+ va_start(args, fmt);
+ len = pg_vfprintf(stream, fmt, args);
+ va_end(args);
+ return len;
+}
+
+int
+pg_vprintf(const char *fmt, va_list args)
+{
+ return pg_vfprintf(stdout, fmt, args);
+}
+
+int
+pg_printf(const char *fmt,...)
+{
+ int len;
+ va_list args;
+
+ va_start(args, fmt);
+ len = pg_vfprintf(stdout, fmt, args);
+ va_end(args);
+ return len;
+}
+
+/*
+ * Attempt to write the entire buffer to target->stream; discard the entire
+ * buffer in any case. Call this only when target->stream is defined.
+ */
+static void
+flushbuffer(PrintfTarget *target)
+{
+ size_t nc = target->bufptr - target->bufstart;
+
+ /*
+ * Don't write anything if we already failed; this is to ensure we
+ * preserve the original failure's errno.
+ */
+ if (!target->failed && nc > 0)
+ {
+ size_t written;
+
+ written = fwrite(target->bufstart, 1, nc, target->stream);
+ target->nchars += written;
+ if (written != nc)
+ target->failed = true;
+ }
+ target->bufptr = target->bufstart;
+}
+
+
+static bool find_arguments(const char *format, va_list args,
+ PrintfArgValue *argvalues);
+static void fmtstr(const char *value, int leftjust, int minlen, int maxwidth,
+ int pointflag, PrintfTarget *target);
+static void fmtptr(const void *value, PrintfTarget *target);
+static void fmtint(long long value, char type, int forcesign,
+ int leftjust, int minlen, int zpad, int precision, int pointflag,
+ PrintfTarget *target);
+static void fmtchar(int value, int leftjust, int minlen, PrintfTarget *target);
+static void fmtfloat(double value, char type, int forcesign,
+ int leftjust, int minlen, int zpad, int precision, int pointflag,
+ PrintfTarget *target);
+static void dostr(const char *str, int slen, PrintfTarget *target);
+static void dopr_outch(int c, PrintfTarget *target);
+static void dopr_outchmulti(int c, int slen, PrintfTarget *target);
+static int adjust_sign(int is_negative, int forcesign, int *signvalue);
+static int compute_padlen(int minlen, int vallen, int leftjust);
+static void leading_pad(int zpad, int signvalue, int *padlen,
+ PrintfTarget *target);
+static void trailing_pad(int padlen, PrintfTarget *target);
+
+/*
+ * If strchrnul exists (it's a glibc-ism), it's a good bit faster than the
+ * equivalent manual loop. If it doesn't exist, provide a replacement.
+ *
+ * Note: glibc declares this as returning "char *", but that would require
+ * casting away const internally, so we don't follow that detail.
+ */
+#ifndef HAVE_STRCHRNUL
+
+static inline const char *
+strchrnul(const char *s, int c)
+{
+ while (*s != '\0' && *s != c)
+ s++;
+ return s;
+}
+
+#else
+
+/*
+ * glibc's <string.h> declares strchrnul only if _GNU_SOURCE is defined.
+ * While we typically use that on glibc platforms, configure will set
+ * HAVE_STRCHRNUL whether it's used or not. Fill in the missing declaration
+ * so that this file will compile cleanly with or without _GNU_SOURCE.
+ */
+#ifndef _GNU_SOURCE
+extern char *strchrnul(const char *s, int c);
+#endif
+
+#endif /* HAVE_STRCHRNUL */
+
+
+/*
+ * dopr(): the guts of *printf for all cases.
+ */
+static void
+dopr(PrintfTarget *target, const char *format, va_list args)
+{
+ int save_errno = errno;
+ const char *first_pct = NULL;
+ int ch;
+ bool have_dollar;
+ bool have_star;
+ bool afterstar;
+ int accum;
+ int longlongflag;
+ int longflag;
+ int pointflag;
+ int leftjust;
+ int fieldwidth;
+ int precision;
+ int zpad;
+ int forcesign;
+ int fmtpos;
+ int cvalue;
+ long long numvalue;
+ double fvalue;
+ const char *strvalue;
+ PrintfArgValue argvalues[PG_NL_ARGMAX + 1];
+
+ /*
+ * Initially, we suppose the format string does not use %n$. The first
+ * time we come to a conversion spec that has that, we'll call
+ * find_arguments() to check for consistent use of %n$ and fill the
+ * argvalues array with the argument values in the correct order.
+ */
+ have_dollar = false;
+
+ while (*format != '\0')
+ {
+ /* Locate next conversion specifier */
+ if (*format != '%')
+ {
+ /* Scan to next '%' or end of string */
+ const char *next_pct = strchrnul(format + 1, '%');
+
+ /* Dump literal data we just scanned over */
+ dostr(format, next_pct - format, target);
+ if (target->failed)
+ break;
+
+ if (*next_pct == '\0')
+ break;
+ format = next_pct;
+ }
+
+ /*
+ * Remember start of first conversion spec; if we find %n$, then it's
+ * sufficient for find_arguments() to start here, without rescanning
+ * earlier literal text.
+ */
+ if (first_pct == NULL)
+ first_pct = format;
+
+ /* Process conversion spec starting at *format */
+ format++;
+
+ /* Fast path for conversion spec that is exactly %s */
+ if (*format == 's')
+ {
+ format++;
+ strvalue = va_arg(args, char *);
+ if (strvalue == NULL)
+ strvalue = "(null)";
+ dostr(strvalue, strlen(strvalue), target);
+ if (target->failed)
+ break;
+ continue;
+ }
+
+ fieldwidth = precision = zpad = leftjust = forcesign = 0;
+ longflag = longlongflag = pointflag = 0;
+ fmtpos = accum = 0;
+ have_star = afterstar = false;
+nextch2:
+ ch = *format++;
+ switch (ch)
+ {
+ case '-':
+ leftjust = 1;
+ goto nextch2;
+ case '+':
+ forcesign = 1;
+ goto nextch2;
+ case '0':
+ /* set zero padding if no nonzero digits yet */
+ if (accum == 0 && !pointflag)
+ zpad = '0';
+ /* FALL THRU */
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ accum = accum * 10 + (ch - '0');
+ goto nextch2;
+ case '.':
+ if (have_star)
+ have_star = false;
+ else
+ fieldwidth = accum;
+ pointflag = 1;
+ accum = 0;
+ goto nextch2;
+ case '*':
+ if (have_dollar)
+ {
+ /*
+ * We'll process value after reading n$. Note it's OK to
+ * assume have_dollar is set correctly, because in a valid
+ * format string the initial % must have had n$ if * does.
+ */
+ afterstar = true;
+ }
+ else
+ {
+ /* fetch and process value now */
+ int starval = va_arg(args, int);
+
+ if (pointflag)
+ {
+ precision = starval;
+ if (precision < 0)
+ {
+ precision = 0;
+ pointflag = 0;
+ }
+ }
+ else
+ {
+ fieldwidth = starval;
+ if (fieldwidth < 0)
+ {
+ leftjust = 1;
+ fieldwidth = -fieldwidth;
+ }
+ }
+ }
+ have_star = true;
+ accum = 0;
+ goto nextch2;
+ case '$':
+ /* First dollar sign? */
+ if (!have_dollar)
+ {
+ /* Yup, so examine all conversion specs in format */
+ if (!find_arguments(first_pct, args, argvalues))
+ goto bad_format;
+ have_dollar = true;
+ }
+ if (afterstar)
+ {
+ /* fetch and process star value */
+ int starval = argvalues[accum].i;
+
+ if (pointflag)
+ {
+ precision = starval;
+ if (precision < 0)
+ {
+ precision = 0;
+ pointflag = 0;
+ }
+ }
+ else
+ {
+ fieldwidth = starval;
+ if (fieldwidth < 0)
+ {
+ leftjust = 1;
+ fieldwidth = -fieldwidth;
+ }
+ }
+ afterstar = false;
+ }
+ else
+ fmtpos = accum;
+ accum = 0;
+ goto nextch2;
+ case 'l':
+ if (longflag)
+ longlongflag = 1;
+ else
+ longflag = 1;
+ goto nextch2;
+ case 'z':
+#if SIZEOF_SIZE_T == 8
+#ifdef HAVE_LONG_INT_64
+ longflag = 1;
+#elif defined(HAVE_LONG_LONG_INT_64)
+ longlongflag = 1;
+#else
+#error "Don't know how to print 64bit integers"
+#endif
+#else
+ /* assume size_t is same size as int */
+#endif
+ goto nextch2;
+ case 'h':
+ case '\'':
+ /* ignore these */
+ goto nextch2;
+ case 'd':
+ case 'i':
+ if (!have_star)
+ {
+ if (pointflag)
+ precision = accum;
+ else
+ fieldwidth = accum;
+ }
+ if (have_dollar)
+ {
+ if (longlongflag)
+ numvalue = argvalues[fmtpos].ll;
+ else if (longflag)
+ numvalue = argvalues[fmtpos].l;
+ else
+ numvalue = argvalues[fmtpos].i;
+ }
+ else
+ {
+ if (longlongflag)
+ numvalue = va_arg(args, long long);
+ else if (longflag)
+ numvalue = va_arg(args, long);
+ else
+ numvalue = va_arg(args, int);
+ }
+ fmtint(numvalue, ch, forcesign, leftjust, fieldwidth, zpad,
+ precision, pointflag, target);
+ break;
+ case 'o':
+ case 'u':
+ case 'x':
+ case 'X':
+ if (!have_star)
+ {
+ if (pointflag)
+ precision = accum;
+ else
+ fieldwidth = accum;
+ }
+ if (have_dollar)
+ {
+ if (longlongflag)
+ numvalue = (unsigned long long) argvalues[fmtpos].ll;
+ else if (longflag)
+ numvalue = (unsigned long) argvalues[fmtpos].l;
+ else
+ numvalue = (unsigned int) argvalues[fmtpos].i;
+ }
+ else
+ {
+ if (longlongflag)
+ numvalue = (unsigned long long) va_arg(args, long long);
+ else if (longflag)
+ numvalue = (unsigned long) va_arg(args, long);
+ else
+ numvalue = (unsigned int) va_arg(args, int);
+ }
+ fmtint(numvalue, ch, forcesign, leftjust, fieldwidth, zpad,
+ precision, pointflag, target);
+ break;
+ case 'c':
+ if (!have_star)
+ {
+ if (pointflag)
+ precision = accum;
+ else
+ fieldwidth = accum;
+ }
+ if (have_dollar)
+ cvalue = (unsigned char) argvalues[fmtpos].i;
+ else
+ cvalue = (unsigned char) va_arg(args, int);
+ fmtchar(cvalue, leftjust, fieldwidth, target);
+ break;
+ case 's':
+ if (!have_star)
+ {
+ if (pointflag)
+ precision = accum;
+ else
+ fieldwidth = accum;
+ }
+ if (have_dollar)
+ strvalue = argvalues[fmtpos].cptr;
+ else
+ strvalue = va_arg(args, char *);
+ /* If string is NULL, silently substitute "(null)" */
+ if (strvalue == NULL)
+ strvalue = "(null)";
+ fmtstr(strvalue, leftjust, fieldwidth, precision, pointflag,
+ target);
+ break;
+ case 'p':
+ /* fieldwidth/leftjust are ignored ... */
+ if (have_dollar)
+ strvalue = argvalues[fmtpos].cptr;
+ else
+ strvalue = va_arg(args, char *);
+ fmtptr((const void *) strvalue, target);
+ break;
+ case 'e':
+ case 'E':
+ case 'f':
+ case 'g':
+ case 'G':
+ if (!have_star)
+ {
+ if (pointflag)
+ precision = accum;
+ else
+ fieldwidth = accum;
+ }
+ if (have_dollar)
+ fvalue = argvalues[fmtpos].d;
+ else
+ fvalue = va_arg(args, double);
+ fmtfloat(fvalue, ch, forcesign, leftjust,
+ fieldwidth, zpad,
+ precision, pointflag,
+ target);
+ break;
+ case 'm':
+ {
+ char errbuf[PG_STRERROR_R_BUFLEN];
+ const char *errm = strerror_r(save_errno,
+ errbuf, sizeof(errbuf));
+
+ dostr(errm, strlen(errm), target);
+ }
+ break;
+ case '%':
+ dopr_outch('%', target);
+ break;
+ default:
+
+ /*
+ * Anything else --- in particular, '\0' indicating end of
+ * format string --- is bogus.
+ */
+ goto bad_format;
+ }
+
+ /* Check for failure after each conversion spec */
+ if (target->failed)
+ break;
+ }
+
+ return;
+
+bad_format:
+ errno = EINVAL;
+ target->failed = true;
+}
+
+/*
+ * find_arguments(): sort out the arguments for a format spec with %n$
+ *
+ * If format is valid, return true and fill argvalues[i] with the value
+ * for the conversion spec that has %i$ or *i$. Else return false.
+ */
+static bool
+find_arguments(const char *format, va_list args,
+ PrintfArgValue *argvalues)
+{
+ int ch;
+ bool afterstar;
+ int accum;
+ int longlongflag;
+ int longflag;
+ int fmtpos;
+ int i;
+ int last_dollar = 0; /* Init to "no dollar arguments known" */
+ PrintfArgType argtypes[PG_NL_ARGMAX + 1] = {0};
+
+ /*
+ * This loop must accept the same format strings as the one in dopr().
+ * However, we don't need to analyze them to the same level of detail.
+ *
+ * Since we're only called if there's a dollar-type spec somewhere, we can
+ * fail immediately if we find a non-dollar spec. Per the C99 standard,
+ * all argument references in the format string must be one or the other.
+ */
+ while (*format != '\0')
+ {
+ /* Locate next conversion specifier */
+ if (*format != '%')
+ {
+ /* Unlike dopr, we can just quit if there's no more specifiers */
+ format = strchr(format + 1, '%');
+ if (format == NULL)
+ break;
+ }
+
+ /* Process conversion spec starting at *format */
+ format++;
+ longflag = longlongflag = 0;
+ fmtpos = accum = 0;
+ afterstar = false;
+nextch1:
+ ch = *format++;
+ switch (ch)
+ {
+ case '-':
+ case '+':
+ goto nextch1;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ accum = accum * 10 + (ch - '0');
+ goto nextch1;
+ case '.':
+ accum = 0;
+ goto nextch1;
+ case '*':
+ if (afterstar)
+ return false; /* previous star missing dollar */
+ afterstar = true;
+ accum = 0;
+ goto nextch1;
+ case '$':
+ if (accum <= 0 || accum > PG_NL_ARGMAX)
+ return false;
+ if (afterstar)
+ {
+ if (argtypes[accum] &&
+ argtypes[accum] != ATYPE_INT)
+ return false;
+ argtypes[accum] = ATYPE_INT;
+ last_dollar = Max(last_dollar, accum);
+ afterstar = false;
+ }
+ else
+ fmtpos = accum;
+ accum = 0;
+ goto nextch1;
+ case 'l':
+ if (longflag)
+ longlongflag = 1;
+ else
+ longflag = 1;
+ goto nextch1;
+ case 'z':
+#if SIZEOF_SIZE_T == 8
+#ifdef HAVE_LONG_INT_64
+ longflag = 1;
+#elif defined(HAVE_LONG_LONG_INT_64)
+ longlongflag = 1;
+#else
+#error "Don't know how to print 64bit integers"
+#endif
+#else
+ /* assume size_t is same size as int */
+#endif
+ goto nextch1;
+ case 'h':
+ case '\'':
+ /* ignore these */
+ goto nextch1;
+ case 'd':
+ case 'i':
+ case 'o':
+ case 'u':
+ case 'x':
+ case 'X':
+ if (fmtpos)
+ {
+ PrintfArgType atype;
+
+ if (longlongflag)
+ atype = ATYPE_LONGLONG;
+ else if (longflag)
+ atype = ATYPE_LONG;
+ else
+ atype = ATYPE_INT;
+ if (argtypes[fmtpos] &&
+ argtypes[fmtpos] != atype)
+ return false;
+ argtypes[fmtpos] = atype;
+ last_dollar = Max(last_dollar, fmtpos);
+ }
+ else
+ return false; /* non-dollar conversion spec */
+ break;
+ case 'c':
+ if (fmtpos)
+ {
+ if (argtypes[fmtpos] &&
+ argtypes[fmtpos] != ATYPE_INT)
+ return false;
+ argtypes[fmtpos] = ATYPE_INT;
+ last_dollar = Max(last_dollar, fmtpos);
+ }
+ else
+ return false; /* non-dollar conversion spec */
+ break;
+ case 's':
+ case 'p':
+ if (fmtpos)
+ {
+ if (argtypes[fmtpos] &&
+ argtypes[fmtpos] != ATYPE_CHARPTR)
+ return false;
+ argtypes[fmtpos] = ATYPE_CHARPTR;
+ last_dollar = Max(last_dollar, fmtpos);
+ }
+ else
+ return false; /* non-dollar conversion spec */
+ break;
+ case 'e':
+ case 'E':
+ case 'f':
+ case 'g':
+ case 'G':
+ if (fmtpos)
+ {
+ if (argtypes[fmtpos] &&
+ argtypes[fmtpos] != ATYPE_DOUBLE)
+ return false;
+ argtypes[fmtpos] = ATYPE_DOUBLE;
+ last_dollar = Max(last_dollar, fmtpos);
+ }
+ else
+ return false; /* non-dollar conversion spec */
+ break;
+ case 'm':
+ case '%':
+ break;
+ default:
+ return false; /* bogus format string */
+ }
+
+ /*
+ * If we finish the spec with afterstar still set, there's a
+ * non-dollar star in there.
+ */
+ if (afterstar)
+ return false; /* non-dollar conversion spec */
+ }
+
+ /*
+ * Format appears valid so far, so collect the arguments in physical
+ * order. (Since we rejected any non-dollar specs that would have
+ * collected arguments, we know that dopr() hasn't collected any yet.)
+ */
+ for (i = 1; i <= last_dollar; i++)
+ {
+ switch (argtypes[i])
+ {
+ case ATYPE_NONE:
+ return false;
+ case ATYPE_INT:
+ argvalues[i].i = va_arg(args, int);
+ break;
+ case ATYPE_LONG:
+ argvalues[i].l = va_arg(args, long);
+ break;
+ case ATYPE_LONGLONG:
+ argvalues[i].ll = va_arg(args, long long);
+ break;
+ case ATYPE_DOUBLE:
+ argvalues[i].d = va_arg(args, double);
+ break;
+ case ATYPE_CHARPTR:
+ argvalues[i].cptr = va_arg(args, char *);
+ break;
+ }
+ }
+
+ return true;
+}
+
+static void
+fmtstr(const char *value, int leftjust, int minlen, int maxwidth,
+ int pointflag, PrintfTarget *target)
+{
+ int padlen,
+ vallen; /* amount to pad */
+
+ /*
+ * If a maxwidth (precision) is specified, we must not fetch more bytes
+ * than that.
+ */
+ if (pointflag)
+ vallen = strnlen(value, maxwidth);
+ else
+ vallen = strlen(value);
+
+ padlen = compute_padlen(minlen, vallen, leftjust);
+
+ if (padlen > 0)
+ {
+ dopr_outchmulti(' ', padlen, target);
+ padlen = 0;
+ }
+
+ dostr(value, vallen, target);
+
+ trailing_pad(padlen, target);
+}
+
+static void
+fmtptr(const void *value, PrintfTarget *target)
+{
+ int vallen;
+ char convert[64];
+
+ /* we rely on regular C library's snprintf to do the basic conversion */
+ vallen = snprintf(convert, sizeof(convert), "%p", value);
+ if (vallen < 0)
+ target->failed = true;
+ else
+ dostr(convert, vallen, target);
+}
+
+static void
+fmtint(long long value, char type, int forcesign, int leftjust,
+ int minlen, int zpad, int precision, int pointflag,
+ PrintfTarget *target)
+{
+ unsigned long long uvalue;
+ int base;
+ int dosign;
+ const char *cvt = "0123456789abcdef";
+ int signvalue = 0;
+ char convert[64];
+ int vallen = 0;
+ int padlen; /* amount to pad */
+ int zeropad; /* extra leading zeroes */
+
+ switch (type)
+ {
+ case 'd':
+ case 'i':
+ base = 10;
+ dosign = 1;
+ break;
+ case 'o':
+ base = 8;
+ dosign = 0;
+ break;
+ case 'u':
+ base = 10;
+ dosign = 0;
+ break;
+ case 'x':
+ base = 16;
+ dosign = 0;
+ break;
+ case 'X':
+ cvt = "0123456789ABCDEF";
+ base = 16;
+ dosign = 0;
+ break;
+ default:
+ return; /* keep compiler quiet */
+ }
+
+ /* disable MSVC warning about applying unary minus to an unsigned value */
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4146)
+#endif
+ /* Handle +/- */
+ if (dosign && adjust_sign((value < 0), forcesign, &signvalue))
+ uvalue = -(unsigned long long) value;
+ else
+ uvalue = (unsigned long long) value;
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+ /*
+ * SUS: the result of converting 0 with an explicit precision of 0 is no
+ * characters
+ */
+ if (value == 0 && pointflag && precision == 0)
+ vallen = 0;
+ else
+ {
+ /*
+ * Convert integer to string. We special-case each of the possible
+ * base values so as to avoid general-purpose divisions. On most
+ * machines, division by a fixed constant can be done much more
+ * cheaply than a general divide.
+ */
+ if (base == 10)
+ {
+ do
+ {
+ convert[sizeof(convert) - (++vallen)] = cvt[uvalue % 10];
+ uvalue = uvalue / 10;
+ } while (uvalue);
+ }
+ else if (base == 16)
+ {
+ do
+ {
+ convert[sizeof(convert) - (++vallen)] = cvt[uvalue % 16];
+ uvalue = uvalue / 16;
+ } while (uvalue);
+ }
+ else /* base == 8 */
+ {
+ do
+ {
+ convert[sizeof(convert) - (++vallen)] = cvt[uvalue % 8];
+ uvalue = uvalue / 8;
+ } while (uvalue);
+ }
+ }
+
+ zeropad = Max(0, precision - vallen);
+
+ padlen = compute_padlen(minlen, vallen + zeropad, leftjust);
+
+ leading_pad(zpad, signvalue, &padlen, target);
+
+ if (zeropad > 0)
+ dopr_outchmulti('0', zeropad, target);
+
+ dostr(convert + sizeof(convert) - vallen, vallen, target);
+
+ trailing_pad(padlen, target);
+}
+
+static void
+fmtchar(int value, int leftjust, int minlen, PrintfTarget *target)
+{
+ int padlen; /* amount to pad */
+
+ padlen = compute_padlen(minlen, 1, leftjust);
+
+ if (padlen > 0)
+ {
+ dopr_outchmulti(' ', padlen, target);
+ padlen = 0;
+ }
+
+ dopr_outch(value, target);
+
+ trailing_pad(padlen, target);
+}
+
+static void
+fmtfloat(double value, char type, int forcesign, int leftjust,
+ int minlen, int zpad, int precision, int pointflag,
+ PrintfTarget *target)
+{
+ int signvalue = 0;
+ int prec;
+ int vallen;
+ char fmt[8];
+ char convert[1024];
+ int zeropadlen = 0; /* amount to pad with zeroes */
+ int padlen; /* amount to pad with spaces */
+
+ /*
+ * We rely on the regular C library's snprintf to do the basic conversion,
+ * then handle padding considerations here.
+ *
+ * The dynamic range of "double" is about 1E+-308 for IEEE math, and not
+ * too wildly more than that with other hardware. In "f" format, snprintf
+ * could therefore generate at most 308 characters to the left of the
+ * decimal point; while we need to allow the precision to get as high as
+ * 308+17 to ensure that we don't truncate significant digits from very
+ * small values. To handle both these extremes, we use a buffer of 1024
+ * bytes and limit requested precision to 350 digits; this should prevent
+ * buffer overrun even with non-IEEE math. If the original precision
+ * request was more than 350, separately pad with zeroes.
+ *
+ * We handle infinities and NaNs specially to ensure platform-independent
+ * output.
+ */
+ if (precision < 0) /* cover possible overflow of "accum" */
+ precision = 0;
+ prec = Min(precision, 350);
+
+ if (isnan(value))
+ {
+ strcpy(convert, "NaN");
+ vallen = 3;
+ /* no zero padding, regardless of precision spec */
+ }
+ else
+ {
+ /*
+ * Handle sign (NaNs have no sign, so we don't do this in the case
+ * above). "value < 0.0" will not be true for IEEE minus zero, so we
+ * detect that by looking for the case where value equals 0.0
+ * according to == but not according to memcmp.
+ */
+ static const double dzero = 0.0;
+
+ if (adjust_sign((value < 0.0 ||
+ (value == 0.0 &&
+ memcmp(&value, &dzero, sizeof(double)) != 0)),
+ forcesign, &signvalue))
+ value = -value;
+
+ if (isinf(value))
+ {
+ strcpy(convert, "Infinity");
+ vallen = 8;
+ /* no zero padding, regardless of precision spec */
+ }
+ else if (pointflag)
+ {
+ zeropadlen = precision - prec;
+ fmt[0] = '%';
+ fmt[1] = '.';
+ fmt[2] = '*';
+ fmt[3] = type;
+ fmt[4] = '\0';
+ vallen = snprintf(convert, sizeof(convert), fmt, prec, value);
+ }
+ else
+ {
+ fmt[0] = '%';
+ fmt[1] = type;
+ fmt[2] = '\0';
+ vallen = snprintf(convert, sizeof(convert), fmt, value);
+ }
+ if (vallen < 0)
+ goto fail;
+
+ /*
+ * Windows, alone among our supported platforms, likes to emit
+ * three-digit exponent fields even when two digits would do. Hack
+ * such results to look like the way everyone else does it.
+ */
+#ifdef WIN32
+ if (vallen >= 6 &&
+ convert[vallen - 5] == 'e' &&
+ convert[vallen - 3] == '0')
+ {
+ convert[vallen - 3] = convert[vallen - 2];
+ convert[vallen - 2] = convert[vallen - 1];
+ vallen--;
+ }
+#endif
+ }
+
+ padlen = compute_padlen(minlen, vallen + zeropadlen, leftjust);
+
+ leading_pad(zpad, signvalue, &padlen, target);
+
+ if (zeropadlen > 0)
+ {
+ /* If 'e' or 'E' format, inject zeroes before the exponent */
+ char *epos = strrchr(convert, 'e');
+
+ if (!epos)
+ epos = strrchr(convert, 'E');
+ if (epos)
+ {
+ /* pad before exponent */
+ dostr(convert, epos - convert, target);
+ dopr_outchmulti('0', zeropadlen, target);
+ dostr(epos, vallen - (epos - convert), target);
+ }
+ else
+ {
+ /* no exponent, pad after the digits */
+ dostr(convert, vallen, target);
+ dopr_outchmulti('0', zeropadlen, target);
+ }
+ }
+ else
+ {
+ /* no zero padding, just emit the number as-is */
+ dostr(convert, vallen, target);
+ }
+
+ trailing_pad(padlen, target);
+ return;
+
+fail:
+ target->failed = true;
+}
+
+/*
+ * Nonstandard entry point to print a double value efficiently.
+ *
+ * This is approximately equivalent to strfromd(), but has an API more
+ * adapted to what float8out() wants. The behavior is like snprintf()
+ * with a format of "%.ng", where n is the specified precision.
+ * However, the target buffer must be nonempty (i.e. count > 0), and
+ * the precision is silently bounded to a sane range.
+ */
+int
+pg_strfromd(char *str, size_t count, int precision, double value)
+{
+ PrintfTarget target;
+ int signvalue = 0;
+ int vallen;
+ char fmt[8];
+ char convert[64];
+
+ /* Set up the target like pg_snprintf, but require nonempty buffer */
+ Assert(count > 0);
+ target.bufstart = target.bufptr = str;
+ target.bufend = str + count - 1;
+ target.stream = NULL;
+ target.nchars = 0;
+ target.failed = false;
+
+ /*
+ * We bound precision to a reasonable range; the combination of this and
+ * the knowledge that we're using "g" format without padding allows the
+ * convert[] buffer to be reasonably small.
+ */
+ if (precision < 1)
+ precision = 1;
+ else if (precision > 32)
+ precision = 32;
+
+ /*
+ * The rest is just an inlined version of the fmtfloat() logic above,
+ * simplified using the knowledge that no padding is wanted.
+ */
+ if (isnan(value))
+ {
+ strcpy(convert, "NaN");
+ vallen = 3;
+ }
+ else
+ {
+ static const double dzero = 0.0;
+
+ if (value < 0.0 ||
+ (value == 0.0 &&
+ memcmp(&value, &dzero, sizeof(double)) != 0))
+ {
+ signvalue = '-';
+ value = -value;
+ }
+
+ if (isinf(value))
+ {
+ strcpy(convert, "Infinity");
+ vallen = 8;
+ }
+ else
+ {
+ fmt[0] = '%';
+ fmt[1] = '.';
+ fmt[2] = '*';
+ fmt[3] = 'g';
+ fmt[4] = '\0';
+ vallen = snprintf(convert, sizeof(convert), fmt, precision, value);
+ if (vallen < 0)
+ {
+ target.failed = true;
+ goto fail;
+ }
+
+#ifdef WIN32
+ if (vallen >= 6 &&
+ convert[vallen - 5] == 'e' &&
+ convert[vallen - 3] == '0')
+ {
+ convert[vallen - 3] = convert[vallen - 2];
+ convert[vallen - 2] = convert[vallen - 1];
+ vallen--;
+ }
+#endif
+ }
+ }
+
+ if (signvalue)
+ dopr_outch(signvalue, &target);
+
+ dostr(convert, vallen, &target);
+
+fail:
+ *(target.bufptr) = '\0';
+ return target.failed ? -1 : (target.bufptr - target.bufstart
+ + target.nchars);
+}
+
+
+static void
+dostr(const char *str, int slen, PrintfTarget *target)
+{
+ /* fast path for common case of slen == 1 */
+ if (slen == 1)
+ {
+ dopr_outch(*str, target);
+ return;
+ }
+
+ while (slen > 0)
+ {
+ int avail;
+
+ if (target->bufend != NULL)
+ avail = target->bufend - target->bufptr;
+ else
+ avail = slen;
+ if (avail <= 0)
+ {
+ /* buffer full, can we dump to stream? */
+ if (target->stream == NULL)
+ {
+ target->nchars += slen; /* no, lose the data */
+ return;
+ }
+ flushbuffer(target);
+ continue;
+ }
+ avail = Min(avail, slen);
+ memmove(target->bufptr, str, avail);
+ target->bufptr += avail;
+ str += avail;
+ slen -= avail;
+ }
+}
+
+static void
+dopr_outch(int c, PrintfTarget *target)
+{
+ if (target->bufend != NULL && target->bufptr >= target->bufend)
+ {
+ /* buffer full, can we dump to stream? */
+ if (target->stream == NULL)
+ {
+ target->nchars++; /* no, lose the data */
+ return;
+ }
+ flushbuffer(target);
+ }
+ *(target->bufptr++) = c;
+}
+
+static void
+dopr_outchmulti(int c, int slen, PrintfTarget *target)
+{
+ /* fast path for common case of slen == 1 */
+ if (slen == 1)
+ {
+ dopr_outch(c, target);
+ return;
+ }
+
+ while (slen > 0)
+ {
+ int avail;
+
+ if (target->bufend != NULL)
+ avail = target->bufend - target->bufptr;
+ else
+ avail = slen;
+ if (avail <= 0)
+ {
+ /* buffer full, can we dump to stream? */
+ if (target->stream == NULL)
+ {
+ target->nchars += slen; /* no, lose the data */
+ return;
+ }
+ flushbuffer(target);
+ continue;
+ }
+ avail = Min(avail, slen);
+ memset(target->bufptr, c, avail);
+ target->bufptr += avail;
+ slen -= avail;
+ }
+}
+
+
+static int
+adjust_sign(int is_negative, int forcesign, int *signvalue)
+{
+ if (is_negative)
+ {
+ *signvalue = '-';
+ return true;
+ }
+ else if (forcesign)
+ *signvalue = '+';
+ return false;
+}
+
+
+static int
+compute_padlen(int minlen, int vallen, int leftjust)
+{
+ int padlen;
+
+ padlen = minlen - vallen;
+ if (padlen < 0)
+ padlen = 0;
+ if (leftjust)
+ padlen = -padlen;
+ return padlen;
+}
+
+
+static void
+leading_pad(int zpad, int signvalue, int *padlen, PrintfTarget *target)
+{
+ int maxpad;
+
+ if (*padlen > 0 && zpad)
+ {
+ if (signvalue)
+ {
+ dopr_outch(signvalue, target);
+ --(*padlen);
+ signvalue = 0;
+ }
+ if (*padlen > 0)
+ {
+ dopr_outchmulti(zpad, *padlen, target);
+ *padlen = 0;
+ }
+ }
+ maxpad = (signvalue != 0);
+ if (*padlen > maxpad)
+ {
+ dopr_outchmulti(' ', *padlen - maxpad, target);
+ *padlen = maxpad;
+ }
+ if (signvalue)
+ {
+ dopr_outch(signvalue, target);
+ if (*padlen > 0)
+ --(*padlen);
+ else if (*padlen < 0)
+ ++(*padlen);
+ }
+}
+
+
+static void
+trailing_pad(int padlen, PrintfTarget *target)
+{
+ if (padlen < 0)
+ dopr_outchmulti(' ', -padlen, target);
+}
diff --git a/contrib/libs/libpq/src/port/strerror.c b/contrib/libs/libpq/src/port/strerror.c
new file mode 100644
index 0000000000..26827d6db4
--- /dev/null
+++ b/contrib/libs/libpq/src/port/strerror.c
@@ -0,0 +1,312 @@
+/*-------------------------------------------------------------------------
+ *
+ * strerror.c
+ * Replacements for standard strerror() and strerror_r() functions
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/port/strerror.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "c.h"
+
+/*
+ * Within this file, "strerror" means the platform's function not pg_strerror,
+ * and likewise for "strerror_r"
+ */
+#undef strerror
+#undef strerror_r
+
+static char *gnuish_strerror_r(int errnum, char *buf, size_t buflen);
+static char *get_errno_symbol(int errnum);
+#ifdef WIN32
+static char *win32_socket_strerror(int errnum, char *buf, size_t buflen);
+#endif
+
+
+/*
+ * A slightly cleaned-up version of strerror()
+ */
+char *
+pg_strerror(int errnum)
+{
+ static char errorstr_buf[PG_STRERROR_R_BUFLEN];
+
+ return pg_strerror_r(errnum, errorstr_buf, sizeof(errorstr_buf));
+}
+
+/*
+ * A slightly cleaned-up version of strerror_r()
+ */
+char *
+pg_strerror_r(int errnum, char *buf, size_t buflen)
+{
+ char *str;
+
+ /* If it's a Windows Winsock error, that needs special handling */
+#ifdef WIN32
+ /* Winsock error code range, per WinError.h */
+ if (errnum >= 10000 && errnum <= 11999)
+ return win32_socket_strerror(errnum, buf, buflen);
+#endif
+
+ /* Try the platform's strerror_r(), or maybe just strerror() */
+ str = gnuish_strerror_r(errnum, buf, buflen);
+
+ /*
+ * Some strerror()s return an empty string for out-of-range errno. This
+ * is ANSI C spec compliant, but not exactly useful. Also, we may get
+ * back strings of question marks if libc cannot transcode the message to
+ * the codeset specified by LC_CTYPE. If we get nothing useful, first try
+ * get_errno_symbol(), and if that fails, print the numeric errno.
+ */
+ if (str == NULL || *str == '\0' || *str == '?')
+ str = get_errno_symbol(errnum);
+
+ if (str == NULL)
+ {
+ snprintf(buf, buflen, _("operating system error %d"), errnum);
+ str = buf;
+ }
+
+ return str;
+}
+
+/*
+ * Simple wrapper to emulate GNU strerror_r if what the platform provides is
+ * POSIX. Also, if platform lacks strerror_r altogether, fall back to plain
+ * strerror; it might not be very thread-safe, but tough luck.
+ */
+static char *
+gnuish_strerror_r(int errnum, char *buf, size_t buflen)
+{
+#ifdef HAVE_STRERROR_R
+#ifdef STRERROR_R_INT
+ /* POSIX API */
+ if (strerror_r(errnum, buf, buflen) == 0)
+ return buf;
+ return NULL; /* let caller deal with failure */
+#else
+ /* GNU API */
+ return strerror_r(errnum, buf, buflen);
+#endif
+#else /* !HAVE_STRERROR_R */
+ char *sbuf = strerror(errnum);
+
+ if (sbuf == NULL) /* can this still happen anywhere? */
+ return NULL;
+ /* To minimize thread-unsafety hazard, copy into caller's buffer */
+ strlcpy(buf, sbuf, buflen);
+ return buf;
+#endif
+}
+
+/*
+ * Returns a symbol (e.g. "ENOENT") for an errno code.
+ * Returns NULL if the code is unrecognized.
+ */
+static char *
+get_errno_symbol(int errnum)
+{
+ switch (errnum)
+ {
+ case E2BIG:
+ return "E2BIG";
+ case EACCES:
+ return "EACCES";
+ case EADDRINUSE:
+ return "EADDRINUSE";
+ case EADDRNOTAVAIL:
+ return "EADDRNOTAVAIL";
+ case EAFNOSUPPORT:
+ return "EAFNOSUPPORT";
+#ifdef EAGAIN
+ case EAGAIN:
+ return "EAGAIN";
+#endif
+#ifdef EALREADY
+ case EALREADY:
+ return "EALREADY";
+#endif
+ case EBADF:
+ return "EBADF";
+#ifdef EBADMSG
+ case EBADMSG:
+ return "EBADMSG";
+#endif
+ case EBUSY:
+ return "EBUSY";
+ case ECHILD:
+ return "ECHILD";
+ case ECONNABORTED:
+ return "ECONNABORTED";
+ case ECONNREFUSED:
+ return "ECONNREFUSED";
+ case ECONNRESET:
+ return "ECONNRESET";
+ case EDEADLK:
+ return "EDEADLK";
+ case EDOM:
+ return "EDOM";
+ case EEXIST:
+ return "EEXIST";
+ case EFAULT:
+ return "EFAULT";
+ case EFBIG:
+ return "EFBIG";
+ case EHOSTDOWN:
+ return "EHOSTDOWN";
+ case EHOSTUNREACH:
+ return "EHOSTUNREACH";
+ case EIDRM:
+ return "EIDRM";
+ case EINPROGRESS:
+ return "EINPROGRESS";
+ case EINTR:
+ return "EINTR";
+ case EINVAL:
+ return "EINVAL";
+ case EIO:
+ return "EIO";
+ case EISCONN:
+ return "EISCONN";
+ case EISDIR:
+ return "EISDIR";
+#ifdef ELOOP
+ case ELOOP:
+ return "ELOOP";
+#endif
+ case EMFILE:
+ return "EMFILE";
+ case EMLINK:
+ return "EMLINK";
+ case EMSGSIZE:
+ return "EMSGSIZE";
+ case ENAMETOOLONG:
+ return "ENAMETOOLONG";
+ case ENETDOWN:
+ return "ENETDOWN";
+ case ENETRESET:
+ return "ENETRESET";
+ case ENETUNREACH:
+ return "ENETUNREACH";
+ case ENFILE:
+ return "ENFILE";
+ case ENOBUFS:
+ return "ENOBUFS";
+ case ENODEV:
+ return "ENODEV";
+ case ENOENT:
+ return "ENOENT";
+ case ENOEXEC:
+ return "ENOEXEC";
+ case ENOMEM:
+ return "ENOMEM";
+ case ENOSPC:
+ return "ENOSPC";
+ case ENOSYS:
+ return "ENOSYS";
+ case ENOTCONN:
+ return "ENOTCONN";
+ case ENOTDIR:
+ return "ENOTDIR";
+#if defined(ENOTEMPTY) && (ENOTEMPTY != EEXIST) /* same code on AIX */
+ case ENOTEMPTY:
+ return "ENOTEMPTY";
+#endif
+ case ENOTSOCK:
+ return "ENOTSOCK";
+#ifdef ENOTSUP
+ case ENOTSUP:
+ return "ENOTSUP";
+#endif
+ case ENOTTY:
+ return "ENOTTY";
+ case ENXIO:
+ return "ENXIO";
+#if defined(EOPNOTSUPP) && (!defined(ENOTSUP) || (EOPNOTSUPP != ENOTSUP))
+ case EOPNOTSUPP:
+ return "EOPNOTSUPP";
+#endif
+#ifdef EOVERFLOW
+ case EOVERFLOW:
+ return "EOVERFLOW";
+#endif
+ case EPERM:
+ return "EPERM";
+ case EPIPE:
+ return "EPIPE";
+ case EPROTONOSUPPORT:
+ return "EPROTONOSUPPORT";
+ case ERANGE:
+ return "ERANGE";
+#ifdef EROFS
+ case EROFS:
+ return "EROFS";
+#endif
+ case ESRCH:
+ return "ESRCH";
+ case ETIMEDOUT:
+ return "ETIMEDOUT";
+#ifdef ETXTBSY
+ case ETXTBSY:
+ return "ETXTBSY";
+#endif
+#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
+ case EWOULDBLOCK:
+ return "EWOULDBLOCK";
+#endif
+ case EXDEV:
+ return "EXDEV";
+ }
+
+ return NULL;
+}
+
+
+#ifdef WIN32
+
+/*
+ * Windows' strerror() doesn't know the Winsock codes, so handle them this way
+ */
+static char *
+win32_socket_strerror(int errnum, char *buf, size_t buflen)
+{
+ static HANDLE handleDLL = INVALID_HANDLE_VALUE;
+
+ if (handleDLL == INVALID_HANDLE_VALUE)
+ {
+ handleDLL = LoadLibraryEx("netmsg.dll", NULL,
+ DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE);
+ if (handleDLL == NULL)
+ {
+ snprintf(buf, buflen,
+ "winsock error %d (could not load netmsg.dll to translate: error code %lu)",
+ errnum, GetLastError());
+ return buf;
+ }
+ }
+
+ ZeroMemory(buf, buflen);
+ if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_FROM_HMODULE,
+ handleDLL,
+ errnum,
+ MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
+ buf,
+ buflen - 1,
+ NULL) == 0)
+ {
+ /* Failed to get id */
+ snprintf(buf, buflen, "unrecognized winsock error %d", errnum);
+ }
+
+ return buf;
+}
+
+#endif /* WIN32 */
diff --git a/contrib/libs/libpq/src/port/tar.c b/contrib/libs/libpq/src/port/tar.c
new file mode 100644
index 0000000000..4afe9f2533
--- /dev/null
+++ b/contrib/libs/libpq/src/port/tar.c
@@ -0,0 +1,206 @@
+#include "c.h"
+
+#include <sys/stat.h>
+
+#include "pgtar.h"
+
+/*
+ * Print a numeric field in a tar header. The field starts at *s and is of
+ * length len; val is the value to be written.
+ *
+ * Per POSIX, the way to write a number is in octal with leading zeroes and
+ * one trailing space (or NUL, but we use space) at the end of the specified
+ * field width.
+ *
+ * However, the given value may not fit in the available space in octal form.
+ * If that's true, we use the GNU extension of writing \200 followed by the
+ * number in base-256 form (ie, stored in binary MSB-first). (Note: here we
+ * support only non-negative numbers, so we don't worry about the GNU rules
+ * for handling negative numbers.)
+ */
+void
+print_tar_number(char *s, int len, uint64 val)
+{
+ if (val < (((uint64) 1) << ((len - 1) * 3)))
+ {
+ /* Use octal with trailing space */
+ s[--len] = ' ';
+ while (len)
+ {
+ s[--len] = (val & 7) + '0';
+ val >>= 3;
+ }
+ }
+ else
+ {
+ /* Use base-256 with leading \200 */
+ s[0] = '\200';
+ while (len > 1)
+ {
+ s[--len] = (val & 255);
+ val >>= 8;
+ }
+ }
+}
+
+
+/*
+ * Read a numeric field in a tar header. The field starts at *s and is of
+ * length len.
+ *
+ * The POSIX-approved format for a number is octal, ending with a space or
+ * NUL. However, for values that don't fit, we recognize the GNU extension
+ * of \200 followed by the number in base-256 form (ie, stored in binary
+ * MSB-first). (Note: here we support only non-negative numbers, so we don't
+ * worry about the GNU rules for handling negative numbers.)
+ */
+uint64
+read_tar_number(const char *s, int len)
+{
+ uint64 result = 0;
+
+ if (*s == '\200')
+ {
+ /* base-256 */
+ while (--len)
+ {
+ result <<= 8;
+ result |= (unsigned char) (*++s);
+ }
+ }
+ else
+ {
+ /* octal */
+ while (len-- && *s >= '0' && *s <= '7')
+ {
+ result <<= 3;
+ result |= (*s - '0');
+ s++;
+ }
+ }
+ return result;
+}
+
+
+/*
+ * Calculate the tar checksum for a header. The header is assumed to always
+ * be 512 bytes, per the tar standard.
+ */
+int
+tarChecksum(char *header)
+{
+ int i,
+ sum;
+
+ /*
+ * Per POSIX, the checksum is the simple sum of all bytes in the header,
+ * treating the bytes as unsigned, and treating the checksum field (at
+ * offset 148) as though it contained 8 spaces.
+ */
+ sum = 8 * ' '; /* presumed value for checksum field */
+ for (i = 0; i < 512; i++)
+ if (i < 148 || i >= 156)
+ sum += 0xFF & header[i];
+ return sum;
+}
+
+
+/*
+ * Fill in the buffer pointed to by h with a tar format header. This buffer
+ * must always have space for 512 characters, which is a requirement of
+ * the tar format.
+ */
+enum tarError
+tarCreateHeader(char *h, const char *filename, const char *linktarget,
+ pgoff_t size, mode_t mode, uid_t uid, gid_t gid, time_t mtime)
+{
+ if (strlen(filename) > 99)
+ return TAR_NAME_TOO_LONG;
+
+ if (linktarget && strlen(linktarget) > 99)
+ return TAR_SYMLINK_TOO_LONG;
+
+ memset(h, 0, 512); /* assume tar header size */
+
+ /* Name 100 */
+ strlcpy(&h[0], filename, 100);
+ if (linktarget != NULL || S_ISDIR(mode))
+ {
+ /*
+ * We only support symbolic links to directories, and this is
+ * indicated in the tar format by adding a slash at the end of the
+ * name, the same as for regular directories.
+ */
+ int flen = strlen(filename);
+
+ flen = Min(flen, 99);
+ h[flen] = '/';
+ h[flen + 1] = '\0';
+ }
+
+ /* Mode 8 - this doesn't include the file type bits (S_IFMT) */
+ print_tar_number(&h[100], 8, (mode & 07777));
+
+ /* User ID 8 */
+ print_tar_number(&h[108], 8, uid);
+
+ /* Group 8 */
+ print_tar_number(&h[116], 8, gid);
+
+ /* File size 12 */
+ if (linktarget != NULL || S_ISDIR(mode))
+ /* Symbolic link or directory has size zero */
+ print_tar_number(&h[124], 12, 0);
+ else
+ print_tar_number(&h[124], 12, size);
+
+ /* Mod Time 12 */
+ print_tar_number(&h[136], 12, mtime);
+
+ /* Checksum 8 cannot be calculated until we've filled all other fields */
+
+ if (linktarget != NULL)
+ {
+ /* Type - Symbolic link */
+ h[156] = '2';
+ /* Link Name 100 */
+ strlcpy(&h[157], linktarget, 100);
+ }
+ else if (S_ISDIR(mode))
+ {
+ /* Type - directory */
+ h[156] = '5';
+ }
+ else
+ {
+ /* Type - regular file */
+ h[156] = '0';
+ }
+
+ /* Magic 6 */
+ strcpy(&h[257], "ustar");
+
+ /* Version 2 */
+ memcpy(&h[263], "00", 2);
+
+ /* User 32 */
+ /* XXX: Do we need to care about setting correct username? */
+ strlcpy(&h[265], "postgres", 32);
+
+ /* Group 32 */
+ /* XXX: Do we need to care about setting correct group name? */
+ strlcpy(&h[297], "postgres", 32);
+
+ /* Major Dev 8 */
+ print_tar_number(&h[329], 8, 0);
+
+ /* Minor Dev 8 */
+ print_tar_number(&h[337], 8, 0);
+
+ /* Prefix 155 - not used, leave as nulls */
+
+ /* Finally, compute and insert the checksum */
+ print_tar_number(&h[148], 8, tarChecksum(h));
+
+ return TAR_OK;
+}
diff --git a/contrib/libs/libpq/src/port/thread.c b/contrib/libs/libpq/src/port/thread.c
new file mode 100644
index 0000000000..375c89b297
--- /dev/null
+++ b/contrib/libs/libpq/src/port/thread.c
@@ -0,0 +1,96 @@
+/*-------------------------------------------------------------------------
+ *
+ * thread.c
+ *
+ * Prototypes and macros around system calls, used to help make
+ * threaded libraries reentrant and safe to use from threaded applications.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ *
+ * src/port/thread.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "c.h"
+
+#include <pwd.h>
+
+
+/*
+ * Historically, the code in this module had to deal with operating systems
+ * that lacked getpwuid_r().
+ */
+
+#ifndef WIN32
+
+/*
+ * pg_get_user_name - get the name of the user with the given ID
+ *
+ * On success, the user name is returned into the buffer (of size buflen),
+ * and "true" is returned. On failure, a localized error message is
+ * returned into the buffer, and "false" is returned.
+ */
+bool
+pg_get_user_name(uid_t user_id, char *buffer, size_t buflen)
+{
+ char pwdbuf[BUFSIZ];
+ struct passwd pwdstr;
+ struct passwd *pw = NULL;
+ int pwerr;
+
+ pwerr = getpwuid_r(user_id, &pwdstr, pwdbuf, sizeof(pwdbuf), &pw);
+ if (pw != NULL)
+ {
+ strlcpy(buffer, pw->pw_name, buflen);
+ return true;
+ }
+ if (pwerr != 0)
+ snprintf(buffer, buflen,
+ _("could not look up local user ID %d: %s"),
+ (int) user_id,
+ strerror_r(pwerr, pwdbuf, sizeof(pwdbuf)));
+ else
+ snprintf(buffer, buflen,
+ _("local user with ID %d does not exist"),
+ (int) user_id);
+ return false;
+}
+
+/*
+ * pg_get_user_home_dir - get the home directory of the user with the given ID
+ *
+ * On success, the directory path is returned into the buffer (of size buflen),
+ * and "true" is returned. On failure, a localized error message is
+ * returned into the buffer, and "false" is returned.
+ *
+ * Note that this does not incorporate the common behavior of checking
+ * $HOME first, since it's independent of which user_id is queried.
+ */
+bool
+pg_get_user_home_dir(uid_t user_id, char *buffer, size_t buflen)
+{
+ char pwdbuf[BUFSIZ];
+ struct passwd pwdstr;
+ struct passwd *pw = NULL;
+ int pwerr;
+
+ pwerr = getpwuid_r(user_id, &pwdstr, pwdbuf, sizeof(pwdbuf), &pw);
+ if (pw != NULL)
+ {
+ strlcpy(buffer, pw->pw_dir, buflen);
+ return true;
+ }
+ if (pwerr != 0)
+ snprintf(buffer, buflen,
+ _("could not look up local user ID %d: %s"),
+ (int) user_id,
+ strerror_r(pwerr, pwdbuf, sizeof(pwdbuf)));
+ else
+ snprintf(buffer, buflen,
+ _("local user with ID %d does not exist"),
+ (int) user_id);
+ return false;
+}
+
+#endif /* !WIN32 */
diff --git a/contrib/libs/libpq/src/port/win32common.c b/contrib/libs/libpq/src/port/win32common.c
new file mode 100644
index 0000000000..2fd78f7f93
--- /dev/null
+++ b/contrib/libs/libpq/src/port/win32common.c
@@ -0,0 +1,68 @@
+/*-------------------------------------------------------------------------
+ *
+ * win32common.c
+ * Common routines shared among the win32*.c ports.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/port/win32common.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifdef FRONTEND
+#include "postgres_fe.h"
+#else
+#include "postgres.h"
+#endif
+
+#ifdef WIN32
+
+/*
+ * pgwin32_get_file_type
+ *
+ * Convenience wrapper for GetFileType() with specific error handling for all the
+ * port implementations. Returns the file type associated with a HANDLE.
+ *
+ * On error, sets errno with FILE_TYPE_UNKNOWN as file type.
+ */
+DWORD
+pgwin32_get_file_type(HANDLE hFile)
+{
+ DWORD fileType = FILE_TYPE_UNKNOWN;
+ DWORD lastError;
+
+ errno = 0;
+
+ /*
+ * When stdin, stdout, and stderr aren't associated with a stream the
+ * special value -2 is returned:
+ * https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/get-osfhandle
+ */
+ if (hFile == INVALID_HANDLE_VALUE || hFile == (HANDLE) -2)
+ {
+ errno = EINVAL;
+ return FILE_TYPE_UNKNOWN;
+ }
+
+ fileType = GetFileType(hFile);
+ lastError = GetLastError();
+
+ /*
+ * Invoke GetLastError in order to distinguish between a "valid" return of
+ * FILE_TYPE_UNKNOWN and its return due to a calling error. In case of
+ * success, GetLastError() returns NO_ERROR.
+ */
+ if (fileType == FILE_TYPE_UNKNOWN && lastError != NO_ERROR)
+ {
+ _dosmaperr(lastError);
+ return FILE_TYPE_UNKNOWN;
+ }
+
+ return fileType;
+}
+
+#endif /* WIN32 */
diff --git a/contrib/libs/libpq/src/port/win32error.c b/contrib/libs/libpq/src/port/win32error.c
new file mode 100644
index 0000000000..d7c3048eba
--- /dev/null
+++ b/contrib/libs/libpq/src/port/win32error.c
@@ -0,0 +1,214 @@
+/*-------------------------------------------------------------------------
+ *
+ * win32error.c
+ * Map win32 error codes to errno values
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/port/win32error.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+static const struct
+{
+ DWORD winerr;
+ int doserr;
+} doserrors[] =
+
+{
+ {
+ ERROR_INVALID_FUNCTION, EINVAL
+ },
+ {
+ ERROR_FILE_NOT_FOUND, ENOENT
+ },
+ {
+ ERROR_PATH_NOT_FOUND, ENOENT
+ },
+ {
+ ERROR_TOO_MANY_OPEN_FILES, EMFILE
+ },
+ {
+ ERROR_ACCESS_DENIED, EACCES
+ },
+ {
+ ERROR_INVALID_HANDLE, EBADF
+ },
+ {
+ ERROR_ARENA_TRASHED, ENOMEM
+ },
+ {
+ ERROR_NOT_ENOUGH_MEMORY, ENOMEM
+ },
+ {
+ ERROR_INVALID_BLOCK, ENOMEM
+ },
+ {
+ ERROR_BAD_ENVIRONMENT, E2BIG
+ },
+ {
+ ERROR_BAD_FORMAT, ENOEXEC
+ },
+ {
+ ERROR_INVALID_ACCESS, EINVAL
+ },
+ {
+ ERROR_INVALID_DATA, EINVAL
+ },
+ {
+ ERROR_INVALID_DRIVE, ENOENT
+ },
+ {
+ ERROR_CURRENT_DIRECTORY, EACCES
+ },
+ {
+ ERROR_NOT_SAME_DEVICE, EXDEV
+ },
+ {
+ ERROR_NO_MORE_FILES, ENOENT
+ },
+ {
+ ERROR_LOCK_VIOLATION, EACCES
+ },
+ {
+ ERROR_SHARING_VIOLATION, EACCES
+ },
+ {
+ ERROR_BAD_NETPATH, ENOENT
+ },
+ {
+ ERROR_NETWORK_ACCESS_DENIED, EACCES
+ },
+ {
+ ERROR_BAD_NET_NAME, ENOENT
+ },
+ {
+ ERROR_FILE_EXISTS, EEXIST
+ },
+ {
+ ERROR_CANNOT_MAKE, EACCES
+ },
+ {
+ ERROR_FAIL_I24, EACCES
+ },
+ {
+ ERROR_INVALID_PARAMETER, EINVAL
+ },
+ {
+ ERROR_NO_PROC_SLOTS, EAGAIN
+ },
+ {
+ ERROR_DRIVE_LOCKED, EACCES
+ },
+ {
+ ERROR_BROKEN_PIPE, EPIPE
+ },
+ {
+ ERROR_DISK_FULL, ENOSPC
+ },
+ {
+ ERROR_INVALID_TARGET_HANDLE, EBADF
+ },
+ {
+ ERROR_INVALID_HANDLE, EINVAL
+ },
+ {
+ ERROR_WAIT_NO_CHILDREN, ECHILD
+ },
+ {
+ ERROR_CHILD_NOT_COMPLETE, ECHILD
+ },
+ {
+ ERROR_DIRECT_ACCESS_HANDLE, EBADF
+ },
+ {
+ ERROR_NEGATIVE_SEEK, EINVAL
+ },
+ {
+ ERROR_SEEK_ON_DEVICE, EACCES
+ },
+ {
+ ERROR_DIR_NOT_EMPTY, ENOTEMPTY
+ },
+ {
+ ERROR_NOT_LOCKED, EACCES
+ },
+ {
+ ERROR_BAD_PATHNAME, ENOENT
+ },
+ {
+ ERROR_MAX_THRDS_REACHED, EAGAIN
+ },
+ {
+ ERROR_LOCK_FAILED, EACCES
+ },
+ {
+ ERROR_ALREADY_EXISTS, EEXIST
+ },
+ {
+ ERROR_FILENAME_EXCED_RANGE, ENOENT
+ },
+ {
+ ERROR_NESTING_NOT_ALLOWED, EAGAIN
+ },
+ {
+ ERROR_NOT_ENOUGH_QUOTA, ENOMEM
+ },
+ {
+ ERROR_DELETE_PENDING, ENOENT
+ },
+ {
+ ERROR_INVALID_NAME, ENOENT
+ },
+ {
+ ERROR_CANT_RESOLVE_FILENAME, ENOENT
+ }
+};
+
+void
+_dosmaperr(unsigned long e)
+{
+ int i;
+
+ if (e == 0)
+ {
+ errno = 0;
+ return;
+ }
+
+ for (i = 0; i < lengthof(doserrors); i++)
+ {
+ if (doserrors[i].winerr == e)
+ {
+ int doserr = doserrors[i].doserr;
+
+#ifndef FRONTEND
+ ereport(DEBUG5,
+ (errmsg_internal("mapped win32 error code %lu to %d",
+ e, doserr)));
+#elif defined(FRONTEND_DEBUG)
+ fprintf(stderr, "mapped win32 error code %lu to %d", e, doserr);
+#endif
+ errno = doserr;
+ return;
+ }
+ }
+
+#ifndef FRONTEND
+ ereport(LOG,
+ (errmsg_internal("unrecognized win32 error code: %lu",
+ e)));
+#else
+ fprintf(stderr, "unrecognized win32 error code: %lu", e);
+#endif
+
+ errno = EINVAL;
+}
diff --git a/contrib/libs/libpq/src/port/win32gettimeofday.c b/contrib/libs/libpq/src/port/win32gettimeofday.c
new file mode 100644
index 0000000000..1e00f7ee14
--- /dev/null
+++ b/contrib/libs/libpq/src/port/win32gettimeofday.c
@@ -0,0 +1,75 @@
+/*
+ * win32gettimeofday.c
+ * Win32 gettimeofday() replacement
+ *
+ * src/port/win32gettimeofday.c
+ *
+ * Copyright (c) 2003 SRA, Inc.
+ * Copyright (c) 2003 SKC, Inc.
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose, without fee, and without a
+ * written agreement is hereby granted, provided that the above
+ * copyright notice and this paragraph and the following two
+ * paragraphs appear in all copies.
+ *
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT,
+ * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
+ * LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
+ * DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS
+ * IS" BASIS, AND THE AUTHOR HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE,
+ * SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#include "c.h"
+
+#include <sysinfoapi.h>
+
+#include <sys/time.h>
+
+/* FILETIME of Jan 1 1970 00:00:00, the PostgreSQL epoch */
+static const unsigned __int64 epoch = UINT64CONST(116444736000000000);
+
+/*
+ * FILETIME represents the number of 100-nanosecond intervals since
+ * January 1, 1601 (UTC).
+ */
+#define FILETIME_UNITS_PER_SEC 10000000L
+#define FILETIME_UNITS_PER_USEC 10
+
+
+/*
+ * timezone information is stored outside the kernel so tzp isn't used anymore.
+ *
+ * Note: this function is not for Win32 high precision timing purposes. See
+ * elapsed_time().
+ */
+int
+gettimeofday(struct timeval *tp, void *tzp)
+{
+ FILETIME file_time;
+ ULARGE_INTEGER ularge;
+
+ /*
+ * POSIX declines to define what tzp points to, saying "If tzp is not a
+ * null pointer, the behavior is unspecified". Let's take this
+ * opportunity to verify that noplace in Postgres tries to use any
+ * unportable behavior.
+ */
+ Assert(tzp == NULL);
+
+ GetSystemTimePreciseAsFileTime(&file_time);
+ ularge.LowPart = file_time.dwLowDateTime;
+ ularge.HighPart = file_time.dwHighDateTime;
+
+ tp->tv_sec = (long) ((ularge.QuadPart - epoch) / FILETIME_UNITS_PER_SEC);
+ tp->tv_usec = (long) (((ularge.QuadPart - epoch) % FILETIME_UNITS_PER_SEC)
+ / FILETIME_UNITS_PER_USEC);
+
+ return 0;
+}
diff --git a/contrib/libs/libpq/src/port/win32ntdll.c b/contrib/libs/libpq/src/port/win32ntdll.c
new file mode 100644
index 0000000000..3b38cdb34c
--- /dev/null
+++ b/contrib/libs/libpq/src/port/win32ntdll.c
@@ -0,0 +1,71 @@
+/*-------------------------------------------------------------------------
+ *
+ * win32ntdll.c
+ * Dynamically loaded Windows NT functions.
+ *
+ * Portions Copyright (c) 2021-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/port/win32ntdll.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "c.h"
+
+#include "port/win32ntdll.h"
+
+RtlGetLastNtStatus_t pg_RtlGetLastNtStatus;
+RtlNtStatusToDosError_t pg_RtlNtStatusToDosError;
+NtFlushBuffersFileEx_t pg_NtFlushBuffersFileEx;
+
+typedef struct NtDllRoutine
+{
+ const char *name;
+ pg_funcptr_t *address;
+} NtDllRoutine;
+
+static const NtDllRoutine routines[] = {
+ {"RtlGetLastNtStatus", (pg_funcptr_t *) &pg_RtlGetLastNtStatus},
+ {"RtlNtStatusToDosError", (pg_funcptr_t *) &pg_RtlNtStatusToDosError},
+ {"NtFlushBuffersFileEx", (pg_funcptr_t *) &pg_NtFlushBuffersFileEx}
+};
+
+static bool initialized;
+
+int
+initialize_ntdll(void)
+{
+ HMODULE module;
+
+ if (initialized)
+ return 0;
+
+ if (!(module = LoadLibraryEx("ntdll.dll", NULL, 0)))
+ {
+ _dosmaperr(GetLastError());
+ return -1;
+ }
+
+ for (int i = 0; i < lengthof(routines); ++i)
+ {
+ pg_funcptr_t address;
+
+ address = (pg_funcptr_t) GetProcAddress(module, routines[i].name);
+ if (!address)
+ {
+ _dosmaperr(GetLastError());
+ FreeLibrary(module);
+
+ return -1;
+ }
+
+ *(pg_funcptr_t *) routines[i].address = address;
+ }
+
+ initialized = true;
+
+ return 0;
+}
diff --git a/contrib/libs/libpq/src/port/win32setlocale.c b/contrib/libs/libpq/src/port/win32setlocale.c
new file mode 100644
index 0000000000..e2c85b0048
--- /dev/null
+++ b/contrib/libs/libpq/src/port/win32setlocale.c
@@ -0,0 +1,193 @@
+/*-------------------------------------------------------------------------
+ *
+ * win32setlocale.c
+ * Wrapper to work around bugs in Windows setlocale() implementation
+ *
+ * Copyright (c) 2011-2023, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/port/win32setlocale.c
+ *
+ *
+ * The setlocale() function in Windows is broken in two ways. First, it
+ * has a problem with locale names that have a dot in the country name. For
+ * example:
+ *
+ * "Chinese (Traditional)_Hong Kong S.A.R..950"
+ *
+ * For some reason, setlocale() doesn't accept that as argument, even though
+ * setlocale(LC_ALL, NULL) returns exactly that. Fortunately, it accepts
+ * various alternative names for such countries, so to work around the broken
+ * setlocale() function, we map the troublemaking locale names to accepted
+ * aliases, before calling setlocale().
+ *
+ * The second problem is that the locale name for "Norwegian (Bokm&aring;l)"
+ * contains a non-ASCII character. That's problematic, because it's not clear
+ * what encoding the locale name itself is supposed to be in, when you
+ * haven't yet set a locale. Also, it causes problems when the cluster
+ * contains databases with different encodings, as the locale name is stored
+ * in the pg_database system catalog. To work around that, when setlocale()
+ * returns that locale name, map it to a pure-ASCII alias for the same
+ * locale.
+ *-------------------------------------------------------------------------
+ */
+
+#include "c.h"
+
+#undef setlocale
+
+struct locale_map
+{
+ /*
+ * String in locale name to replace. Can be a single string (end is NULL),
+ * or separate start and end strings. If two strings are given, the locale
+ * name must contain both of them, and everything between them is
+ * replaced. This is used for a poor-man's regexp search, allowing
+ * replacement of "start.*end".
+ */
+ const char *locale_name_start;
+ const char *locale_name_end;
+
+ const char *replacement; /* string to replace the match with */
+};
+
+/*
+ * Mappings applied before calling setlocale(), to the argument.
+ */
+static const struct locale_map locale_map_argument[] = {
+ /*
+ * "HKG" is listed here:
+ * http://msdn.microsoft.com/en-us/library/cdax410z%28v=vs.71%29.aspx
+ * (Country/Region Strings).
+ *
+ * "ARE" is the ISO-3166 three-letter code for U.A.E. It is not on the
+ * above list, but seems to work anyway.
+ */
+ {"Hong Kong S.A.R.", NULL, "HKG"},
+ {"U.A.E.", NULL, "ARE"},
+
+ /*
+ * The ISO-3166 country code for Macau S.A.R. is MAC, but Windows doesn't
+ * seem to recognize that. And Macau isn't listed in the table of accepted
+ * abbreviations linked above. Fortunately, "ZHM" seems to be accepted as
+ * an alias for "Chinese (Traditional)_Macau S.A.R..950". I'm not sure
+ * where "ZHM" comes from, must be some legacy naming scheme. But hey, it
+ * works.
+ *
+ * Note that unlike HKG and ARE, ZHM is an alias for the *whole* locale
+ * name, not just the country part.
+ *
+ * Some versions of Windows spell it "Macau", others "Macao".
+ */
+ {"Chinese (Traditional)_Macau S.A.R..950", NULL, "ZHM"},
+ {"Chinese_Macau S.A.R..950", NULL, "ZHM"},
+ {"Chinese (Traditional)_Macao S.A.R..950", NULL, "ZHM"},
+ {"Chinese_Macao S.A.R..950", NULL, "ZHM"},
+ {NULL, NULL, NULL}
+};
+
+/*
+ * Mappings applied after calling setlocale(), to its return value.
+ */
+static const struct locale_map locale_map_result[] = {
+ /*
+ * "Norwegian (Bokm&aring;l)" locale name contains the a-ring character.
+ * Map it to a pure-ASCII alias.
+ *
+ * It's not clear what encoding setlocale() uses when it returns the
+ * locale name, so to play it safe, we search for "Norwegian (Bok*l)".
+ *
+ * Just to make life even more complicated, some versions of Windows spell
+ * the locale name without parentheses. Translate that too.
+ */
+ {"Norwegian (Bokm", "l)_Norway", "Norwegian_Norway"},
+ {"Norwegian Bokm", "l_Norway", "Norwegian_Norway"},
+ {NULL, NULL, NULL}
+};
+
+#define MAX_LOCALE_NAME_LEN 100
+
+static const char *
+map_locale(const struct locale_map *map, const char *locale)
+{
+ static char aliasbuf[MAX_LOCALE_NAME_LEN];
+ int i;
+
+ /* Check if the locale name matches any of the problematic ones. */
+ for (i = 0; map[i].locale_name_start != NULL; i++)
+ {
+ const char *needle_start = map[i].locale_name_start;
+ const char *needle_end = map[i].locale_name_end;
+ const char *replacement = map[i].replacement;
+ char *match;
+ char *match_start = NULL;
+ char *match_end = NULL;
+
+ match = strstr(locale, needle_start);
+ if (match)
+ {
+ /*
+ * Found a match for the first part. If this was a two-part
+ * replacement, find the second part.
+ */
+ match_start = match;
+ if (needle_end)
+ {
+ match = strstr(match_start + strlen(needle_start), needle_end);
+ if (match)
+ match_end = match + strlen(needle_end);
+ else
+ match_start = NULL;
+ }
+ else
+ match_end = match_start + strlen(needle_start);
+ }
+
+ if (match_start)
+ {
+ /* Found a match. Replace the matched string. */
+ int matchpos = match_start - locale;
+ int replacementlen = strlen(replacement);
+ char *rest = match_end;
+ int restlen = strlen(rest);
+
+ /* check that the result fits in the static buffer */
+ if (matchpos + replacementlen + restlen + 1 > MAX_LOCALE_NAME_LEN)
+ return NULL;
+
+ memcpy(&aliasbuf[0], &locale[0], matchpos);
+ memcpy(&aliasbuf[matchpos], replacement, replacementlen);
+ /* includes null terminator */
+ memcpy(&aliasbuf[matchpos + replacementlen], rest, restlen + 1);
+
+ return aliasbuf;
+ }
+ }
+
+ /* no match, just return the original string */
+ return locale;
+}
+
+char *
+pgwin32_setlocale(int category, const char *locale)
+{
+ const char *argument;
+ char *result;
+
+ if (locale == NULL)
+ argument = NULL;
+ else
+ argument = map_locale(locale_map_argument, locale);
+
+ /* Call the real setlocale() function */
+ result = setlocale(category, argument);
+
+ /*
+ * setlocale() is specified to return a "char *" that the caller is
+ * forbidden to modify, so casting away the "const" is innocuous.
+ */
+ if (result)
+ result = unconstify(char *, map_locale(locale_map_result, result));
+
+ return result;
+}
diff --git a/contrib/libs/libpq/src/port/win32stat.c b/contrib/libs/libpq/src/port/win32stat.c
new file mode 100644
index 0000000000..aa3a0c174e
--- /dev/null
+++ b/contrib/libs/libpq/src/port/win32stat.c
@@ -0,0 +1,306 @@
+/*-------------------------------------------------------------------------
+ *
+ * win32stat.c
+ * Replacements for <sys/stat.h> functions using GetFileInformationByHandle
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/port/win32stat.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifdef WIN32
+
+#include "c.h"
+#include "port/win32ntdll.h"
+
+#include <windows.h>
+
+/*
+ * Convert a FILETIME struct into a 64 bit time_t.
+ */
+static __time64_t
+filetime_to_time(const FILETIME *ft)
+{
+ ULARGE_INTEGER unified_ft = {0};
+ static const uint64 EpochShift = UINT64CONST(116444736000000000);
+
+ unified_ft.LowPart = ft->dwLowDateTime;
+ unified_ft.HighPart = ft->dwHighDateTime;
+
+ if (unified_ft.QuadPart < EpochShift)
+ return -1;
+
+ unified_ft.QuadPart -= EpochShift;
+ unified_ft.QuadPart /= 10 * 1000 * 1000;
+
+ return unified_ft.QuadPart;
+}
+
+/*
+ * Convert WIN32 file attributes to a Unix-style mode.
+ *
+ * Only owner permissions are set.
+ */
+static unsigned short
+fileattr_to_unixmode(int attr)
+{
+ unsigned short uxmode = 0;
+
+ uxmode |= (unsigned short) ((attr & FILE_ATTRIBUTE_DIRECTORY) ?
+ (_S_IFDIR) : (_S_IFREG));
+
+ uxmode |= (unsigned short) ((attr & FILE_ATTRIBUTE_READONLY) ?
+ (_S_IREAD) : (_S_IREAD | _S_IWRITE));
+
+ /* there is no need to simulate _S_IEXEC using CMD's PATHEXT extensions */
+ uxmode |= _S_IEXEC;
+
+ return uxmode;
+}
+
+/*
+ * Convert WIN32 file information (from a HANDLE) to a struct stat.
+ */
+static int
+fileinfo_to_stat(HANDLE hFile, struct stat *buf)
+{
+ BY_HANDLE_FILE_INFORMATION fiData;
+
+ memset(buf, 0, sizeof(*buf));
+
+ /*
+ * GetFileInformationByHandle minimum supported version: Windows XP and
+ * Windows Server 2003, so it exists everywhere we care about.
+ */
+ if (!GetFileInformationByHandle(hFile, &fiData))
+ {
+ _dosmaperr(GetLastError());
+ return -1;
+ }
+
+ if (fiData.ftLastWriteTime.dwLowDateTime ||
+ fiData.ftLastWriteTime.dwHighDateTime)
+ buf->st_mtime = filetime_to_time(&fiData.ftLastWriteTime);
+
+ if (fiData.ftLastAccessTime.dwLowDateTime ||
+ fiData.ftLastAccessTime.dwHighDateTime)
+ buf->st_atime = filetime_to_time(&fiData.ftLastAccessTime);
+ else
+ buf->st_atime = buf->st_mtime;
+
+ if (fiData.ftCreationTime.dwLowDateTime ||
+ fiData.ftCreationTime.dwHighDateTime)
+ buf->st_ctime = filetime_to_time(&fiData.ftCreationTime);
+ else
+ buf->st_ctime = buf->st_mtime;
+
+ buf->st_mode = fileattr_to_unixmode(fiData.dwFileAttributes);
+ buf->st_nlink = fiData.nNumberOfLinks;
+
+ buf->st_size = ((((uint64) fiData.nFileSizeHigh) << 32) |
+ fiData.nFileSizeLow);
+
+ return 0;
+}
+
+/*
+ * Windows implementation of lstat().
+ */
+int
+_pglstat64(const char *name, struct stat *buf)
+{
+ /*
+ * Our open wrapper will report STATUS_DELETE_PENDING as ENOENT. We
+ * request FILE_FLAG_BACKUP_SEMANTICS so that we can open directories too,
+ * for limited purposes. We use the private handle-based version, so we
+ * don't risk running out of fds.
+ */
+ HANDLE hFile;
+ int ret;
+
+ hFile = pgwin32_open_handle(name, O_RDONLY, true);
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ if (errno == ENOENT)
+ {
+ /*
+ * If it's a junction point pointing to a non-existent path, we'll
+ * have ENOENT here (because pgwin32_open_handle does not use
+ * FILE_FLAG_OPEN_REPARSE_POINT). In that case, we'll try again
+ * with readlink() below, which will distinguish true ENOENT from
+ * pseudo-symlink.
+ */
+ memset(buf, 0, sizeof(*buf));
+ ret = 0;
+ }
+ else
+ return -1;
+ }
+ else
+ ret = fileinfo_to_stat(hFile, buf);
+
+ /*
+ * Junction points appear as directories to fileinfo_to_stat(), so we'll
+ * need to do a bit more work to distinguish them.
+ */
+ if ((ret == 0 && S_ISDIR(buf->st_mode)) || hFile == INVALID_HANDLE_VALUE)
+ {
+ char next[MAXPGPATH];
+ ssize_t size;
+
+ /*
+ * POSIX says we need to put the length of the target path into
+ * st_size. Use readlink() to get it, or learn that this is not a
+ * junction point.
+ */
+ size = readlink(name, next, sizeof(next));
+ if (size < 0)
+ {
+ if (errno == EACCES &&
+ pg_RtlGetLastNtStatus() == STATUS_DELETE_PENDING)
+ {
+ /* Unlinked underneath us. */
+ errno = ENOENT;
+ ret = -1;
+ }
+ else if (errno == EINVAL)
+ {
+ /* It's not a junction point, nothing to do. */
+ }
+ else
+ {
+ /* Some other failure. */
+ ret = -1;
+ }
+ }
+ else
+ {
+ /* It's a junction point, so report it as a symlink. */
+ buf->st_mode &= ~S_IFDIR;
+ buf->st_mode |= S_IFLNK;
+ buf->st_size = size;
+ ret = 0;
+ }
+ }
+
+ if (hFile != INVALID_HANDLE_VALUE)
+ CloseHandle(hFile);
+ return ret;
+}
+
+/*
+ * Windows implementation of stat().
+ */
+int
+_pgstat64(const char *name, struct stat *buf)
+{
+ int loops = 0;
+ int ret;
+ char curr[MAXPGPATH];
+
+ ret = _pglstat64(name, buf);
+
+ strlcpy(curr, name, MAXPGPATH);
+
+ /* Do we need to follow a symlink (junction point)? */
+ while (ret == 0 && S_ISLNK(buf->st_mode))
+ {
+ char next[MAXPGPATH];
+ ssize_t size;
+
+ if (++loops > 8)
+ {
+ errno = ELOOP;
+ return -1;
+ }
+
+ /*
+ * _pglstat64() already called readlink() once to be able to fill in
+ * st_size, and now we need to do it again to get the path to follow.
+ * That could be optimized, but stat() on symlinks is probably rare
+ * and this way is simple.
+ */
+ size = readlink(curr, next, sizeof(next));
+ if (size < 0)
+ {
+ if (errno == EACCES &&
+ pg_RtlGetLastNtStatus() == STATUS_DELETE_PENDING)
+ {
+ /* Unlinked underneath us. */
+ errno = ENOENT;
+ }
+ return -1;
+ }
+ if (size >= sizeof(next))
+ {
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+ next[size] = 0;
+
+ ret = _pglstat64(next, buf);
+ strcpy(curr, next);
+ }
+
+ return ret;
+}
+
+/*
+ * Windows implementation of fstat().
+ */
+int
+_pgfstat64(int fileno, struct stat *buf)
+{
+ HANDLE hFile = (HANDLE) _get_osfhandle(fileno);
+ DWORD fileType = FILE_TYPE_UNKNOWN;
+ unsigned short st_mode;
+
+ if (buf == NULL)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ fileType = pgwin32_get_file_type(hFile);
+ if (errno != 0)
+ return -1;
+
+ switch (fileType)
+ {
+ /* The specified file is a disk file */
+ case FILE_TYPE_DISK:
+ return fileinfo_to_stat(hFile, buf);
+
+ /*
+ * The specified file is a socket, a named pipe, or an anonymous
+ * pipe.
+ */
+ case FILE_TYPE_PIPE:
+ st_mode = _S_IFIFO;
+ break;
+ /* The specified file is a character file */
+ case FILE_TYPE_CHAR:
+ st_mode = _S_IFCHR;
+ break;
+ /* Unused flag and unknown file type */
+ case FILE_TYPE_REMOTE:
+ case FILE_TYPE_UNKNOWN:
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+
+ memset(buf, 0, sizeof(*buf));
+ buf->st_mode = st_mode;
+ buf->st_dev = fileno;
+ buf->st_rdev = fileno;
+ buf->st_nlink = 1;
+ return 0;
+}
+
+#endif /* WIN32 */
diff --git a/contrib/libs/libpq/ya.make b/contrib/libs/libpq/ya.make
new file mode 100644
index 0000000000..d7acd293f3
--- /dev/null
+++ b/contrib/libs/libpq/ya.make
@@ -0,0 +1,155 @@
+# Generated by devtools/yamaker from nixpkgs 22.11.
+
+LIBRARY()
+
+LICENSE(
+ Apache-2.0 AND
+ BSD-3-Clause AND
+ BSL-1.0 AND
+ ISC AND
+ PostgreSQL AND
+ Public-Domain
+)
+
+LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
+
+VERSION(16.1)
+
+ORIGINAL_SOURCE(https://github.com/postgres/postgres/archive/REL_16_1.tar.gz)
+
+PEERDIR(
+ contrib/libs/libc_compat
+ contrib/libs/openssl
+ contrib/libs/zlib
+)
+
+ADDINCL(
+ contrib/libs/libpq/src/backend
+ GLOBAL contrib/libs/libpq/src/include
+ contrib/libs/libpq/src/common
+ contrib/libs/libpq/src/interfaces/libpq
+ contrib/libs/libpq/src/port
+)
+
+NO_COMPILER_WARNINGS()
+
+NO_RUNTIME()
+
+CFLAGS(
+ -DFRONTEND
+ -DUNSAFE_STAT_OK
+ -D_POSIX_PTHREAD_SEMANTICS
+ -D_REENTRANT
+ -D_THREAD_SAFE
+)
+
+SRCS(
+ src/common/archive.c
+ src/common/base64.c
+ src/common/checksum_helper.c
+ src/common/compression.c
+ src/common/config_info.c
+ src/common/controldata_utils.c
+ src/common/cryptohash_openssl.c
+ src/common/d2s.c
+ src/common/encnames.c
+ src/common/exec.c
+ src/common/f2s.c
+ src/common/fe_memutils.c
+ src/common/file_perm.c
+ src/common/file_utils.c
+ src/common/hashfn.c
+ src/common/hmac_openssl.c
+ src/common/ip.c
+ src/common/jsonapi.c
+ src/common/keywords.c
+ src/common/kwlookup.c
+ src/common/link-canary.c
+ src/common/logging.c
+ src/common/md5_common.c
+ src/common/percentrepl.c
+ src/common/pg_get_line.c
+ src/common/pg_lzcompress.c
+ src/common/pg_prng.c
+ src/common/pgfnames.c
+ src/common/protocol_openssl.c
+ src/common/psprintf.c
+ src/common/relpath.c
+ src/common/restricted_token.c
+ src/common/rmtree.c
+ src/common/saslprep.c
+ src/common/scram-common.c
+ src/common/sprompt.c
+ src/common/string.c
+ src/common/stringinfo.c
+ src/common/unicode_norm.c
+ src/common/username.c
+ src/common/wait_error.c
+ src/common/wchar.c
+ src/interfaces/libpq/fe-auth-scram.c
+ src/interfaces/libpq/fe-auth.c
+ src/interfaces/libpq/fe-connect.c
+ src/interfaces/libpq/fe-exec.c
+ src/interfaces/libpq/fe-lobj.c
+ src/interfaces/libpq/fe-misc.c
+ src/interfaces/libpq/fe-print.c
+ src/interfaces/libpq/fe-protocol3.c
+ src/interfaces/libpq/fe-secure-common.c
+ src/interfaces/libpq/fe-secure-openssl.c
+ src/interfaces/libpq/fe-secure.c
+ src/interfaces/libpq/fe-trace.c
+ src/interfaces/libpq/libpq-events.c
+ src/interfaces/libpq/pqexpbuffer.c
+ src/port/bsearch_arg.c
+ src/port/chklocale.c
+ src/port/getpeereid.c
+ src/port/inet_net_ntop.c
+ src/port/noblock.c
+ src/port/path.c
+ src/port/pg_bitutils.c
+ src/port/pg_crc32c_sb8.c
+ src/port/pg_strong_random.c
+ src/port/pgcheckdir.c
+ src/port/pgmkdirp.c
+ src/port/pgsleep.c
+ src/port/pgstrcasecmp.c
+ src/port/pgstrsignal.c
+ src/port/pqsignal.c
+ src/port/qsort.c
+ src/port/qsort_arg.c
+ src/port/quotes.c
+ src/port/snprintf.c
+ src/port/strerror.c
+ src/port/tar.c
+ src/port/thread.c
+)
+
+IF (ARCH_X86_64)
+ SRCS(
+ src/port/pg_crc32c_sse42.c
+ src/port/pg_crc32c_sse42_choose.c
+ )
+ENDIF()
+
+IF (OS_WINDOWS)
+ ADDINCL(
+ contrib/libs/libpq/src/include/port
+ contrib/libs/libpq/src/include/port/win32
+ contrib/libs/libpq/src/include/port/win32_msvc
+ )
+ SRCS(
+ src/interfaces/libpq/pthread-win32.c
+ src/interfaces/libpq/win32.c
+ src/port/dirmod.c
+ src/port/inet_aton.c
+ src/port/open.c
+ src/port/win32common.c
+ src/port/win32error.c
+ src/port/win32gettimeofday.c
+ src/port/win32ntdll.c
+ src/port/win32setlocale.c
+ src/port/win32stat.c
+ )
+ENDIF()
+
+END()